How does this video on C avoid *Error: Variable-sized object may not be initialized* during compilation?

How does this video on C avoid *Error: Variable-sized object may not be initialized* during compilation?

*** 编辑 - 我知道它很长 post 并且我知道我使用了一些 'interesting' 语言选项。而且,我选择相信到目前为止我得到的三个答案都是出于善意——为此我感谢你们。但是,我真的必须坚持,如果你不愿意通读整个 post 或者你不明白我真正要问的是什么,请节省我们的时间并避免 post荷兰国际集团***

我一直在寻找 完全 提出的相同问题的答案 here - 相同的在线课程,相同的讲师;我认得视频中的代码。

我很快找到了#define 和使用枚举形式的解决方案,但这仍然没有真正解决讲师如何编译他的代码;而且,我想真正理解,而不仅仅是让它发挥作用,所以我试图更深入地挖掘。

有问题的教授实际上从未展示过代码编译,它始终是“这是我之前编译的”场景 - 所以我已经包括了错误出现在两个答案所指示的那个看不见的阶段的可能性在页面上:他很可能一直在使用 g++ 或 clang。

然而,我的搜索是最迂回的,引导我在网上四处寻找,在我找到上面链接的答案之前,除其他外,我遇到了这个 video在 9 分钟左右,他编写了这段代码:

#include <stdio.h>
#include <stdlib.h>

const int ARRAY_LENGTH = 5;

void printarray(int myarray[ARRAY_LENGTH]) {

    for (int i = 0; i < ARRAY_LENGTH; i++){
        printf("%i, ", myarray[i]);
    }
    printf("\n");
}


int main (int argc, char **argv){   

    int a[ARRAY_LENGTH] = {1, 2, 3, 4, 5};
    int b[ARRAY_LENGTH] = {5, 4, 3, 2, 1};

    int *p = malloc(sizeof(int) * 567);

    printarray(a);
    printarray(b);
    printarray(p);

    free(p);

}

他使用了一个运行带有 -g -Wall 标志的 gcc 的 makefile,并且在 mac 上(我想,如果我错了请纠正我)。互联网告诉我 clang 是 macs 上的默认编译器,所以也许这与它有关(虽然我不知道为什么会这样),但是用 g++ 尝试这段代码给出 error: invalid conversion from ‘void*’ to ‘int*’ [-fpermissive] .

我只想了解实际情况。并不是说 C 中的 consts 实际上不是常量,更像是只读的;使用#define/enum。我读过(可能在这里),我理解它,我重写了我的代码并使用这两种方法成功编译。我什至通过分离声明和赋值来使用 const 进行编译。而且,在这一点上,这不再是关于原始讲师如何编译他的代码的问题了——我已经测试了 g++ 它确实有效,而且,如果我早点找到那个答案,我现在可能会很高兴地满足于没有进一步的问题。

但是,我没有。而且,我发现的 none 解释了视频中的代码是如何编译的,运行(或者,为什么很多人认为这是 C 编码的良好实践,应该作为教育共享 material,但这似乎是次要的题外话)。也许这是一个简单的错字,但我已经检查并重新检查了,但我根本找不到它。希望有人能够彻底解开困扰我的谜团。

感谢您抽出宝贵时间阅读,这似乎有点长,但我试图做到全面,避免太常见的初始问答乒乓球。毫无疑问,我仍然忽略了一些最重要的东西 - c'est la vie。

这是在 clang 编译器中常量折叠的结果。

讲师正在 Mac 上编译程序,在该平台上“gcc”是“clang”的别名。虽然 gcc 不会为 VLA 执行此折叠,但 clang 会。

来自 clang 文档(版本 10):

Differences between all c* and gnu* modes:

  • c* modes define __STRICT_ANSI__.
  • Target-specific defines not prefixed by underscores, like “linux”, are defined in gnu* modes.
  • Trigraphs default to being off in gnu* modes; they can be enabled by the -trigraphs option.
  • The parser recognizes asm and typeof as keywords in gnu* modes; the variants __asm__ and __typeof__ are recognized in all modes.
  • The Apple “blocks” extension is recognized by default in gnu* modes on some platforms; it can be enabled in any mode with the -fblocks option.
  • Arrays that are VLA’s according to the standard, but which can be constant folded by the frontend are treated as fixed size arrays. This occurs for things like int X[(1, 2)];, which is technically a VLA. c * modes are strictly compliant and treat these as VLAs.