C字符串存储在哪个数据段中? [英] In which data segment is the C string stored?

查看:51
本文介绍了C字符串存储在哪个数据段中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道 char s [] ="hello" char * s ="hello" 有什么区别.

I'm wondering what's the difference between char s[] = "hello" and char *s = "hello".

阅读,我对这个问题仍然不太清楚.

After reading this and this, I'm still not very clear on this question.

据我所知,内存中有五个数据段,分别是文本,BSS,数据,堆栈和堆.

As I know, there are five data segments in memory, Text, BSS, Data, Stack and Heap.

据我了解

如果 char s [] ="hello" :

  1. 你好" 在文本中.
  2. 如果
  3. s 是全局变量,则在Data中;如果是局部变量,则在Stack中.

  1. "hello" is in Text.
  2. s is in Data if it is a global variable or in Stack if it is a local variable.

我们还有存储 s "hello" 的副本,因此我们可以通过 s .

We also have a copy of "hello" where the s is stored, so we can modify the value of this string via s.

如果 char * s ="hello" :

  1. 你好" 在文本中.
  2. s 如果是全局变量,则在Data中;如果是局部变量,则在Stack中.
  3. s 只是指向Text中的"hello" ,我们没有它的副本,因此通过此指针修改string的值应导致"Segmentation错误".
  1. "hello" is in Text.
  2. s is in Data if it is a global variable or in Stack if it is a local variable.
  3. s just points to "hello" in Text and we don't have a copy of it, therefore modifying the value of string via this pointer should cause "Segmentation Fault".

我说得对吗?

推荐答案

您是正确的,第一种情况下的"hello"是 mutable ,第二种情况下的"hello"是 immutable >字符串.并且它们在初始化之前被保存在只读存储器中.

You are right that "hello" for the first case is mutable and for the second case is immutable string. And they are kept in read-only memory before initialization.

在第一种情况下,可变内存是从不可变字符串 初始化/复制的.在第二种情况下,指针指向不可变字符串.

In the first case the mutable memory is initialized/copied from immutable string. In the second case the pointer refers to immutable string.

对于第一种情况,维基百科说,

For first case wikipedia says,

这些变量的值最初存储在只读内存(通常在.text中),然后复制到程序启动过程中的.data段.

The values for these variables are initially stored within the read-only memory (typically within .text) and are copied into the .data segment during the start-up routine of the program.

让我们检查segment.c文件.

Let us examine segment.c file.

char*s = "hello"; // string
char sar[] = "hello"; // string array
char content[32];

int main(int argc, char*argv[]) {
        char psar[] = "parhello"; // local/private string array
        char*ps = "phello"; // private string
        content[0] = 1;
        sar[3] = 1; // OK
        // sar++; // not allowed
        // s[2] = 1; // segmentation fault
        s = sar;
        s[2] = 1; // OK
        psar[3] = 1; // OK
        // ps[2] = 1; // segmentation fault
        ps = psar;
        ps[2] = 1; // OK
        return 0;
}

这是为segment.c文件生成的程序集.请注意, s sar 都在 global aka .data 段中.似乎 sar 是指向可变 已初始化内存的 const指针或根本不是指针(实际上是一个数组)).最终,这暗示着 sizeof(sar)= 6 sizeof(s)= 8 不同.在readonly( .rodata )部分中有"hello"和"phello",并且实际上是 immutable .

Here is the assembly generated for segment.c file. Note that both s and sar is in global aka .data segment. It seems sar is const pointer to a mutable initialized memory or not pointer at all(practically it is an array). And eventually it has an implication that sizeof(sar) = 6 is different to sizeof(s) = 8. There are "hello" and "phello" in readonly(.rodata) section and effectively immutable.

    .file   "segment.c"
    .globl  s
    .section    .rodata
.LC0:
    .string "hello"
    .data
    .align 8
    .type   s, @object
    .size   s, 8
s:
    .quad   .LC0
    .globl  sar
    .type   sar, @object
    .size   sar, 6
sar:
    .string "hello"
    .comm   content,32,32
    .section    .rodata
.LC1:
    .string "phello"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $64, %rsp
    movl    %edi, -52(%rbp)
    movq    %rsi, -64(%rbp)
    movq    %fs:40, %rax
    movq    %rax, -8(%rbp)
    xorl    %eax, %eax
    movl    $1752326512, -32(%rbp)
    movl    $1869376613, -28(%rbp)
    movb    $0, -24(%rbp)
    movq    $.LC1, -40(%rbp)
    movb    $1, content(%rip)
    movb    $1, sar+3(%rip)
    movq    $sar, s(%rip)
    movq    s(%rip), %rax
    addq    $2, %rax
    movb    $1, (%rax)
    movb    $1, -29(%rbp)
    leaq    -32(%rbp), %rax
    movq    %rax, -40(%rbp)
    movq    -40(%rbp), %rax
    addq    $2, %rax
    movb    $1, (%rax)
    movl    $0, %eax
    movq    -8(%rbp), %rdx
    xorq    %fs:40, %rdx
    je  .L2
    call    __stack_chk_fail
.L2:
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
    .section    .note.GNU-stack,"",@progbits

主要还是针对 local 变量,编译器不会费心创建 name .并将其保存在 register stack 内存中.

Again for local variable in main, the compiler does not bother to create a name. And it may keep it in register or in stack memory.

请注意,局部变量值"parhello"已优化为1752326512和1869376613的数字.我通过将"parhello"的值更改为"parhellp"来发现它.程序集输出的差异如下,

Note that local variable value "parhello" is optimized into 1752326512 and 1869376613 numbers. I discovered it by changing the value of "parhello" to "parhellp". The diff of the assembly output is as follows,

39c39
<   movl    $1886153829, -28(%rbp)
---
>   movl    $1869376613, -28(%rbp)

因此,没有为 psar 提供单独的不可变存储.它在代码段中转换为整数.

So there is no separate immutable store for psar . It is turned into integers in the code segment.

这篇关于C字符串存储在哪个数据段中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆