Dynamic memory allocation for pointer arrays - c

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]);
}

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.

char* leads to segfault but char[] doesn't [duplicate]

This question already has answers here:
Difference between char[] and char * in C [duplicate]
(3 answers)
Closed 7 years ago.
I think I know the answer to my own question but I would like to have confirmation that I understand this perfectly.
I wrote a function that returns a string. I pass a char* as a parameter, and the function modifies the pointer.
It works fine and here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void get_file_name(char* file_name_out)
{
char file_name[12+1];
char dir_name[50+12+1];
strcpy(file_name, "name.xml");
strcpy(dir_name, "/home/user/foo/bar/");
strcat(dir_name, file_name);
strcpy(file_name_out, dir_name); // Clarity - equivalent to a return
}
int main()
{
char file_name[100];
get_file_name(file_name);
printf(file_name);
return 0;
}
But if I replace char file_name[100]; by char *filename; or char *filename = "";, I get a segmentation fault in strcpy().
I am not sure why ?
My function takes a char* as a parameter and so does strcpy().
As far as I understand, char *filename = ""; creates a read-only string. strcpy() is then trying to write into a read-only variable, which is not allowed so the error makes sense.
But what happens when I write char *filename; ? My guess is that enough space to fit a pointer to a char is allocated on the stack, so I could write only one single character where my file_name_out points. A call to strcpy() would try to write at least 2, hence the error.
It would explain why the following code compiles and yields the expected output:
void foo(char* a, char* b)
{
*a = *b;
}
int main()
{
char a = 'A', b = 'B';
printf("a = %c, b = %c\n", a, b);
foo(&a, &b);
printf("a = %c, b = %c\n", a, b);
return 0;
}
On the other hand, if I use char file_name[100];, I allocate enough room on the stack for 100 characters, so strcpy() can happily write into file_name_out.
Am I right ?
As far as I understand, char *filename = ""; creates a read-only
string. strcpy() is then trying to write into a read-only variable,
which is not allowed so the error makes sense.
Yes, that's right. It is inherently different from declaring a character array. Initializing a character pointer to a string literal makes it read-only; attempting to change the contents of the string leads to UB.
But what happens when I write char *filename; ? My guess is that
enough space to fit a pointer to a char is allocated on the stack, so
I could write only one single character into my file_name_out
variable.
You allocate enough space to store a pointer to a character, and that's it. You can't write to *filename, not even a single character, because you didn't allocate space to store the contents pointed to by *filename. If you want to change the contents pointed to by filename, first you must initialize it to point to somewhere valid.
I think the issue here is that
char string[100];
allocates memory to string - which you can access using string as pointer
but
char * string;
does not allocate any memory to string so you get a seg fault.
to get memory you could use
string = calloc(100,sizeo(char));
for example, but you would need to remember at the end to free the memory with
free(string);
or you could get a memory leak.
another memory allocation route is with malloc
So in summary
char string[100];
is equivalent to
char * string;
string = calloc(100,sizeo(char));
...
free(string);
although strictly speaking calloc initializes all elements to zero, whereas in the string[100] decalaration the array elements are undefined unless you use
string[100]={}
if you use malloc instead to grad the memory the contents are undefined.
Another point made by #PaulRooney is that char string[100] gives memory allocation on the stack whereas calloc uses the heap. For more information about the heap and stack see this question and answers...
char file_name[100]; creates a contiguous array of 100 chars. In this case file_name is a pointer of type (char*) which points to the first element in the array.
char* file_name; creates a pointer. However, it is not initialized to a particular memory address. Further, this expression does not allocate memory.
char *filename;
Allocate nothing. Its just a pointer pointing to an unspecified location (the value is whatever was in that memory previously). Using this pointer will never work as it probably points outside the memory range your program is allowed to use.
char *filename = "";
Points to a piece of the programs data segment. As you already said it's read only and so attempting to change it leads to the segfault.
In your final example you are dealing with single char values, not strings of char values and your function foo treats them as such. So there is no issue with the length of buffers the char* values point to.

C strings by reference voodoo

I am a novice programmer and I hagly appreciate any advice with my problem here.
I've made a procedure that gets a string in buffer and parses it in three cunks, separated by the first 2 ";".
What I tried to do is to pass 3 char pointers in where I will store my parsed string. But all I got in the calling function is memory garbage. What am I doing wrong?
void parseomensaje(char buf[256], char **idNodo, char **idMensaje, char **mensaje){
char *temp;
temp=(char *)malloc(sizeof(buf));
strcpy(temp, buf);
printf("\ntemp adentro de la funcion = %s\n", temp);
idNodo = strtok (temp,";");
idMensaje = strtok (NULL, ";");
mensaje = strtok (NULL, "\0");
printf("\nADENTRO\nidNodo: %s\nidMensaje: %s\nmensaje: %s", idNodo, idMensaje, mensaje);
}
this function is called this way:
char *idnod=NULL;
char *idmen=NULL;
char *men=NULL;
idnod=(char *)malloc(sizeof(buffer));
idmen=(char *)malloc(sizeof(buffer));
men=(char *)malloc(sizeof(buffer));
parseomensaje (buffer, &idmen, &idnod, &men);
after parseomensaje is executed buffer contains its original string, but idmen, idnod and men are blank.
I was reading from tutorials that pointers names are pointers itself, so it is the same thing as passing a parameter by reference, but in case of a string I need to pass the pointer address to a pointer to pointer...
I was reading it from here, but I'm still trying to figure it out.
PD: I apologize for my English, please feel free to point any mistakes in my writing. :)
This is incorrect:
char *temp;
temp=(char *)malloc(sizeof(buf));
as the array will degrade to a char* within the function, so only sizeof(char*) bytes are being allocated (typically 4 or 8 bytes). If the actually length of buf is greater than 4 or 8 bytes then the program has undefined behaviour as the strcpy() will be writing beyond the bounds of the array. Basically:
void parseomensaje(char buf[256], char **idNodo, char **idMensaje, char **mensaje){
is equivalent to:
void parseomensaje(char* buf, char **idNodo, char **idMensaje, char **mensaje){
If you are, as you say, a novice programmer I would recommend avoiding dynamic memory allocation until you get more comfortable with the language. Modify the program to use fixed sized arrays instead of dynamically allocated memory (and prevent writing beyond the bounds of the arrays). Once you have that working and fully understand it then attempt to use dynamically allocated memory.
First of all you have multiple memory leaks in your program. Consider freeing every single memory chunk you've allocated thanks to malloc once you don't need them anymore.
As regard your function:
void parseomensaje(char buf[256], char **idNodo, char **idMensaje, char **mensaje)
Why do you pass char** pointers on your function? Pass char* instead. Because strtok is declared this way:
char *strtok(char *str, const char *delim);
Moreover, you don't need to allocate any memory before calling parseomensaje since strtok returns a pointer on your own memory, not new allocated one.

Cannot assign char to char pointer

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.

memory allocation for array of pointers

I need to allocate memory for a pointer which needs to be used as a 2d array.I know how to allocate memory for char pointers and int pointers I am confused how memory is allocated of a array of pointers.A pictorial representation of the reason would be very helpful,also is the code below fine?
char *names[5];
for(i=0;i<5;i++)
{
names[i]=(*char)malloc(sizeof(char));
}
No, this is not because you are allocating the array assuming a dimension of just 1 element of primitive type char (which is 1 byte).
I'm assuming you want to allocate 5 pointers to strings inside names, but just pointers.
You should allocate it according to the size of the pointer multiplied by the number of elements:
char **names = malloc(sizeof(char*)*5);
You don't need to allocate them one by one with a loop. Note that you need to specify that it is a pointer-of-pointers by using **
What you're doing is allocating space for 5 chars. You could write this and it'll have the same result:
char *names = (char *)malloc(sizeof(char) * 5);
If you want to have an array of pointers, I think this'd be the best code
char **names = (char **)malloc(sizeof(char *) * 5);
I'm not a super-coder, but as what I now, this is the right solution.
Also, in short you can do the following too in this case for allocating storage for five characters
names = (char*)malloc(5 * sizeof(char))
Emphisizing what Jack said in in the end: his code works only if the array is declared as a pointer-of-pointers by using **.
When the array is declared as
char *names[5];
I guess the right way of allocating memory is almost as Ak1to did, but multiplying by the wanted size of the string of chars:
char *names[5];
for(i=0;i<5;i++)
{
names[i]=(char *)malloc(sizeof(char)*80);
}
else the compiler throws an error about incompatible types.

Resources