【发布时间】:2018-12-21 08:52:02
【问题描述】:
根据this thread,用较短的字符串字面量初始化数组会用零填充数组。
那么,为什么这两个函数(test1 和 test2)在为 ARM Cortex M4 编译时会产生不同的结果?
extern void write(char * buff);
void test1(void)
{
char buff[8] = {'t', 'e', 's', 't', 0, 0, 0, 0 };
write(buff);
}
void test2(void)
{
char buff[8] = "test";
write(buff);
}
我收到了equivalent assemblies for x86-64,但在 ARM gcc 上我收到了different output:
test1:
str lr, [sp, #-4]!
sub sp, sp, #12
mov r3, sp
ldr r2, .L4
ldm r2, {r0, r1}
stm r3, {r0, r1}
mov r0, r3
bl write
add sp, sp, #12
ldr pc, [sp], #4
.L4:
.word .LANCHOR0
test2:
mov r3, #0
str lr, [sp, #-4]!
ldr r2, .L8
sub sp, sp, #12
ldm r2, {r0, r1}
str r0, [sp]
mov r0, sp
strb r1, [sp, #4]
strb r3, [sp, #5]
strb r3, [sp, #6]
strb r3, [sp, #7]
bl write
add sp, sp, #12
ldr pc, [sp], #4
.L8:
.word .LANCHOR0+8
【问题讨论】:
-
就 C 标准而言,它们是等价的。尽管允许编译器跳过在空终止符之后写入零,但如果它可以推断出
\0之后的内存没有被使用(由于外部链接,它不能在这里使用)。因此,这似乎是某种错误。如果我将test2更改为char buff[8] = "test\0\0\0";(4 个尾随零),我也会在 ARM 上获得相同的机器代码。 -
顺便说一句:如果你也使用
{'t', 'e', 's', 't', 0 },buff 也会被0填满。我希望这会产生与字符串文字版本相同的汇编器输出。 -
@StephanLechner: it does,除非使用 arm gcc 进行编译。
-
x86-64 是一个 64 位架构(并且免费将 32 位立即数零扩展为 64 位),因此两个版本都使用单个 qword 存储区的多种原因也就不足为奇了。如果您将数组设为 9 字节长,并添加第 5 个非零字节 (godbolt.org/z/Xk-vLP),您将获得与 gcc 截然不同的代码(带有一些愚蠢的 test1 代码),但 clang 仍然为两者制作相同的好代码。跨度>
标签: c gcc assembly arm array-initialization