Extremely confused about the role of triple pointers - c

int main()
{
char** subject_array;
char** courses_array;
initialize(subject_array, courses_array);
}
void initialize(char*** subject_array, char*** courses_array)
{
int i;
*subject_array = (char**) malloc(100 * sizeof(char*)); // 100 char pointers
*courses_array = (char**) malloc(100 * sizeof(char*));
for(i = 0; i < 100; i++) //malloc for subject_array
{
(*subject_array)[i] = (char*) malloc(4 * sizeof(char)); // 4 chars for each
(*courses_array)[i] = (char*) malloc(6 * sizeof(char)); // char pointer
}
} //void initialize
My question is: Why is there a discrepancy between the declared double pointers in main and the triple pointers in the initialize function? I think the triple pointer allows me to modify where the 2d array points.
My assignment gives these requirements:
Since you will be changing to where the pointers point, this will involve triple pointers for subjects and
courses!
The above code takes care of bolded requirement but I have absolutely no idea what this even means.
Can someone break it down to me? Does that mean I can modify contents of the 2d arrays of subject_array and courses_array? Such as swapping?
But I can do that already with just double pointers making a 2d array! WHY triple pointers?

First of all, the code is incorret, because initialize asks for char***'s and main gives it char**'s. To add another "pointer level", you take the address of whatever you want to give it to. So, the last line of main shall read initialize(&subject_array, &courses_array) (or shall it be return 0?)
After all, if you don't need to modify the variable subject_array and courses_array themselves, not what they point to, you may remove those pointers. And you actually do modify those variables themselves by means of *var = malloc(...). And, as I already noted, the only problem is that the arguments to initialize are char***, char***, not char**, char** as main is doing.

Related

If I am reducing the size of a char ** pointer using realloc, does it internally frees up the individual char * pointers of the reduction size

I am trying to reduce the size of a char ** double pointer using realloc.
First the char ** pointer is allocated using malloc and then the individual char* pointers as given below.
char **first= (char**)malloc(num*sizeof(char*));
char **last=(char**)malloc(num*sizeof(char*));
for(int i=0;i<num;i++)
{
//each individual pointer holds 20 characters
first[i]=(char*)malloc(20*sizeof(char));
last[i]=(char*)malloc(20*sizeof(char));
}
Now after some operations, I want to reduce the size of first and last by one counter value where counter is less than num.
Purpose is to free last counter number of records.
If I do the following
//Freeing up internal pointer memories
i = 0;
while (i<counter)
{
free(first[num1-1 - i]);
free(last[num1-1-i]);
i++;
}
//Reducing the size of the double pointer using realloc
first = (char **)realloc(first, (num1-counter) * sizeof(char *));
last = (char **)realloc(last, (num1-counter) * sizeof(char *) );
After this if I print the records
for(i=0; i<num - counter; i++){
printf("First Name: %s ",first[i]);
printf("Last Name: %s ",last[i]);
}`
The last record seems to be corrupted.
If I just perform the following and do not free the individual char * pointers, it works fine.
first = (char **)realloc(first, (num1-counter) * sizeof(char *));
last = (char **)realloc(last, (num1-counter) * sizeof(char *) );
My question is does realloc of a double pointer to reduce the size, internally frees up the internal pointers and as I am doing both, it is some how corrupting the memory?
To answer your question: No, it doesn't.
Freeing the nested pointers in a char ** might be rude if the pointer is still in use somewhere else.
The C compiler doesn't follow memory pointers around, nor does it count object references, so it's up to you to free (or keep) the allocated memory of the nested strings within the char **.
As for the example code itself, it seems to have issues, but these were described in the comments to your question.

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

Changing a static array to a dynamic one with minimal changes?

I have a C code that creates an array of char pointers as the following:
char* arr[100];
I use each element in this array to point to some string that is being calculated by another function. So basically arr[0] would point to string1 and arr[1] to string2, etc.
This works just fine. However I'm now asked to be more flexible by having the user to specify the number of strings as a parameter.
How can I do this with minimal changes to my code? I understand that I need to use malloc. However I'm getting a lot of warnings in all of the assignment statements I had before. I changed the declaration of the array as the following:
char* arr = (char*)malloc(n * sizeof(char*)); //where n is provided by user
I thought that I only needed to change the declaration. Now all of the assignment statements are giving warnings ("assignment makes integer from pointer without a cast"). The following is an example of an assignment statement:
arr[i] = str; //where str is defined as char* and is calculated by another function
Am I missing something here?
If you're looking to create an array of char *, you need a char **arr. Think of it as an array of char * -- if you had an array of int, you would have int *. Since you have an array of char *s, you need char **.
char** arr = malloc(n * sizeof(char*));
You are declaring arr as a pointer to char: either a single string or, if you prefer, an array of chars.
To allocate an array of pointers, declare arr as
char **arr = malloc(n * sizeof(char *));
By the way, remove the cast: it is unnecessary in C. See also Question 7.7 in the comp.lang.c FAQ.
Don't forget that string is an array too (char *), so u will need array of pointers, which should look like this:
char** arr = (char**)malloc(n * sizeof(char*));
you want to declare arr as as char ** since you are pointing to an array of pointers. If you declare arr only as char * (not char ** or char *[]) you only have one "string".

How do I allocate memory for a pointer to an array of char *?

Could someone please explain how to correctly allocate memory for for a pointer to an array of pointer of characters in c? For example:
char *(*t)[];
I try to do it like this:
*t = malloc( 5 * sizeof(char*));
This gives me a compile error:
error: invalid use of array with unspecified bounds
Any assistance on this would be great! Thanks
What you can do is:
char **t = (char**)malloc( <no of elements> * sizeof(char*));
That allocates the array of pointers.
for (i = 0 ; i< <no of elements> ; i++)
{
t[i] = (char*)malloc( <length of text> * sizeof(char));
}
That allocates memory for the text that each element of the array points to.
When people say "a pointer to an array of X", usually they really mean a pointer to the first element of an array of X. Pointer-to-array types are very clunky to use in C, and usually only come up in multi-dimensional array usage.
With that said, the type you want is simply char **:
char **t = malloc(num_elems * sizeof *t);
Using a pointer-to-array type, it would look like:
char *(*t)[num_elems] = malloc(sizeof *t);
Note that this will be a C99 variable-length array type unless num_elems is an integer constant expression in the formal sense of the term.
Well it depends how you want it to be allocated, but here is one way.
char** myPointer = malloc(sizeof(char *) * number_Of_char_pointers)
int i;
for(i = 0; i < number_Of_char_pointers; i++)
{
myPointer[i] = malloc(sizeof(char) * number_of_chars);
}
something to note is that myPointer[i] is almost exactly identical to saying *(myPointer + i), when being used to dereference a variable, not during initialization.
Try this:
int main()
{
char** a = new char* [100];
delete []a;
return 0;
}

How do I dynamically allocate an array of strings in C?

If I have the number of items in a var called "totalstrings" and a var called "string size" that is the string size of each item, how do I dynamically allocate an array called "array?"
This is an array of strings in C, not C++.
Thanks!
NOTE: My examples are not checking for NULL returns from malloc()... you really should do that though; you will crash if you try to use a NULL pointer.
First you have to create an array of char pointers, one for each string (char *):
char **array = malloc(totalstrings * sizeof(char *));
Next you need to allocate space for each string:
int i;
for (i = 0; i < totalstrings; ++i) {
array[i] = (char *)malloc(stringsize+1);
}
When you're done using the array, you must remember to free() each of the pointers you've allocated. That is, loop through the array calling free() on each of its elements, and finally free(array) as well.
The common idiom for allocating an N by M array of any type T is
T **a = malloc(N * sizeof *a);
if (a)
for (i = 0; i < N; i++)
a[i] = malloc(M * sizeof *a[i]);
As of the 1989 standard, you don't need to cast the result of malloc, and in fact doing so is considered bad practice (it can suppress a useful diagnostic if you forget to include stdlib.h or otherwise don't have a prototype for malloc in scope). Earlier versions of C had malloc return char *, so the cast was necessary, but the odds of you having to work with a pre-1989 compiler are pretty remote at this point. C++ does require the cast, but if you're writing C++ you should be using the new operator.
Secondly, note that I'm applying the sizeof operator to the object being allocated; the type of the expression *a is T *, and the type of *a[i] is T (where in your case, T == char). This way you don't have to worry about keeping the sizeof expression in sync with the type of the object being allocated. IOW, if you decide to use wchar instead of char, you only need to make that change in one place.
char** stringList = (char**)malloc(totalStrings * sizeof(char*));
for( i=0; i<totalStrings; i++ ) {
stringList[i] = (char*)malloc(stringSize[i]+1);
}
I know this question is old and was already answered. I just want to point out that malloc is a system call and shouldn't be used multiple times.
It would be better to allocate one big chunk of memory and make the array point to it. Something like this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_SIZE 100 //STR_SIZE doesn't have to be a constant
int main(){
int i;
char **arr;
char *long_string;
long_string = (char *)malloc(sizeof(char)*STR_SIZE*10);
arr = malloc(sizeof(char *)*10);
//Pointing each item of the array to an allocated memory.
for (i=0; i<10; i++){
arr[i] = (long_string + STR_SIZE * i);
}
//Initialising the array
for (i=0; i<10; i++){
strcpy(arr[i], "This is a line in a\
paragraph\n");
}
//Printing the items of the array
for (i=0; i<10; i++){
printf("%s \n", arr[i]);
}
//freeing the allocated memory
free(long_string);
free(arr);
return 0;
}
Well, first you might want to allocate space for "array", which would be an array of char * that is "totalstrings" long.
What would then be the starting and final indexes in "array"? You know the first one is 0; what's the last one?
Then, for each entry in "array", you could (if you wanted) allocate one area of memory that is "stringsize+1" (why +1, pray tell me?) long, putting the starting address of that area -- that string -- into the correct member of "array."
That would be a good start, imo.

Resources