c - 为什么这不会在 C 中生成越界访问?

标签 c gcc enums c99

为了对 C99 和 Rust 进行一些比较,我编写了以下 C 代码,

typedef enum {
    NICKLE, DIME, QUARTER, DOLLAR,
} Denom;

static const int cents[] = {
    [NICKLE] = 5,
    [DIME] = 10,
    [QUARTER] = 25,
    [DOLLAR] = 100,
};

int main () {
    printf( "Result %d\n", cents[DIME] );
}

这按预期工作,现在我想显示越界访问,当我这样做时

typedef enum {
    NICKLE, DIME, QUARTER, DOLLAR, ZOD = 20394
} Denom;

我很期待

printf( "Result %d\n", cents[ZOD] );

显示为 cents + ZOD 的访问权限。但事实并非如此。

 mov eax, 0
 mov esi, eax
 lea rdi, str.Result__d        ; 0x5570bf1ed020 ; "Result %d\n"
 mov eax, 0
 call sym.imp.printf           ; int printf(const char *format)

为什么要将 esi 设置为 0,为什么会打印

Result 0

-Wall -Wextra -Wpedantic 也没有错误。 GCC 是否提供管理此行为的标志?它是否知道这是越界的,如果是这样,它是否也不会发出警告(或者是否可以让它发出警告)?

最佳答案

是的,GCC 可以在特定情况下对此发出警告(请参阅@Acorn 的回答)。

有一个运行时未定义行为检查器,-fsanitize=undefined ,如果您执行某些类型的未定义行为(例如访问过去的数组边界),应该会报错。

由于这是未定义的行为,编译器可以自由地做任何它想做的事。这意味着它可以将 esi 设置为零、您的密码的十六进制表示形式或任何其他内容。

关于c - 为什么这不会在 C 中生成越界访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57748788/

相关文章:

c - mex:计算权;但是,我得到了错误的输出

gcc - 创建和链接静态 rust 库并链接到 c

c++ - typedef'ing enum 不会使 enum-values 可见

enums - JAXB 不会为受限元素创建枚举

c - 我正确使用结构吗?

c - 打包两个 8 位值

c - C 中每轮 INT 降低 10%

c++ - 减少所需的 libc 版本

c - 是否可以用我自己的 <string.h> 覆盖 strdup?

android - 如何在 Kotlin 的枚举中检索用 vararg 声明的参数的值