C 代码编译成奇怪的指令[重复]

问题描述 投票:0回答:1
#include<stdio.h>
#include<stdlib.h>

int main(int argc, char** argv) {
  char *str5=malloc(10);
  *str5="xxxxx\0";
  printf("%s\n",str5);
  return 0;
}

编译成以下程序集(使用“gcc source.c”):

=> 0x555555555179 <main+4>:     sub    rsp,0x20
   0x55555555517d <main+8>:     mov    DWORD PTR [rbp-0x14],edi
   0x555555555180 <main+11>:    mov    QWORD PTR [rbp-0x20],rsi
   0x555555555184 <main+15>:    mov    edi,0xa
   0x555555555189 <main+20>:    call   0x555555555040 <malloc@plt>
   0x55555555518e <main+25>:    mov    QWORD PTR [rbp-0x8],rax
   0x555555555192 <main+29>:    lea    rax,[rip+0xe6b]        # 0x555555556004
   0x555555555199 <main+36>:    mov    edx,eax
   0x55555555519b <main+38>:    mov    rax,QWORD PTR [rbp-0x8]
   0x55555555519f <main+42>:    mov    BYTE PTR [rax],dl
   0x5555555551a1 <main+44>:    mov    rax,QWORD PTR [rbp-0x8]
   0x5555555551a5 <main+48>:    mov    rdi,rax
   0x5555555551a8 <main+51>:    call   0x555555555030 <puts@plt>
   0x5555555551ad <main+56>:    mov    eax,0x0
   0x5555555551b2 <main+61>:    leave
   0x5555555551b3 <main+62>:    ret
   0x5555555551b4 <_fini>:      sub    rsp,0x8
   0x5555555551b8 <_fini+4>:    add    rsp,0x8
   0x5555555551bc <_fini+8>:    ret

编辑- 澄清一下,我不是问如何正确复制或分配字符串 - 我知道如何做到这一点。我问为什么这套特定的指令以这种方式编译。所选答案很好地回答了这个问题。 -结束编辑。

实际发生的情况: 因此,在 main+42 上,它将 $dl (字符串常量“xxxxx”的地址的最低字节加载到 $rax 指向的地址中,即我的变量 str5。这最终只是一个垃圾字符,并且字符串常量的其余部分永远不会被复制。编译器会发出以下警告,这可能是相关的,但我不明白如何:

source.c:6:14: warning: assignment to ‘char’ from ‘char *’ makes integer from pointer without a cast [-Wint-conversion]

我期望发生什么: 字符串常量“xxxxx”被加载到str5指向的地址中。然后,str5指向的字符串被打印到屏幕上。 为什么 gcc 这样编译这段代码?

c gcc
1个回答
4
投票

在 C

*str5="xxxxx\0";
中不复制字符串。

这个操作其实是:

  • 获取字符串文字的地址
    "xxxxx\0"
  • 将此地址转换为
    char
    (这是一个整数)
  • malloc
    分配的内存的第一个字符分配为该整数值

打印时,第一个字符是字符形式的整数。其余字符未初始化,此代码调用未定义的行为。

如果你想复制字符串文字,你需要

strcpy(str, "xxxxx");
(字符串文字将有空终止字符,你不需要自己把它放在那里) 所以编译器是正确的,它正在为您编写的程序生成代码。

© www.soinside.com 2019 - 2024. All rights reserved.