C字符串存储在哪个数据段中? [英] In which data segment is the C string stored?
问题描述
我想知道 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"
:
-
你好"
在文本中. 如果 -
s
是全局变量,则在Data中;如果是局部变量,则在Stack中.
"hello"
is in Text.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"
:
-
你好"
在文本中. -
s
如果是全局变量,则在Data中;如果是局部变量,则在Stack中. -
s
只是指向Text中的"hello"
,我们没有它的副本,因此通过此指针修改string的值应导致"Segmentation错误".
"hello"
is in Text.s
is in Data if it is a global variable or in Stack if it is a local variable.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屋!