C语言 当声明一个数组形式的双指针时,为什么因为它是一个指针数组而不需要加括号?

x8diyxa7  于 2022-12-17  发布在  其他
关注(0)|答案(2)|浏览(133)
#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
}

在这段代码中,我们必须最后得到一个shopping,然后打印出candy在购物清单中出现的次数。为了做到这一点,我们必须分配足够的内存来保存用户希望在购物清单中出现的单词(字符串)。然后,为每个项目分配足够的内存来存储单词。

这份声明对我来说毫无意义

**char** stringArray; **

根据我的理解,双指针是一个数组,数组中的元素包含一个指向字符串地址的指针。
因此,我认为我们必须像这样声明双指针:

字符串数组[];

像这样的东西,但那是行不通的

所以我想知道如果我们不加括号代码怎么知道它是一个指针数组

我试着用数组声明双指针,但无法让它工作,也不能弄清楚它是否可能。

dbf7pr2w

dbf7pr2w1#

指针是指针,数组是数组。然而,当C语言中的数组被用于表达式或作为参数传递给函数时,它会“衰减”为指向数组第一个元素的指针。这反过来又使指针运算和[]索引运算符的方便使用成为可能。
这也意味着在大多数情况下,指向第一个元素的指针可以用来代替数组,如果我们有一个指针数组char* arr[n];,那么char**可以用来指向第一个元素,然后从那里指向数组的其余部分。
所以如果你想写一个像int DetermineNumberOfCandy(int numFoods, char* list[numFoods]);这样的函数,这是很好的和有效的C语言,但是list无论如何都会“衰减”成一个指向第一个元素的指针,所以它100%等价于
int DetermineNumberOfCandy(int numFoods, char** list);
你的代码中也有其他的错误。

  • 由于AllocateItem是分配有效内存位置的对象,因此main中的stringArray[i]()必须先赋值给这个内存位置,然后才能使用它。因为在此之前,它只是一个指向垃圾的未初始化指针。因此,您不能strcpy(stringArray[i], words)。请记住,该函数不仅仅分配了一块内存,而且用有效的数据填充了它。所以设置指针指向那个数据就足够了,不需要复制任何东西。

word变量没有任何用途,您还可以编写以下内容:

for(int i=0; i < foods; i++){
  stringArray[i] = AllocateItem();
}
  • 类似地,free(words)是错误的,这将只释放最后分配的内存。对于每个malloc调用,您必须有一个对应的free调用!因此它应该是:
for(int i=0; i < foods; i++){
  free(stringArray[i]);
}
free(stringArray);
wfsdck30

wfsdck302#

当你像这样声明一个字符串变量时:字符串[10];你的计算机实际上声明了一个指针,但是分配了足够的内存来自动保存10个字符,你会看到如果你解引用它,你会得到你的字符串的第一个字符。
关于你的strcpy在第20行不起作用,if不起作用,因为你在for循环中创建了i变量,当你这样做的时候,变量在循环结束时消失,所以你不能在代码中的任何地方使用它。
关于你的第40行,你可以用至少两种不同的方式来使用指针,第一种是在函数中传递一个变量作为指针,这样你就不必在函数的末尾返回它,就像这样:

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

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

这里你需要解引用它,但是如果你给指针分配了内存,你现在可以把它当作一个数组来使用,而不用解引用它。
在这里,你只需要释放字符串数组中2的一个指针。要释放所有指针,试试:

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

请告诉我,如果我没有对每件事都很清楚,或者我说的不够清楚

相关问题