我真的不知道哪个标题合适,但是我将尽我所能解释,请耐心等待。

今天,我发现了这个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的大小。

10-08 00:59