Tho*_*rio 2 c arrays gcc compiler-errors riscv
我正在初始化一个由 1 和 0 组成的 32 元素数组,作为 C 中生命游戏的起始状态。当我使用这一行时:
int board[] = {0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0};
Run Code Online (Sandbox Code Playgroud)
编译没有问题。但是,当我只是更改数组中的值,而不是数组的长度或声明时:
int board[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Run Code Online (Sandbox Code Playgroud)
该代码不会编译,而是生成“对‘memset’的未定义引用。”。这是我编译时遇到的错误:
[ubuntu@swell-dipper:~/OS/assiqnment2/c-and-assemblvA] $ make
riscv64-unknown-elf-gcc -O -march=rv32im -mabi=ilp32 -g -c main.c -o main.o
riscv64-unknown-elf-gcc -O -march=rv32im -mabi=ilp32 -g -c lib.c -o lib.o
riscv64-unknown-elf-as -march=rv32im -g -c calc_val.s -o calc_val.o
riscv64-unknown-elf-gcc -O -march=rv32im -mabi.ilp32 -g -c simulation.c \
-o simulation.o
riscv64-unknown-elf-ld -nostdlib -o simulation -Map simulation.map \
-T demo.lds crt0.0 main.o lib.o calc_val.o simulation.o
riscv64-unknown-elf-ld: main.o: in function 'main':
/home/ubuntu/OS/assignment2/c-and-assembly/q2/main.c:23:
undefined reference to 'memset'
make: *** [Makefile:58: simulation] Error 1
Run Code Online (Sandbox Code Playgroud)
完全相同的代码,只是数组元素具有不同的值,怎么可能无法编译?memset我也从未在任何地方的代码中使用过任何与 相关的内容。
我为数组的元素尝试了一些不同的值,无论代码是否编译,它都是打开和关闭的。
你ld自己在跑。这几乎总是一个错误。使用gcc“编译器驱动程序”进行链接,并从链接命令行中删除-nostdlib和crt0.o,问题就会消失。
发生的情况是编译器可能选择为第二个数组初始化生成代码,就像您编写的一样
int board[32];
memset(board, 0, sizeof board);
board[K] = 1;
Run Code Online (Sandbox Code Playgroud)
其中 K 是数组初始值设定项中单个 1 的位置。这是完全可以允许的;C 标准规定编译器可以生成对任何C 库函数的调用,即使它们没有出现在源代码中。您可以使用命令行选项使 GCC不太-ffreestanding愿意这样做,但它不会完全消除这些“合成”调用。 GCC手册的2.1节特别指出,即使在-ffreestanding模式下,它也可能生成对memcpy、memmove、memset和memcmp。
GCC 还可以生成对其自己的内部运行时库中的函数的调用,无论它是否处于独立模式。它们用于硬件不提供指令的算术运算之类的事情。
当您使用编译器驱动程序进行链接时,C 库、内部运行时库以及一些处理 C++ 全局构造函数等内容的“启动文件”都会自动包含在链接中,因此所有这些对您来说都是不可见的。使用ld绕过这一点并暴露了代码生成需要这些东西的事实,即使您认为不需要。原则上,您可以gcc -v使用查找所有额外隐式内容的名称,并仅添加回您需要的位,但几乎可以肯定,仅使用编译器驱动程序进行链接会更容易。