【发布时间】:2015-10-05 05:48:21
【问题描述】:
考虑以下声明:
int a[M][N]; // M and N are known compile-time
像声明的那样对待它是否合法:
int a[N][M];
甚至:
int a[A][B]; // where A * B = M * N
在 C 中不违反其规则(严重)?
我发现它可以在没有任何演员表的情况下完成:
#include <stdio.h>
void print_array(int a[][2], int n);
int main(void)
{
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
//int (*p1)[2] = a; // compile error
int (*ptr_temp)[] = a; // pointer to array of incomplete type
int (*p2)[2] = ptr_temp; // compiles without any warning
print_array(p2, 3);
}
void print_array(int a[][2], int n)
{
for (int i = 0; i < n; i++)
for (int j = 0; j < 2; j++)
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
}
请注意,我们不能将a 直接分配给p1 指针。然而,当p2 被分配给ptr_temp 时,编译器不会抱怨,即使它看起来有潜在的危险(它不需要任何强制转换)。真的消毒了吗?如果是这样,那为什么它不允许第一次分配?
【问题讨论】:
-
不,这是不允许的。完全由合法隐式转换组成的转换路径的存在并没有说明对此类指针执行算术或取消引用的有效性。请记住,您可以使用指向
void的指针创建几乎任意的隐式转换路径。 -
单步执行中间指针类型时没有编译器错误并不一定意味着世界是正确的。一个简单的中间
void*(甚至是演员表)将在 C 中完成相同的缺少错误。 -
我不太确定您的具体代码,但我相信
print_array( (int(*)[2])&a , 3);是合法的。关于通过强制转换为不同的数组类型来访问数组的标准并不十分明确。 -
@R.. 你能详细说明一下这个答案吗?我对仅转换本身并不能说明有效性这一事实感到满意。但它也没有说明无效性。
-
我认为根据 C 标准这是合法的,但这是一个非常糟糕的想法,它没有实际意义,不值得花时间进行语言律师来确定明确的答案。