为了账号安全,请及时绑定邮箱和手机立即绑定

为什么C和C ++编译器在从未强制实施时允许函数签名中的数组长度?

为什么C和C ++编译器在从未强制实施时允许函数签名中的数组长度?

C++ C
牧羊人nacy 2019-07-23 10:53:23
为什么C和C ++编译器在从未强制实施时允许函数签名中的数组长度?这是我在学习期间发现的:#include<iostream>using namespace std;int dis(char a[1]){     int length = strlen(a);     char c = a[2];     return length;}int main(){     char b[4] = "abc";     int c = dis(b);     cout << c;     return 0;}所以在变量中int dis(char a[1]),[1]似乎什么都不做,根本不起作用,因为我可以使用a[2]。就像int a[]或char *a。我知道数组名称是一个指针,以及如何传达一个数组,所以我的谜题不是这个部分。我想知道的是为什么编译器允许这种行为(int a[1])。或者它有其他我不知道的含义?
查看完整描述

3 回答

?
12345678_0001

TA贡献1802条经验 获得超5个赞

这是将数组传递给函数的语法的怪癖。

实际上,无法在C中传递数组。如果您编写的语法看起来应该通过数组,那么实际发生的是传递指向数组第一个元素的指针。

由于指针不包含任何长度信息,因此[]实际上忽略了函数形式参数列表中的内容。

允许这种语法的决定是在20世纪70年代做出的,并且自从......以来引起了很大的混乱。


查看完整回答
反对 回复 2019-07-23
?
慕桂英4014372

TA贡献1871条经验 获得超13个赞

忽略第一个维度的长度,但需要额外维度的长度以允许编译器正确计算偏移量。在下面的示例中,foo函数传递指向二维数组的指针。

#include <stdio.h>void foo(int args[10][20]){
    printf("%zd\n", sizeof(args[0]));}int main(int argc, char **argv){
    int a[2][20];
    foo(a);
    return 0;}

[10]忽略第一个维度的大小; 编译器不会阻止你索引结束(请注意,正式需要10个元素,但实际只提供2个元素)。但是,第二个维度的大小[20]用于确定每一行的步幅,这里,形式必须与实际匹配。同样,编译器也不会阻止您索引第二个维度的末尾。

从数组基址到元素的字节偏移量由下式args[row][col]确定:

sizeof(int)*(col + 20*row)

请注意,如果col >= 20,那么您将实际索引到后续行(或整个数组的末尾)。

sizeof(args[0])80在我的机器上返回sizeof(int) == 4。但是,如果我尝试接受sizeof(args),我会得到以下编译器警告:

foo.c:5:27: warning: sizeof on array function parameter will return size of 'int (*)[20]' instead of 'int [10][20]' [-Wsizeof-array-argument]
    printf("%zd\n", sizeof(args));
                          ^foo.c:3:14: note: declared herevoid foo(int args[10][20])
             ^1 warning generated.

在这里,编译器警告它只会给出数组已经衰减的指针的大小而不是数组本身的大小


查看完整回答
反对 回复 2019-07-23
  • 3 回答
  • 0 关注
  • 822 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信