我真的不知道哪个标题合适,但是我将尽我所能解释,请耐心等待。
今天,我发现了这个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
标志12:gcc -Wall -Wextra -Werror -Wlarger-than=10 program.c -o program
当我执行12时,我得到16:
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=]
为什么会这样呢?我对此感到困惑,因为这一行:
char a[len1];
我虽然会是:
char a[12];
如果将
size_t len1 = sizeof ptr;
更改为size_t len1 = strlen(ptr) + 1;
,也会发生相同的情况 最佳答案
您的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
的大小。