我真的不知道哪个应该是正确的标题,但我会尽量解释它,请耐心等待我。
今天我发现了这个GCC
标志=>> -Wlarger-than=len
:
Warn whenever an object of larger than len bytes is defined.
所以我决定尝试一下。让我们来看看以下程序:
#include <stdio.h>
#include <string.h>
int main(void){
char ptr[12] = "Mississippi";
size_t len1 = sizeof ptr;
printf("Len1 = %zu\n", len1);
char a[len1];
strcpy(a, ptr);
printf("\nA = %s\n", a);
}
返回输出:
Len1 = 12
A = Mississippi
所以程序看起来很好,但是如果我用-Wlarger-than=len
而不是len == 10
开启gcc -Wall -Wextra -Werror -Wlarger-than=10 program.c -o program
标志:
program.c:5:14: error: size of ‘ptr’ is 12 bytes [-Werror=larger-than=]
char ptr[12] = "Mississippi";
^~~
program.c:10:14: error: size of ‘({anonymous})’ is 16 bytes [-Werror=larger-than=]
char a[len1];
^
program.c:10:14: error: size of ‘({anonymous})’ is 16 bytes [-Werror=larger-than=]
program.c:10:14: error: size of ‘({anonymous})’ is 16 bytes [-Werror=larger-than=]
program.c:10:14: error: size of ‘({anonymous})’ is 16 bytes [-Werror=larger-than=]
当我12岁时,我得到16:
char a[len1];
为什么会这样?我对此感到困惑,因为这一行:
char a[12];
我虽然会:
size_t len1 = sizeof ptr;
如果我将size_t len1 = strlen(ptr) + 1;
更改为element.style
答案 0 :(得分:4)
您的a
是一个可变长度数组(VLA)。显然,编译器无法预测VLA的未来运行时大小,这意味着-Wlarger-than=len
选项不能也不会发出适用于VLA阵列本身的警告。尽管您有所期望,但您看到的警告并不直接适用于您的数组a
,也不会由a
本身的大小触发。
可变长度数组是通过一些与实现相关的内部数据类型实现的,它恰好在GCC中的大小为16。可以猜测,在您的平台上,此内部数据类型包括一个指向数组内存的8字节指针以及8字节运行时大小信息。这是尺寸16来自的地方。如果您使用代码进行更多实验,您会发现大小完全不依赖于len1
的值。大小总是16。
您收到的警告适用于该内部类型的特定堆栈分配的匿名对象。这就是错误消息显示‘({anonymous})’
而不是a
的原因。您基本上可以说使用-Wlarger-than=len
选项且len
小于16将始终触发每个VLA的诊断。
即。你的
char a[len1];
不等于
char a[12];
你似乎相信了。它实际上相当于像这样的东西
struct anonymous_t {
char *data;
size_t size;
} anonymous = { alloca(len1), len1 };
每次访问a[i]
时,编译器实际访问anonymous.data[i]
。您看到的消息会抱怨anonymous
的大小,而不是a
的大小。