为什么C在这里需要指针解引用?

yeotifhr  于 2024-01-06  发布在  其他
关注(0)|答案(1)|浏览(77)

下面是一个小的C程序,它生成以下内容:
警告:指向整数转换的指针不兼容,初始化.“int”与类型为“int”的表达式;用 * 解引用

#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]);
}


我在这里还有什么不知道的?

lf5gs5x2

lf5gs5x21#

  • 每当你传递一个数组到一个函数,你本质上是传递一个指向它的第一个元素的指针 *

这是正确的;两个函数foo(int a[])foo(int* a)实际上是相同的。

  • 以上内容应与本程序相同 *

然而,这是 * 不 * 正确的。new_node函数的不同参数类型(int arr[N]vsint *arr不是两个代码片段之间的唯一差异node结构中也有显著差异。
在第二个代码片段中,struct的第一个成员是int*,将结构转换为其第一个成员的类型(反之亦然)是有效的C;然而,在第一个代码片段中,结构中没有指针(数组 * 不是 * 指针,尽管在许多表达式中,它“衰减”为指向其第一个元素的指针)。
在第一个代码片段中,结构的第一个成员(也就是说,该结构的起始地址处的数据类型)实际上是数组的第一个元素**。因此,当您这样做时,*x = (node){ arr };arr标识符衰减为指针,但转换和赋值的LHS引用int的位置。
要设置结构体的数组成员的值,您需要:* 要么 * 将参数所指向的内存复制到结构体中; * 要么 * 使用由指向数组的元素构造的compound literal初始化分配的node

node* new_node(int arr[N]) // Version using the "memcpy" function
{
    node* x = malloc(sizeof(node));
    memcpy(x, arr, sizeof(int) * N);
    return x;
}

node* new_node(int arr[N]) // Version using a compound literal
{
    node* x = malloc(sizeof(node));
    *x = (node){ { arr[0], arr[1], arr[2] } };
    return x;
}

字符串
或者,您可以在两个代码片段之间使用“混合”:将int arr[N]参数设置为new_node(如第一种情况),但使用struct nodeint *arr成员(如第二种情况)。这将按预期工作:

#include <stdio.h>
#include <stdlib.h>

#define N 3
typedef struct node {
    int *arr;
} node;

node* new_node(int arr[N]) // The "N" is now redundant
{
    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;
}

相关问题