这是一个带有
warning: incompatible pointer to integer conversion initializing. 'int' with an expression of type 'int *'; dereference with *
, 的小 C 程序
#include <stdio.h>
#include <stdlib.h>
#define N 3
typedef struct node {
int arr[N];
} node;
node *new_node(int arr[N]) {
node *x = (node *)malloc(sizeof(node));
*x = (node){arr};
return x;
}
int main() {
int arr[N] = {0, 1, 2};
node *x = new_node(arr);
for (int i = 0; i < 3; i++)
printf("%d\n", x->arr[i]);
}
取消引用
*x = (node){*arr};
可以解决警告,但程序不会产生预期的输出。
我的 C 有点生疏,但据我了解,每当您将数组传递给函数时,您实际上都会传递一个指向其第一个元素的指针。因此,上面的内容应该与这个程序相同(顺便说一句,它按预期工作)。
#include <stdio.h>
#include <stdlib.h>
#define N 3
typedef struct node {
int *arr;
} node;
node *new_node(int *arr) {
node *x = (node *)malloc(sizeof(node));
*x = (node){arr};
return x;
}
int main() {
int arr[N] = {0, 1, 2};
node *x = new_node(arr);
for (int i = 0; i < 3; i++)
printf("%d\n", x->arr[i]);
}
我这里没有什么 C 细节?
每当您将数组传递给函数时,您实际上都会传递一个指向其第一个元素的指针
这是正确的;就所有意图和目的而言,这两个函数
foo(int a[])
和 foo(int* a)
是相同的。
上面应该和这个程序一样
然而,这是不正确的。
new_node
函数的不同参数类型 (int arr[N]
vs int *arr
) 不是两个代码片段之间唯一的区别:node
结构也存在显着差异。
在第二个片段中,
struct
的第一个成员是int*
,并且将结构强制转换为其第一个成员的类型(反之亦然)是有效的C;然而,在第一个片段中,结构中没有指针(数组不是指针,尽管在许多表达式中,它“衰减”为指向其第一个元素的指针)。
在第一个片段中,结构的第一个成员(也就是说,该结构起始地址处的数据类型)实际上是“数组的第一个元素”。因此,当您这样做时,*x = (node){ arr };
arr
标识符会衰减为指针,但赋值的转换和 LHS 引用 int
的位置。要设置结构体数组成员的值,您需要将参数指向的内存复制到结构体中:
node* new_node(int arr[N]) {
node* x = (node*)malloc(sizeof(node));
memcpy(x, arr, sizeof(int) * N);
return x;
}
或者,您可以在两个代码片段之间使用“混合”:将
int arr[N]
参数设置为
new_node
(如您的第一种情况),但使用 int *arr
的 struct node
成员(如您的第二个情况)案件)。然后它将按预期工作:#include <stdio.h>
#include <stdlib.h>
#define N 3
typedef struct node {
int *arr;
} node;
node* new_node(int arr[N])
{
node* x = malloc(sizeof(node));
*x = (node){ arr }; // Member pointer is assigned value of passed pointer
return x;
}
int main()
{
int arr[N] = { 0, 1, 2 };
node* x = new_node(arr); // Address is passed
for (int i = 0; i < 3; i++) {
printf("%d\n", x->arr[i]); // Works!
}
free(x);
return 0;
}