Home > Net >  When Declaring a Double Pointer that is an array why is there no need to put brackets because it is
When Declaring a Double Pointer that is an array why is there no need to put brackets because it is

Time:12-13

    #include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** AllocateShoppingList(int numFoods);
char* AllocateItem();
int DetermineNumberOfCandy(char** list, int numFoods);

int main()
{
  
   char** stringArray;// pointer to pointers
   char* words; //pointer to char array
   //1. ask the user how many foods are on their list
   int foods;
   printf("How many foods on the shopping list?\n");
   scanf("%d", &foods);
   //2. call the AllocateShoppingList function and store the result
   stringArray = AllocateShoppingList(foods);   
   //3. for X times (user's previous input), call the AllocateItem function 
   //       and store the result in the list of pointers (step 2)
   for(int i =0;i < foods; i  ){
   words = AllocateItem();
   stringArray[i] = words;}

  //strcpy(stringArray[i],words); why not work?
   
   //4. call the DetermineNumberOfCandy function, and print the result
   printf("Candy appeared this many times: %d\n",DetermineNumberOfCandy(stringArray, foods)); 
   //5. free up all of the pointers that are held by the shopping list
   //6. free up the shopping pointer itself
   free(words);
   free(stringArray);
   
}

int DetermineNumberOfCandy(char** list, int numFoods)
{
   //0. setup a counter variable
   int counter = 0 ;
   //1. for each pointer in the shopping list:
   //1a.   compare the string at the pointer's address to "candy"
   
   for(int i =0; i< numFoods; i  )
   if (strcmp(list[i],"candy")==0)
     // why you dont have to dereference it
     // this concept works with single pointers
     // does it work with double or tripple pointers as long as it orignally points to the string?
     
   counter  ;
   
   //1b.   if it is candy, then tick up the counter variable
   //2. return the counter variable
   return counter;
}

char** AllocateShoppingList(int numFoods)
{
   
   return calloc(numFoods, sizeof(char*));
   //1. allocate memory that can hold X pointers (X = numFoods)
   //2. return the memory address holding this pointer to pointers
}

char* AllocateItem()
{
   char* wordPtr;
   char word[100];
   //1. get a word from the user that is max 100 characters
 
   scanf("%s", word);
   //2. determine how large the word actually is
   wordPtr = calloc(strlen(word) 1,sizeof(char));
   strcpy(wordPtr, word);
   //3. allocate memory that is just enough to hold the word
   return wordPtr;
   //4. copy the user's word into the new memory location
   //5. return the memory address holding the word
}

**For this code we had to get a shopping last and see print out how many times candy was in the shopping list and in order to do that we had to allocates enough memory to hold onto as many words (strings) as the user wants to have on their shopping list. Then, for each item, allocate just enough memory to store the word. **

This declaration right here for me doesn't make sense

**char** stringArray; **

From what I understand the double pointer is an array which element in the array contains a pointer to the string address.

Because of this I would think that we would have to declare the double pointer like:

char stringArray[]; **

something like this but that would not work.

So I wanted to know how the code knows it is an Array of pointers if we never put brackets

I tried declaring the double pointer with an array and could not get it to work nor could figure out if it was even possible.

CodePudding user response:

When you declare a variable like a string like this: char str[10]; Your computer declares in fact a pointer but allocates enough memory to hold 10 characters automaticely. You will see that if you dereference it, you will get the first character of your string.

About your strcpy not working on line 20, if doesnt work because you created your i variable in a for loop and when you do that, the variable disapeers at the end of the loop so you are not able to use it nowhere into your code.

And about your line 40, you can use pointers in at least 2 deferent ways. First one is passing a variabe as a pointer in a function for you to dont have to return it at the end of a function like so:

int main()
{
    int var = 0;
    my_funct(&var);
    //var = 1 now
}

void myfunct(int *var)
{
    *var = 1;
}

Here you need to dereference it but if you allocated memory to your pointer, you can now use it as an array without dereferencing it.

Oh and here, you just free one pointer of the 2 in your stringarray. To free everything, try:

for(int i = 0; i < foods; i  ) {
    free(StringArray[i]);
}
free(StringArray);

Tell me if i didnt awnser to everything or if i was not clear enough

CodePudding user response:

Pointers are pointers, arrays are arrays. However, when an array in C is used in an expression or passed as a parameter to a function, it "decays" into a pointer to the first element of that array. This in turn enables things like a pointer arithmetic and the convenient use of the [] index operator.

This also means that in most contexts, a pointer to the first element can be used in place of an array. If we have an array of pointers char* arr[n]; then a char** can be used to point at the first item, and from there on the rest of the array.

So if you'd write a function like int DetermineNumberOfCandy(int numFoods, char* list[numFoods]); that's fine and valid C, but list "decays" into a pointer to the first element anyway, so it is 100% equivalent to
int DetermineNumberOfCandy(int numFoods, char** list);


Also you have misc bugs in your code.

  • Since AllocateItem is what allocates a valid memory location, the stringArray[i] in main() must be assigned to this memory location before it can be used. Because until then it is just an uninitialized pointer pointing at garbage. Therefore you can't strcpy(stringArray[i], words). Remember that the function did not just allocate a chunk of memory, but also filled it with valid data. So it is sufficient to set the pointer to point at that data, no need to copy anything.

    The word variable doesn't fill any purpose, you could as well write this:

    for(int i=0; i < foods; i  ){
      stringArray[i] = AllocateItem();
    }
    
  • Similarly free(words) is wrong, this would only free the last allocated memory. Rule of thumb: for each malloc call you must have a corresponding free call! Therefore it should be:

    for(int i=0; i < foods; i  ){
      free(stringArray[i]);
    }
    free(stringArray);
    
  • Related