我完全意识到,当传递给函数时,数组只会衰减为指针,因此您不能使用
sizeof(x)/sizeof((x)[0])
来计算它们的大小。然而,我发现可以使用 (&x)[1]-x
,即指针算术,因此,出于好奇,我尝试创建一个函数,它接受两个数组,计算出它们的长度,然后连接它们(使用 malloc
动态分配一块内存,其大小是其长度之和乘以 int 的大小)。
这有效:
#define ARR_LEN(a) ((&(a))[1]-(a))
void join (int a[], int b[]) {
printf("%zu %zu", ARR_LEN(a), ARR_LEN(b));
}
int main() {
int a[3] = {0, 1, 2};
int b[5] = {0, 1, 2, 3, 4};
join(a, b);
return 0;
}
它打印
3 5
。但是,更改 join
的主体以将 ARR_LEN(a)
存储在局部变量 n
中,即使在我们第一次打印 ARR_LEN(a)
后也是如此:
int n;
printf("%zu %zu", ARR_LEN(a), ARR_LEN(b));
n = ARR_LEN(a);
导致看似伪随机的结果,例如
18446708891292021383 5
。最奇怪的是,当 3 5
是全局而不是本地时,它工作正常,打印 n
。此外,打印 n
的内容会得到与第一个不同的数字。
我的猜测是,当
a
和 b
位于堆栈上时,将 n
放在那里会以某种方式导致 C 编译器对它们的大小感到困惑,尽管当我将 n
声明为 int __attribute__ ((aligned (256)))
时,这个问题仍然存在
尝试强制它远离其他两个(以及任何奇怪的缓存问题)。当我打印 &a
、&b
和 &n
时,我得到类似以下内容:
0x7ffd680a8df8 0x7ffd680a8df0 0x7ffd680a8e00
而当
n
为全局时,&n
为 0x404200
,因为 .data
位于堆栈下方。此外,当 n
是全局变量而我改为放置局部变量 m = ARR_LEN(b)
时,a
会“损坏”,而 ARR_LEN(b)
会再次正确打印。