众所周知,当在C中作为参数传递时,数组会衰减为指针。但是数组数组只会衰减到数组的指针;因此,如果我们将原始数组本身封装在一个数组中,我们可以在将封闭数组传递给函数后检索原始数组长度。这是一个测试这个想法的程序:
/* array_workaround.c */
#include <stdio.h>
void printsize(char array_pointer[][10]);
int main(void)
{
char a[10];
for(char i = 0; i < 10; i++)
a[i] = i;
char a_p[1][10] = {a};
printsize(a_p);
return 0;
}
void printsize(char array_pointer[][10])
{
printf("%lu\n", sizeof(array_pointer[0]));
}
运行时,会输出正确的值(10
),但编译器会发出此警告:
array_workaround.c:12:24: warning: incompatible pointer to integer conversion
initializing 'char' with an expression of type 'char [10]' [-Wint-conversion]
char a_p[1][10] = {a};
当然,这种“解决方法”的问题在于它要求将数组的大小硬编码到接收它的函数中,这样就失去了整个目的。但是,它确实意味着检查数组的大小是正确的,而不必将长度作为单独的参数传递...(只要它总是10!lol)。
那警告发生了什么?编译器是不是“足够聪明”才能知道这里发生的事情不会破坏任何数据?或者我只是以某种方式获得幸运?任何人都可以看到一种方法使其成为实际的解决方法,这样您就不必在那里对数字10进行硬编码了吗?
答案 0 :(得分:1)
该行
char a_p[1][10] = {a};
相当于
char a_p[1][10];
a_p[0][0] = a;
希望你能看到那里的问题。至于为什么你的大小很幸运,这是因为你将数组的第一个维度设置为1.试试这个
char a_p[5][10];
看看你得到了什么。没有解决方法可以避免printsize
函数中的数字10。编译器需要10才能正确计算数组元素的地址。
答案 1 :(得分:1)
在
char a_p[1][10] = {a};
a
的基础地址,a
的基地址,并且具有指向char
的指针类型,用于初始化a_p[0][0]
,char
应该是{{1}} {1}},这就是编译器为您提供转换警告的原因。
答案 2 :(得分:1)
感谢大家的答案。我已经给你答案,leeduhem,因为你指出了我所有的误解。但是我还想在这里添加一个答案(而不是编辑一个混乱的编辑),因为我想出了一个使用变长数组声明和全局变量使其工作的一种方法。
#include <stdio.h>
int length;
void printsize(char array_pointer[][length]);
int main(void)
{
char a[10];
length = sizeof a;
for(int i = 0; i < sizeof a; i++)
a[i] = i;
char a_p[1][sizeof a];
for(int i = 0; i < sizeof a; i++)
a_p[0][i] = a[i];
printsize(a_p);
return 0;
}
void printsize(char array_pointer[][length])
{
printf("%lu\n", sizeof(array_pointer[0]));
}
这会返回10,大小为a
。
编辑:这是一个使用指针解决问题的版本。它在运行时获取length
的值,但不知何故,取决于长度的声明仍然可以。 (我尝试直接传入数组,但它给了我指回char指针的大小,而不是数组大小。)
#include <stdio.h>
int length;
int arraylength(char (*a)[length]);
int main(void){
int n;
printf("Enter array length: ");
scanf("%d", &n);
char a[n];
for(int i = 0; i < sizeof a; i++)
a[i] = i;
length = sizeof a;
printf("%d\n", arraylength(&a));
}
int arraylength(char (*a)[length]){ /* pointer to array of chars */
return sizeof (*a); // note that the "(*a)" here is a deferenced array
}