在C函数中,双指针和单指针的区别是什么



我是C编程语言的新手,开始处理指针和为对象分配内存的问题。我想制作一个简单的程序,从用户那里读入(x(个元素,然后使用函数简单地打印出来。

这是我一开始的初始代码。代码正确读取了用户输入,但它给出了错误的输出,并在显示主函数中的元素时崩溃。

int main() {
int *myArr;
int myArrSize;
getInputArr(&myArrSize, &myArr);
for (int i = 0; i < myArrSize; i++) {
printf("Element No.%i: %in", i, myArr[i]);
}
free(myArr);
return 0;
}
void getInputArr(int *arrSize, int *arr) {
printf("Please Enter Length of Array: n");
scanf("%i", arrSize);
arr = (int *) malloc(*arrSize * sizeof(int));
printf("Enter %i Numbers!n", *arrSize);
for (int i = 0; i < *arrSize; i++) {
scanf("%i", &arr[i]);
}
}

经过一番折腾,我终于用双指针让它工作了,但我不确定它是如何完全工作的,有人能解释一下为什么下面的代码会像预期的那样工作吗?

int main() {
int *myArr;
int myArrSize;
getInputArr(&myArrSize, &myArr);
for (int i = 0; i < myArrSize; i++) {
printf("Element No.%i: %in", i, myArr[i]);
}
free(myArr);
return 0;
}
void getInputArr(int *arrSize, int **myArr) {
printf("Please Enter Length of Array: n");
scanf("%i", arrSize);
*myArr = (int *) malloc(*arrSize * sizeof(int));
printf("Enter %i Numbers!n", *arrSize);
for (int i = 0; i < *arrSize; i++) {
scanf("%i", &((*myArr)[i]));
}
}

在您的实现中有一些令人惊讶的事情,但最终它们都是有意义的,而且它们必须存在才能使此实现工作。

  1. 您最终希望main中的int *myArr模拟int的数组,但在getInputArr中,您使用";双指针";int **myArr。但这是有道理的,因为任何时候你都想从函数"返回一些东西;通过引用";像这样,您需要使用一个指针——一个额外的指针。要通过引用返回int,可以使用int *。但是要通过引用返回int *,您需要一个int **。事实上,您(正确地(在main中调用了getInputArr(&myArrSize, &myArr),这表明getInputArr的第二个参数将是int **
  2. 在getInputArr中,当您调用scanf时,您不会在传递给scanf以供%d读取的参数旁边有一个&。这是非常不寻常的,但在这种情况下它是绝对正确的,因为arrSize已经是一个指针了
  3. 然后您就有了*myArr = (int *) malloc(*arrSize * sizeof(int))。这是我在您最初(非工作(实现中发现的第一件非常错误的事情。在getInputArr中,myArr是指向要设置的指针的指针。所以*myArr是您想要设置的指针
  4. 最后,您有了一个名为scanf("%i", &((*myArr)[i]));的Jawbbreaker。这看起来很难看,可能有更简单的写法,但它是正确的。让我们把它分解一下。同样,myArr是指向要使用的指针的指针。因此*myArr是您想要使用的指针。因此,(*myArr)[i]是要使用的模拟数组(由指针指向(的一个元素。你需要明确的括号,因为如果你写*myArr[i],这意味着;获取myArr指向的第i个元素,将其解释为指针,并获取内容"但你想要的(加上括号,你已经拥有了(是";取myArr,将其解释为指针,取其所指向的东西,即*myArr,并将解释为指针。最后取其(第二个指针(所指向的第i个元素

您有多个级别的指针让您感到困惑。但是,如果您正在处理的动态分配数组位于结构内部,该怎么办?然后我们只需要处理该结构上的指针传递("引用"(语义。

请考虑以下内容。有关说明,请参见注释。

/* Basic stuff. */    
#include <stdio.h>
#include <stdlib.h>
/* Here's our struct. 
* It contains the size of the array,
* and the pointer to the memory allocated for the array.
*/
typedef struct dyn_int_array {
size_t size;
int * array;
} dyn_int_array_t; 
/* Forward declarations for a function which creates and 
* returns our dynamic_int_array struct.
*/
dyn_int_array_t * create_dyn_int_array();
/* ... and here's where you see that we don't want to 
* pass the struct by value, but rather effectively by 
* reference by passing a pointer to it. 
*/
void scan_into_dyn_int_array(dyn_int_array_t * da);
int main(void) {
dyn_int_array_t * da = create_dyn_int_array();
/* I never bothered to free up the allocated memory,
* because it's not really critical for demonstration here.
*/
}

这些函数的实现如下,但对本演示并不重要,因为您希望看到指针的引用传递使用,而不必直接担心或被两个级别的指针间接性所混淆。

dyn_int_array_t * create_dyn_int_array() {
dyn_int_array_t * result = malloc(sizeof(dyn_int_array_t));
fprintf(stdout, "Input an array size: ");
fscanf(stdin, "%zd", &(result->size));

result->array = malloc(sizeof(int) * result->size);

/* Because "da" is already a pointer to dye_int_array_t
* there's no need to get its address.
*/
scan_into_dyn_int_array(result);

return result;  
}
void scan_into_dyn_int_array(dyn_int_array_t * da) {
for (int i = 0; i < da->size; i++) {
/* We do have to pass the address of the current 
* element of the array to fscanf.
*/
fscanf(stdin, "%d", &(da->array[i]));
}
}

相关内容

  • 没有找到相关文章

最新更新