【问题标题】:What does it mean to pass an array of pointers in C?在 C 中传递指针数组是什么意思?
【发布时间】:2021-07-31 13:07:26
【问题描述】:

我正在为 C 的指针概念而苦苦挣扎,正是指针数组。请参阅以下程序以供参考。

#include <stdio.h> 

int a1[] = {6,7,8,18,34,67};
int a2[] = {23,56,28,29};
int a3[] = {-12,27,-31};
int *x[] = {a1,a2,a3};

void print (int *a[]){
  printf ("%d",a[0][2]);
  printf ("%d",*a[2]);
  printf ("%d",*++a[0]);
  printf ("%d",*(++a)[0]);
  printf ("%d",a[-1][1]);
 
}

void main (){ 
  print (x);
}

我不明白的是,如果我们将int *a[] 作为指针数组传递,那么它应该是一个数组好吗?但有人告诉我,这里 a 只是一个单一的指针变量,它充当 x 的别名,但根据语法 a 应该是一个数组,即。 print() 函数的激活记录应该包含一个数组,而不仅仅是一个保存 x 基地址的指针变量,而是整个混淆是指针还是指针数组,语法肯定暗示它应该是int 指针的数组,我在网上阅读但更加困惑,请不要通过标记无关来忽略这个问题。

【问题讨论】:

  • 您是否阅读过Modern C、C 编译器的文档(例如GCC... 将作为gcc -Wall -Wextra -g 调用)和调试器的文档(例如GDB... )。另请参阅 this C referencen1570 或一些更新的 C 标准
  • 你可以使用调试器吗?并逐步运行您的程序?并在纸上画图(用箭头表示指针,就像在linked list wikipage 中一样?)如果您阅读documentation of GDB 会发生什么?顺便说一句,你可以考虑在你的笔记本电脑上安装Debian
  • 你读过关于pointers 的维基页面吗?还有virtual address space 上的那个?您可能想阅读一些good operating system textbook。你能看纸上的书吗?你可以使用Clang static analyzer 吗?还是Frama-C
  • 你可能想运行gcc -fverbose-asm -Wall -Wextra -O2 -S your-prog.c并查看生成的汇编代码your-prog.s,假设你被允许使用GCC
  • 你知道array pointer decay的工作原理吗?

标签: arrays c pointers parameter-passing


【解决方案1】:

在两种情况下,数组“衰减”为指向其第一项的指针:

  • 无论何时在(大多数)表达式中使用数组名称,或
  • 当函数参数声明为数组类型时。

int *x[] = {a1,a2,a3}; 起作用的原因是因为这 3 个数组“衰减”为指向其第一个元素的指针。在所有 3 种情况下都是 int* 类型,因此它与 x 数组的元素类型兼容。

然后,当您定义诸如void print (int *a[]) 之类的函数时,编译器会默默地隐式地将这个数组声明“衰减”为指向第一个元素的指针。 int* [] 数组的第一个元素是 int*,指向一个元素的指针是 int**。所以这个函数相当于void print (int** a);。这就是为什么我们可以在这里写一个空的[] - 编译器并不关心数组的大小,因为它无论如何都会用指针替换数组。

这也是多级间接a[0][2] 起作用的原因。这是不是,因为a 是一个二维数组——它不是。但是第一个[]int** 类型进行指针运算以获得相关的int* 元素。第二个依次对该指针元素进行指针运算,以得到实际的int

至于该函数内的各种行,这是某种人工学校示例,旨在教授运算符优先级。提示:后缀运算符通常具有最高优先级。

a[-1][1] 行是一个错误,因为它调用了未定义的行为——我们不应该编写这样的程序,其原因是它自己的一个有点高级的话题。详细信息在这里:Is it undefined behaviour to just make a pointer point outside boundaries of an array without dereferencing it?

【讨论】:

  • 运算符[]对地址做了什么指针运算,能详细说明一下吗?
  • @PawanNirpal 与任何指针算法一样,每个索引或 +1 都会将偏移量增加sizeof(type)。因此,如果您对 int** 指针进行指针运算,您将获得 sizeof(int*) 的块。
  • 是的,谢谢,这就是我所期待的,但我不确定,现在我知道了,再次感谢。
猜你喜欢
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-04
  • 2011-01-27
  • 2012-11-02
相关资源
最近更新 更多