gpt4 book ai didi

我可以在 C99 中使用数组作为函数参数吗?

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

C99 标准在 6.7.5.3/7 中说明如下:

A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation.

我的理解是:

void foo(int * arr) {} // valid
void foo(int arr[]) {} // invalid

但是,gcc 4.7.3 将乐于接受这两个函数定义,即使在使用 gcc -Wall -Werror -std=c99 -pedantic-errors 编译时也是如此。由于我不是 C 专家,我不确定我是否误解了标准的内容。

我也注意到了

size_t foo(int arr[]) { return sizeof(arr); }

将始终返回 sizeof(int *) 而不是数组大小,这坚定了我的信念,即 int arr[] 被处理为 int * 和 gcc 只是想让我感觉更舒服。

有人可以阐明这个问题吗?仅供引用,这个问题来自this comment .

最佳答案

一些上下文:

首先,请记住,当“T 的 N 元素数组”类型的表达式出现在不是 sizeof 的操作数的上下文中时或一元 & 运算符,或者不是用于在声明中初始化另一个数组的字符串文字,它将被转换为“指向 T 的指针”类型的表达式它的值将是数组中第一个元素的地址。

这意味着当你将一个数组参数传递给一个函数时,该函数将接收一个指针值作为参数;在调用函数之前,数组表达式被转换为指针类型。

这很好,但是为什么 arr[] 允许作为指针声明?我不能说这就是 肯定 的原因,但我怀疑这是 B 语言的遗留问题,C 语言就是从 B 语言派生出来的。事实上,几乎所有关于 C 中数组的古怪或不直观的东西都是 B 的遗留物。

B 是一种“无类型”语言;对于 float 、整数、文本等,您没有不同的类型。一切都存储为固定大小的字或“单元格”,内存被视为单元格的线性阵列。当你在 B 中声明一个数组时,如

auto arr[10];

编译器会为数组留出 10 个单元格,然后留出额外的第 11 个单元格,用于存储数组第一个元素的偏移量,并且该额外的单元格将绑定(bind)到变量 arr。与在 C 中一样,B 中的数组索引计算为 *(arr + i);您将获取存储在 arr 中的值,添加一个偏移量 i,然后取消引用结果。 Ritchie 保留了大部分这些语义,除了不再为指向数组第一个元素的指针留出存储空间之外。相反,该指针值将在翻译代码时从数组表达式本身计算。这就是为什么数组表达式被转换为指针类型,为什么 &arrarr 给出相同的值,如果类型不同(数组的地址和第一个元素的地址的数组是相同的)以及为什么数组表达式不能成为赋值的目标(没有任何东西可以分配给 ;没有为独立于数组元素的变量预留存储空间)。

现在是有趣的部分;在 B 中,您将声明一个“指针”为

auto ptr[];

这具有分配单元格以存储数组第一个元素的偏移量并将其绑定(bind)到 ptr 的效果,但是 ptr 没有指向任何地方特别的;您可以将其指定为指向不同的位置。我怀疑这种表示法被搁置有几个原因:

  1. 大多数从事 C 初始版本工作的人都熟悉它;
  2. 有点强调参数在调用者中代表一个数组;

就我个人而言,我更希望 Ritchie 在任何地方都使用 * 来指定指针,但他没有(或者,使用 [] 来指定指针在所有上下文中,不仅仅是函数参数声明)。我通常会建议大家使用 * 表示函数参数而不是 [],因为它更准确地传达了参数的类型,但我能理解为什么人们会更喜欢第二种表示法。

关于我可以在 C99 中使用数组作为函数参数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18833174/

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