c - block 作用域缓冲区在 c 中的 block 之外是否有效

标签 c memory lexical-scope

我只是想知道以下是否可以被认为是安全的做法:

void some_func(void) {
    const char * foo;

    if (SOME_MACRO()) {
       char * foo_buf[20];
       snprintf(foo_buf,sizeof(foo_buf),"blah_%d",some_global);
       foo = foo_buf;
    } else {
       foo = "some constant string";
    }
    // do a bunch of other stuff here...
    printf("%s\n", foo);
}

这假设 foo_buf 中的内存在 block 作用域之外仍然有效(且未更改)。我担心是否存在编译器在 block 退出时丢弃或覆盖 block 特定内存的情况。我希望在 block 中而不是在全局范围内声明的原因是,在某些平台上,SOME_MACRO() 会解析为一个常量,而在其他平台上,则解析为一个表达式,因此在某些情况下可以优化 if block 。

最佳答案

这是UB。

提升 char * foo_buf[20]; 不应该给你更糟糕的代码。无论如何,所有函数的局部变量都可能分配在顶部,并且编译器能够很好地消除从未使用过的局部变量。

尝试编译:

#define UP 0
#define CONST 1

#include <stdio.h>

#if CONST
   #define SOME_MACRO() 0
#else
   int SOME_MACRO(void);
#endif

int some_global;


void some_func(void) {
    const char * foo;

#if UP
    char foo_buf[20]; //fixed from char *foo_buf[20];
#endif


    if (SOME_MACRO()) {
#if !UP
       char foo_buf[20]; //fixed from char *foo_buf[20];
#endif
       snprintf(foo_buf,sizeof(foo_buf),"blah_%d",some_global);
       foo = foo_buf;
    } else {
       foo = "some constant string";
    }
    // do a bunch of other stuff here...
    printf("%s\n", foo);
}

将 CONST 设置为 0 或 1,然后将 UP 更改为介于 0 和 1 之间。

使用 gcc、clang 或 icc 移动声明(通过更改 UP)即使在 -O0 也没有区别:https://gcc.godbolt.org/z/z9jnQD .

关于c - block 作用域缓冲区在 c 中的 block 之外是否有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56463477/

相关文章:

scheme - 暂时覆盖Scheme let block 中的全局定义函数?

Perl 替换值而不更新数组

python - 如何在Python中执行一小部分C代码?

php - 将二进制数组转换为十进制字符串奇怪的行为

java - 如何解决 'java.lang.OutOfMemoryError: GC overhead limit exceeded'

c++ - VirtualAlloc C++,注入(inject)的dll,asm

dynamic - OCaml 词法与动态作用域

c - 在 C 中使用 win32 在父线程中创建未知数量的子线程?

c - 完全相同的命令行在 Make 中产生错误,但如果从 shell 运行则成功

c - C 中的文件输入和数组指针