Reputation: 64175
Here are 2 type of code snippets which have the same outputs.
char *p = "abc";
::printf("%s",p);
And
::printf("%s","abc");
Is there any difference as to where the "abc" string is stored in memory?
I once heard that in the second code, the "abc" string is placed by the compiler in read-only memory (the .text part?)
How to tell this difference from code if any?
Many thanks.
My current understanding is:
when we write:
char *p="abc"
Though this seems to be only a declarative statement, but indeed the compiler will generate many imperative instructions for it. These instructions will allocate proper space within the stack frame of the containing method, it could be like this:
subl %esp, $4
then the address of "abc" string is moved to that allocated space, it could be like this:
movl $abc_string_address, -4(%ebp)
The "abc" string is stored in the executable file image. But where in the memory it (i mean the string) will be loaded totally depends on the implementation of the compiler/linker, if it is loaded into the read-only part of the process's address space (i.e. the protection bit of the memory page is flagged as read-only), then the p is a read-only pointer, if it is loaded into the r/w part, the p is writable.
Correct me if I am wrong. Now I am looking into the assembly code generated by the gcc to have a confirmation for my understanding. I'll update this thread again shortly.
Upvotes: 0
Views: 216
Reputation: 2004
Yes, it won't be stored in different locations, they are all compile-time know variables, so the compiler will generate the assembly code, and the "abc" string will be on the data segment, that is initialized data. .bss section is for unitialized data.
Try compiling with gcc and the -s option. It will generate a .s
file, which is assembly code. The "abc" variable will be under the .rodata segment, same as .data for NASM assembly.
Here's the assembly code if you don't want to do the work:
This is for char* c = "abc"; printf("%s\n", c); Note how this file has more lines of code than the other one, since this code allocates a pointer variable, and print this variable, the other solution doesn't use a variable, it justs references a static memory address.
.file "test.c"
.section .rodata
.LC0:
.string "abc"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
movl $.LC0, 28(%esp)
movl 28(%esp), %eax
movl %eax, (%esp)
call puts
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
And this is for printf("abc\n");
.file "test2.c"
.section .rodata
.LC0:
.string "abc"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl $.LC0, (%esp)
call puts
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
To your edit:
I don't think any compiler would put p
on a read-only memory, since you declared it as a variable on the code, it's not a hidden/protected variable generated by the compiler, it's a variable you can use whenever you want.
If you do char* p = "abc";
the compiler will sub the pointer's size to the stack, and on the later instruction, it will insert the memory address of the "abc" string (now this is put into read only) into the register, and if the compiler needs register, save it's value to the stack.
If you do printf("abc");
no variable will be alocated, since the compiler knows the string's value at compile time, so it just inserts a number there (relative to the start of the executable file) and it can read the content of that part of the memory.
In this option, you can compile it, generate a .exe, then use a HEX editor, and search for the "abc" string, and change it to "cba" or whatever (probably it will be one of the first lines or one of the last), if the compiler generates a simple .exe like this, which is probable.
Upvotes: 1
Reputation: 490143
No difference besides a char pointer allocated on the stack for the first one.
They both use a string literal, delimited by double quotes.
Upvotes: 1
Reputation: 124632
Is there any difference as to where the "abc" string is stored in memory?
Nope, and that is true for both. String literals are stored in the read-only segment. However, if you declare your variable as a char[] it will be copied onto the stack, i.e., not read only.
Upvotes: 3
Reputation: 798526
There is no difference in where the string literal is stored. The only difference is that the former also allocates space on the stack for the variable to store the pointer.
Upvotes: 3