Cannot assign char to char pointer - c

Here is my code:
printf("%s\n", "test1");
char c = '2';
char * lines[2];
char * tmp1 = lines[0];
*tmp1 = c;
printf("%s\n", "test2");
I don't see the second printf in console.
Question: Can anybody explain me what's wrong with my code?
NOTE: I'm trying to learn C :)

This line:
char * lines[2];
declares an array of two char pointers. However, you don't actually initialize the pointers to anything. So later when you do *tmp1 = (char)c; then you assign the character c to somewhere in memory, possibly even address zero (i.e. NULL) which is a bad thing.
The solution is to either create the array as an array of arrays, like
char lines[2][30];
This declares lines to have two arrays of 30 characters each, and since strings needs a special terminator character you can have string of up to 29 characters in them.
The second solution is to dynamically allocate memory for the strings:
char *lines[2];
lines[0] = malloc(30);
lines[1] = malloc(30);
Essentially this does the same as the above array-of-arrays declaration, but allocates the memory on the heap.
Of course, maybe you just wanted a single string of a single character (plus the terminator), then you were almost right, just remove the asterisk:
char line[2]; /* Array of two characters, or a string of length one */

The array lines in uninitialized. Thus lines[0] is an uninitalized pointer. Dereferencing it in *tmp1 is sheer undefined behaviour.
Here's an alternative, that may or may not correspond to what you want:
char lines[2];
char * tmp1 = lines; // or "&lines[0]"
*tmp = c;
Or, more easily:
char lines[2] = { c, 0 };

lines is uninitialized, and tmp1 initialization is wrong.
It should be:
char lines[2];
char * tmp1 = lines;
Alternatively, you can say:
char * tmp1 = &lines[0];
Or else for an array of strings:
char lines[2][30];
char * tmp1 = lines[0];

The line
char * lines[2];
creates an array of two char pointers. But that doesn't allocate memory, it's just a "handle" or "name" for the pointer in memory. The pointer doesn't point to something useful.
You will either have to allocate memory using malloc():
char * lines = malloc(2);
or tell the compiler to allocate memory for you:
char lines[2];
Note: Don't forget to terminate the string with a 0 byte before you use it.

char *lines[2]; : A two element array of char pointers.
char *tmp; : A pointer to a character.
char *tmp = lines[0] : The value inside the array element 0 of the lines array is transferred into tmp. Because it is an automatic array, therefore it will have garbage as the value for lines[0].
*temp : Dereference the garbage value. Undefined Behaviour.

char * tmp1 = lines[0];
here you declare a char pointer and initialize its pointer value to line[0],the fist element stored in line array which is also uninitialized.
now the tmp is pointing to somewhere unknown and not actually accessible. When you
*tmp1 = (char)c;
you are operating on a invalid memory address which causes a Segmentation fault.

Related

Why should I declare a String as a fixed-size array

I have this program:
#include<stdio.h>
void copy_string(char string1[], char string2[]){
int counter=0;
while(string1[counter]!='\0'){
string2[counter] = string1[counter];
counter++;
}
string2[counter] = '\0';
}
int main() {
char* myString = "Hello there!";
char* myStringCopy;
copy_string(myString, myStringCopy);
printf("%s", myStringCopy);
}
My question is, why isn't it working unless I declare myStringCopy as a fixed-size variable (char myStringCopy[12];)? Shouldn't it work if I add a \0 character after the copy as I'm doing?
It can work by doing char* myStringCopy as long as you allocate memory space for it.
for example
char* myStringCopy
myStringCopy = malloc(sizeof(char) * (strlen(myString)+1))
I might be mistaken about the +1 but I think it is like this.
char myStringCopy[12]; tells the compiler to create an array of 12 char. When myStringCopy is passed to copy_string, this array is automatically converted to a pointer to its first element, so copy_string receives a pointer to the characters.
char *myStringCopy; tells the compiler to create a pointer to char. The compiler creates this pointer, including providing memory for it, but it does not set the value of the pointer. When this pointer is passed to copy_string, copy_string does not receive a valid value.
To make char *myStringCopy; work, you must allocate memory (which you can do with malloc). For example, you could use:
char *myStringCopy;
myStringCopy = malloc(13 * sizeof *myStringCopy);
if (myStringCopy == NULL)
{
fprintf(stderr, "Error, the malloc did not work.\n");
exit(EXIT_FAILURE);
}
Also, note that 12 is not enough. The string “Hello there!” contains 12 characters, but it also includes a terminating null character. You must provide space for the null character. char myStringCopy[12]; appeared to work, but copy_string was actually writing a thirteenth character beyond the array, damaging something else in your program.
The problem is that you don't have room for mystringCopy
You need to reserve space first:
char* myString = "Hello there!";
char* myStringCopy = malloc(strlen(myString) + 1);
char* myStringCopy;
This is only pointer to char*. You must first allocate memory for myStringCopy, before start copy. When you declare it like this:
char myStringCopy[12];
compiler allocate enough memory in stack.

How to set a char 'a' to a char pointer array?

I'm trying to figure out how to use pointers.
I'm confused on how to insert an individual char to the char *line2[80]
Is this even possible to do this without referencing the memory location of another pointer?
My thought process is that at *line2[0] = 'a' the character 'a' will be at index 0 of the array.
How is this different from line[0] = 'a'
#include <stdio.h>
void returnValue(void);
int main(void){
returnValue();
}
void returnValue(){
char line[80];
line[0] = 'a';
line[1] = '\0';
printf("%s",line);
char* line2[80];
*line2[0] = 'a';
*line2[1] = '\0';
printf("%s",*line2); //program crashes
}
When you allocate
char* line2[80];
You are allocating an array of 80 character pointers.
When you use
*line2[0] = 'a';
You are referencing undefined behaviour. This is because you are allocating the pointer line2[0], but the pointer is not initialized and may not be pointing to any valid location in memory.
You need to initialize the pointer to some valid location in memory for this to work. The typical way to do this would be to use malloc
line2[0] = malloc(10); // Here 10 is the maximum size of the string you want to store
*line2[0] = 'a';
*(line2[0]+1) = '\0';
printf("%s",*line2);
What you are doing in the above program is allocating a 2D array of C strings. line2[0] is the 1st string. Likewise, you can have 79 more strings allocated.
you must have already read, a pointer is a special variable in c which stores address of another variable of same datatype.
for eg:-
char a_character_var = 'M';
char * a_character_pointer = &a_character_var; //here `*` signifies `a_character_pointer` is a `pointer` to `char datatype` i.e. it can store an address of a `char`acter variable
likewise in your example
char* line2[80]; is an array of 80 char pointer
usage
line2[0] = &line[0];
and you may access it by writing *line2[0] which will yield a as output

C multidimentional char array - assignment makes integer from pointer without a cast

I create a big 2d char array and want to assign strings to it.
int i;
char **word;
int start_size = 35000;
word=(char **) malloc(start_size*sizeof(char *));
for(i=0;i<start_size;i++)
word[i]=(char *) malloc(start_size*sizeof(char));
word[2][2] = "word";
how do I assign a string?
Explain me why this code doesn't work...
I am new to low level programming and C but experienced in high level programming
You cannot do string assignment in C.
You need to call a function, sepcifically strcpy() (prototype in <string.h>)
#include <string.h>
strcpy(word[2], "word");
word[2][2] = "word";
In the above statement, the string literal "word" is implicitly converted to a pointer to its first element which has type char * whereas word[2][2] has type char. This attempts to assign a pointer to a character. This explains the warning message you have stated -
assignment makes integer from pointer without a cast
You can use string literals only to initialize character arrays. What you need to do is use the standard function strcpy to copy the string literal. Also, you should not cast the result of malloc. Please read this - Do I cast the result of malloc? I suggest the following changes -
int i;
int start_size = 35000;
// do not cast the result of malloc
char **word = malloc(start_size * sizeof *word);
// check word for NULL in case malloc fails
// to allocate memory
for(i = 0; i < start_size; i++) {
// do not cast the result of malloc. Also, the
// the sizeof(char) is always 1, so you don't need
// to specify it, just the number of characters
word[i] = malloc(start_size);
// check word[i] for NULL in case malloc
// malloc fails to allocate memory
}
// copy the string literal "word" to the
// buffer pointed to by word[2]
strcpy(word[2], "word");
You have to decide if you want a list of strings or a 2D array of strings.
A list of string works like this:
char **word;
word = (char**)malloc(start_size*sizeof(char*));
word[2] = "word";
In this example word[2] would be the third string in the list and word[2][1] would be the second character in the third string.
If you want a 2D array of string you have to do this:
int i;
char ***word;
^^^ 3 stars
int start_size = 35000;
word = (char***)malloc(start_size*sizeof(char**));
^^^ 3 stars ^^^ 2 stars
for(i=0;i<start_size;i++)
word[i] = (char**) malloc(start_size*sizeof(char*));
^^^ 2 stars ^^^ 1 star
word[2][2] = "word"; // no it works!
Note that in C you do not need the casts before the malloc. So this would also work:
word = malloc(start_size*sizeof(char**));

Dynamic memory allocation for pointer arrays

I'm am trying to write a program that reads in a series of strings from a text file and stores these in an array of strings, dynamically allocating memory for each element. My plan was to store each string in an array using a pointer and then grow the array size as more were read in. I am having trouble to understand why my test code below is not working. Is this a workable idea?
char *aPtr;
aPtr =(char*)malloc(sizeof(char));
aPtr[0]="This is a test";
printf("%s",aPtr[0]);
In C a string is a char*. A dynamic array of type T is represented as a pointer to T, so for char* that would be char**, not simply a char* the way you declared it.
The compiler, no doubt, has issued some warnings about it. Pay attention to these warnings, very often they help you understand what to do.
Here is how you can start your testing:
char **aPtr;
int len = 1; // Start with 1 string
aPtr = malloc(sizeof(char*) * len); // Do not cast malloc in C
aPtr[0] = "This is a test";
printf("%s",aPtr[0]); // This should work now.
char *str; //single pointer
With this you can store one string.
To store array of strings you Need two dimensional character array
or else array of character pointers or else double pointer
char str[10][50]; //two dimensional character array
If you declare like this you need not allocate memory as this is static declaration
char *str[10]; //array of pointers
Here you need to allocate memory for each pointer
loop through array to allocate memory for each pointer
for(i=0;i<10;i++)
str[i]=malloc(SIZE);
char **str; //double pointer
Here you need to allocate memory for Number of pointers and then allocate memory for each pointer .
str=malloc( sizeof(char *)*10);
And then loop through array allocate memory for each pointer
for(i=0;i<10;i++)
str[i]=malloc(SIZE);
char * aPtr;
is as pointer to a character, to which you allocated memory to hold exactly 1 character.
Doing
aPrt[0] = "test";
you address the memory for this one characters and try to store the address of the literal "test" to it. This will fail as this address most likley is wider then a character.
A fix to your code would be to allocate memory for a pointer to a character.
char ** aPtr = malloc(sizeof(char *));
aPtr[0] = "test";
printf("%s", aPtr[0]);
Are more elegant and more over robust approach would be to allocate the same (as well as adding the mandatory error checking) by doing:
char ** aPtr = malloc(sizeof *aPtr);
if (NULL == aPtr)
{
perror("malloc() failed");
exit(EXIT_FAILURE);
}
...
You are doing it totally wrong. The correct version of your code should be like this:
int main ()
{
char *aPtr;
aPtr =(char*)malloc(20*sizeof(char));
aPtr ="This is a test";
printf("%s",aPtr);
}
You can use pointer array. if you want to store multiple string. Yes I know using for loop will be easy. But I am trying to explain in simple way even a beginner can understand.
int main ()
{
char *aPtr[10];
aPtr[0] =(char*)malloc(20*sizeof(char));
aPtr[0] ="This is a test";
aPtr[1] =(char*)malloc(20*sizeof(char));
aPtr[1] ="This is a test2";
printf("%s\n%s\n",aPtr[0],aPtr[1]);
}

Initializing arrays of type char

I want to initialize arbitrary large strings. It is null terminated string of characters, but I cannot print its content.
Can anybody tell me why?
char* b;
char c;
b = &c;
*b = 'm';
*(b+1) = 'o';
*(b+2) = 'j';
*(b+3) = 'a';
*(b+4) = '\0';
printf("%s\n", *b);
Your solution invokes undefined behaviour, because *(b+1) etc. are outside the bounds of the stack variable c. So when you write to them, you're writing all over memory that you don't own, which can cause all sorts of corruption. Also, you need to printf("%s\n", b) (printf expects a pointer for %s).
The solution depends on what you want to do. You can initialize a pointer to a string literal:
const char *str1 = "moja";
You can initialize a character array:
char str2[] = "moja";
This can also be written as:
char str2[] = { 'm', 'o', 'j', 'a', '\0' };
Or you can manually assign the values of your string:
char *str3 = malloc(5);
str3[0] = 'm';
str3[1] = 'o';
str3[2] = 'j';
str3[3] = 'a';
str3[4] = '\0';
...
free(str3);
This might result in a segmentation fault! *(b+1), *(b+2) etc refer to unallocated areas. First allocate memory and then write into it!
b doesn't have enough space to hold all those characters. Allocate enough space using malloc or declare b as a char array.
Your code is not safe at all! You allocate only 1 char on the stack with char c; but write 5 chars into it! this will give you a stack-overflow which can be very dangerous.
Another thing: you mustn't dereference the string when printing it: printf("%s\n", b);
Why not simply write const char *b = "mojo";?
You need to assign memory space for it, either with malloc or using a static array. Here, in your code, you're using the address of just one character to store at the addresses of that characters, and others following it. This is not defined.
Note, step by step, what you're doing. First, you assign the pointer to point to a single char space in memory. Then, by using *b = 'm' you set that memory to the character 'm'. But then, you access to the next memory position (that is undefined, because no memory is reserved for that position) to store another value. This won't work.
How to do it?
You have two options. For example:
char *b;
char c[5];
b = &c[0];
*b = 'm';
... //rest of your code
This will work because you have space for 5 chars in c. The other option is to directly assign memory for b using malloc:
char * b = (char*) malloc(5);
*b = 'm';
... // rest of your code
Finally, maybe not what you want, but you can either initialize a char array or pointer using a string literal:
char c[] = "hello";
const char* b = "abcdef";
The printf does not print because it expect a char*, so you should pass b, not *b.
To initialize a pointer to a string constant you can do something like:
char *s1 = "A string"
or
char s2[] = "Another string"
or allocate a buffer with char *b = malloc(5) and then write to this buffer (as you did, or with the string functions)
what you did was taking the address of a single char memory location and then write past to it, possibly overwriting other variables or instructions and thus possibly leading to data corruption or crash.
If you write the following instead of your printf, it will print the first character.
printf("%c\n", *b);
In order for you to have arbitrarily large strings, you will need to use a library such as bstring or write one of your own.
This is because, in C one needs to get memory, use it and free it accordingly. b in your case only points to a character unless you allocate memory to it using malloc. And for malloc you have to specify a fixed size.
For arbitrarily large string, you need to encapsulate the actual pointer to character in a data structure of your own, and then manage its size according to the length of the string that is to be set as its value.
printf("%s\n", *b);
why *?
printf("%s\n", b);
is what you want

Resources