带有GCC标志“-Wlarger-than = len”的可变长度数组

时间:2016-05-20 19:01:14

标签: c gcc

我真的不知道哪个应该是正确的标题,但我会尽量解释它,请耐心等待我。

今天我发现了这个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

,也会发生同样的事情

1 个答案:

答案 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的大小。