gpt4 book ai didi

c - 局部指针数组问题

转载 作者:太空宇宙 更新时间:2023-11-04 04:19:01 24 4
gpt4 key购买 nike

我做了一些调查,但找不到解决办法。在下面的代码中,当我将float **array声明为全局变量时,我的程序按预期运行。然而,我试图在main()中声明它并将其传递到函数中,并且在尝试编译时遇到了一些令人讨厌的错误。
样本运行如下:

lab2.c: In function ‘NumOfVal’:
lab2.c:116: error: incompatible types when assigning to type ‘float’ from type ‘void *’
lab2.c:118: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:119: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:124: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:125: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘calculateSum’:
lab2.c:137: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:140: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘calculateAvg’:
lab2.c:150: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:153: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘findMax’:
lab2.c:162: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:165: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:166: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘findMin’:
lab2.c:174: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:175: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:177: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:178: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘printVal’:
lab2.c:187: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:189: error: invalid type argument of ‘unary *’ (have ‘float’)

现在我意识到我的“计算函数”的错误都是一样的,但是第116行的第一个错误是不同的。我不明白为什么一旦我在 main()中局部声明指针,它就会给我带来所有这些问题。我不得不使用指针算术,看不出语句是如何:
*(array + index) = malloc();

不再有效。。
为什么本地声明会更改分配内存和读取/写入数组的语法??
代码如下:我不包括一些“计算功能”以节省空间
/* Function declarations */
void printVal();
void userChoice();
void calculateSum();
void calculateAvg();
void findMin();
void findMax();

int main(){

float **array;
int numData;

/*get number of datasets */
numData = NumOfSet();
printf("%d\n",numData);
array = malloc(numData * sizeof(float*));
if(array != 0){
/* get # of values per dataset and enter those values */
NumOfVal(numData, array);
}
else{
printf("Memory Allocation Failed");
}

userChoice();
}


void userChoice(){

int flag = 1;
int setChoice;
int opChoice;
while(1){
if(flag == 0)
break;

printf("Which dataset would you like to perform operations on?: \n");
scanf("%d", &setChoice);
printf("Which operation would you like to perform on dataset #%d\n", setChoice);
printf("1. Calculate sum of all the values\n");
printf("2. Calculate average of all the values\n");
printf("3. Find the minimum value\n");
printf("4. Find the maximum value\n");
printf("5. Print values in dataset\n");
printf("6. Exit the program\n");

scanf("%d", &opChoice);
/* Switch statement which makes function calls to perform whatever the user specified */
switch(opChoice){
case 1:
calculateSum(setChoice);
break;
case 2:
calculateAvg(setChoice);
break;
case 3:
findMin(setChoice);
break;
case 4:
findMax(setChoice);
break;
case 5:
printVal(setChoice);
break;
case 6:
flag = 0;
printf("Thanks for playing!\n");
printf("%d", flag);
}
}
}




int NumOfSet(){
int numData;
printf("Enter number of Datasets: \n");
scanf("%d",&numData);
return(numData);

}


/* for each data set declare size and input float values */
int NumOfVal(int data, float *array){
int index; /* counters */
int array_index;
int copy;
float size;
float val;

for(index = 0; index < data;index++){
printf("Enter size of dataset %d:\n", index);
scanf("%f", &size);
copy = size;
printf("Size = %d\n", (int) size);
printf("Array #: %d\n", index);
/* malloc() for row */
/* array[index] */
*(array + index) = malloc(size * sizeof(float));
/*array[index][0] */
*(*(array + index) + 0) = size;
printf("%f\n", *(*(array + index) + 0));
/* loop for entering float values */
for(array_index = 1; array_index <= copy; array_index++){
printf("Enter each float value:");
scanf("%f", &val);
*(*(array + index) + array_index) = val;
printf("%f\n", *(*(array + index) + array_index));
printf("count: %d\n",array_index);
printf("size: %d\n",copy);

}

}

}

void calculateSum(int setChoice, float *array){
int i;
int first = *(*(array + setChoice-1) + 0);
float sum = 0;
for(i = 1; i <= first; i++){
sum += *(*(array + setChoice-1) + i);
}
printf("The sum of the values is: %.3f\n", sum);
}

当然,当我声明array为global时,我没有array作为这些函数的参数。
因此,如果我声明指向 floatfloat **array main()的指针,则似乎是这样。我需要把 float **array作为函数的参数,而不仅仅是 float *array
**array-->指向 float数组列表的指针(?)
*array-->只是指向单个 float数组的指针(?)
如果我错了请纠正我

最佳答案

首先你要明白什么是指针。指针是变量
存储地址。它可能是另一个变量的地址,也可能是
从动态分配内存中获得的内存块的开始
malloc&friends或数组的开始。
*array-->只是指向单个float数组的指针(?)
不一定。
我们来看看这个:

float *array;

首先,忘记变量的名称,真正重要的是
变量的类型。在本例中,您有一个指向 float的指针。
它可能指向单个浮点变量
float n = 8.7;
float *array = &n;

但它也可能指向 floats序列(aka数组)的开始:
float na[] = { 1.1, 2.2, 3.3, 4.4 };
float *array = na;
//or
float *array = na + 2;

哪一个(指向单个对象vs指向一个对象数组)是
正确的取决于上下文。函数的文档将显示
你是它所期待的。这才是最重要的,而不是变量名。如果
变量名是 array,它可能没有指向数组,然后
误导,实际上是一个选择不当的名字。
**array-->指向 float数组列表的指针(?)
再说一遍,不一定。
让我们更进一步。双指针
float **array;

是指向另一个 float指针的指针。再一次,忘记
变量的名称、上下文很重要。它可能指向一个指针
指向单个变量:
float n = 8.7;
float *array = &n;
float **p2arr = &array;

或者它可以指向指向数组开头的指针
float na[] = { 1.1, 2.2, 3.3, 4.4 };
float *array = na;
float **p2arr = &array;

// *p2arr[0] == 1.1
// *(p2arr[0] + 1) == 2.2
// *(p2arr[0] + 2) == 3.3

或者它可以指向指向单个 float值的指针数组:
float a=1.1, b=2.2, c=3.3;
float **ppa = calloc(3, sizeof *ppa);

ppa[0] = &a;
ppa[1] = &b;
ppa[2] = &b;

如果指针指向 float的数组,则它可能指向数组
价值观:
float **ppa = calloc(3, sizeof *ppa);

ppa[0] = calloc(5, sizeof *ppa[0]);
ppa[1] = calloc(2, sizeof *ppa[1]);
ppa[2] = calloc(9, sizeof *ppa[2]);

ppa[0][0] = 1.1;
ppa[0][1] = 2.2;

ppa[1][0] = 10.8;

ppa[2][5] = 11.1;

上下文很重要,如果您使用的函数 float **arg
参数,函数文档将告诉您
一个指针。如果你在创建一个函数,你决定上下文,
因为你知道你在做什么。
关于你的代码。据我所见, float **array;中的 main分配
指针数组的内存。在这种情况下,我建议使用 calloc
相反,因为 calloc将分配的内存设置为0。它使初始化
即使随后调用
malloc/ realloc/ calloc失败。
array = calloc(numData, sizeof *array);

另外请注意,这里我没有使用 sizeof(float*),而是使用 sizeof *array
前者是不正确的,但更容易犯遗忘之类的错误
*或添加超出需要的内容,特别是当
处理双指针。但后者总是返回正确的
大小,与类型无关。
现在数组被分配和初始化。所有指针 array[0]
array[1]等初始化并指向 NULL。你的电话
NumOfVal(numData, array);这就是问题所在。
让我们看看函数的签名:
int NumOfVal(int data, float *array);

它需要一个指针,所以这不好,不能传递双指针
指针。既然是你自己写的函数,你可以改变
函数并设置自己的上下文。
在修复函数之前,让我们看看 NumOfVal中的这一行:
*(array + index) = malloc(size * sizeof(float));

在这里,我建议使用 calloc。第二,让我们看看这个:
*(array + index)。这与执行 array[index]相同,并将返回给您
a float。你实际上在做:
float f = malloc(sizeof * sizeof(float));

这是错误的,因为 malloc返回一个 void指针,您不能设置
指向指针。
但是你的思路也错了,因为
float是一个双指针,内存布局不同。为什么?
我将更改变量的名称,以明确我指的是哪个变量。
void与执行 array相同。它还给你
指向 main的指针。当您将 *(array_main + index)传递到 array_main[index]时,您现在是
把它当作一个指针。a float和a array_main的大小
指向 NumOfVal的指针可能不同,因此 floatfloat将返回
不同的内存位置。实际上,它会返回一个内存位置,其中
指针被保存,而不是 array_main + index被保存的地方,所以您正在销毁
指针保存在 array + index中。
pfs = sizeof(float*)
fs = sizeof(float)


real address base base+pfs base+2*pfs base+3*pfs
pointer arithmetic base base+1 base+2 base+3
+---------+----------+----------+
| float* | float * | float * |
+---------+----------+----------+

real address base base+fs base+2*fs base+3*fs
pointer arithmetic base base+1 base+2 base+3
+-----------+-----------+-----------+
| float | float | float |
+-----------+-----------+-----------+

上面的图表显示了相同的内存地址
float(顶部)和视为 array_main(底部)。基本上是最高代表
是你在 base中的 float**所拥有的。最下面的就是你要的
float*中的 array。你看指针的算术不成一行,所以你
正在访问不正确的内存位置,这会产生未定义的
行为。
怎么解决?像这样修复 main
int NumOfVal(int data, float **array) {
int index; /* counters */
int array_index;
int copy;
float size;
float val;

for(index = 0; index < data;index++){
printf("Enter size of dataset %d:\n", index);
scanf("%f", &size);
copy = size;
printf("Size = %d\n", (int) size);
printf("Array #: %d\n", index);
/* malloc() for row */
/* array[index] */
array[index] = calloc(size + 1, sizeof *index);
array[index][0] = size;

我知道你想用第一个元素来保存大小。这是个不错的策略,
但由于这个原因,您需要再分配一个元素,否则您将 array
循环将溢出。
您在 NumOfVal中有相同的问题,相同的修复:
void calculateSum(int setChoice, float **array){
int i;
int first = array[setChoice-1][0];
float sum = 0;
for(i = 1; i <= first; i++){
sum += array[setChoice - 1][i];
}
printf("The sum of the values is: %.3f\n", sum);
}

如果朋友返回,请不要忘记检查其返回值
NumOfVal,无法访问该内存。同时编写一个函数来释放
记忆。这里 for很有用,因为 calculateSum是合法的。
void free_array(int size, float **array)
{
if(array == NULL)
return;

for(int i = 0; i < size; ++i)
free(array[i]);

free(array);
}

malloc函数中,您应该执行以下操作:
array[index] = calloc(size + 1, sizeof *index);
if(array[index] == NULL)
{
// error handling
return 0;
}

另外,您忘记返回 NULL中的值。如果你的功能不是
无论如何,要返回一个值,请将其声明为 calloc
现在在计算之后进入 free(NULL);
free_array(numData, array);

去释放记忆。

关于c - 局部指针数组问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48602937/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com