可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Code:
#include <stdio.h>
int main() {
char *str;
char i = 'a';
str = &i;
str = "Hello";
printf("%s, %c, %x, %x", str, i, str, &i);
return 0;
}
I get this output:
Hello, a, 403064, 28ff0b
I have following two doubts:
How can I store a string without allocating any memory for it. str
is a character pointer and is pointing to where char variable i
. When I add str = "Hello";
aren't I using 5
bytes from that location 4
of which are not allocated?
Since, I code str = &i;
shouldn't str
and &i
have same value when I printf them? When I remove the str = "Hello";
statement str
and &i
are same. And if str
and &i
are same then I believe when I say str = "Hello"
it should overwrite 'a'
with 'H'
and the rest 'ello\0'
come into the subsequent bytes.
I believe the whole problem is with str = "Hello"
statement. It doesn't seem to be working like what I think.
Please someone explain how it works??
回答1:
When the compiler encounters a string literal, in this case "Hello"
, memory is allocated in the static (global) memory area. This "allocation" is done before your program executes.
When your program starts executing at main
, a stack frame is allocated to store the local variables of main
: str
and i
. Note that str
is a simple variable that just stores an address. It does not store any characters. It just stores a pointer.
The statement str = &i;
writes into variable str
the address of i
.
The statement str = "Hello"
writes into the variable str
, the address of the string literal "Hello"
which has been pre-allocated by the compiler. This is a completely different address than that of i
. That assignment does not move any of the characters in the word "Hello" anywhere at all.
TL;DR the value of a "string" variable in C is just a pointer. Assigning to a string variable is assigning a number, namely an address.
回答2:
The compiler writes the sequence of bytes { 'H', 'E', 'L', 'L', 'O', '\0' } in a section of the executable called the data segment.
When the application runs, it takes the address of these bytes and stores them in the variable representing 'str'.
It doesn't have to "allocate" memory in the sense that, at run time, the program does not have to ask the OS for memory to store the text.
You should try to avoid treating string literals like this as non-const. GCC's "-Wall" option promotes assignment of string literals to "char*" pointers as
warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
Many compilers, when compiling with optimization, will do something called "string pooling", which avoids duplicating strings.
const char* str1 = "hello";
const char* str2 = "hello";
If compiled with string pooling, the executable might only contain one instance of "hello".
回答3:
When I say str = "Hello" aren't I using 5 bytes from that location 4
of which are not allocated?
No. The compiler sets aside 6 bytes (remember the null terminator) in a different part of memory (a read-only part, but that's an answer to a different question). The assignment:
str = "Hello";
causes str
to point to the location of the first of these 6 bytes, the H
.
Since, I said str=&i; shoudln't str and &i have same value when I
printf them?
Yes, but you set str
to point to something else on the very next line, before you printed anything.
回答4:
The literal string "Hello"
is taking 6 bytes of memory somewhere, probably in the program space. Assigning the pointer to it just sets the pointer to where the string already exists. It doesn't copy the characters at all.
If you wanted to copy the characters you would need to use strcpy
, but as you did not set the pointer to a writable buffer of sufficient size it would cause undefined behavior if you did.
回答5:
str
is a pointer to a char. When you say str = &i;
you are pointing it to an int. When you say str = "Hello";
you are changing str to point to a location where the character sequence 'H', 'e', 'l', 'l', 'o', 0 is stored.
But you say str = something else
right after you say str = &i
Looks like you haven't quite grasped pointers yet...
回答6:
Okay, simply put, every string is a pointer in C.
If we run with this:
int main() {
char *str;
char i='a';
str = &i;
str = "Hello";
printf("%s, %c, %x, %x", str, i, str, &i);
return 0;
}
When you set str = &i
, you are making str
point to i
. Thus, i == *str
and &i == str
hold true.
When you call str = "Hello";
, str
now points to a statically allocated array of size 6 (this usually resides directly in your program code). Because str
is a pointer, when you reset it to point to the new array, it makes no change to i
. Now, if instead of setting str
to "Hello"
, we did *str = 'Z';
, i
would now have the value of 'Z', while str
still points to i
.
回答7:
First how can I store the string without allocating any memory for it. str is a chracter pointer and is pointing to where char i is stored. When I say str = "Hello" aren't I using 5 bytes from that location 4 of which are not allocated?
The memory for the string is allocated by the compiler. I don't think the standard specifies exactly how the compiler must do this. If you run 'strings' against your executable, you should find "Hello" in there somewhere.
Since, I said str=&i; shoudln't str and &i have same value when I printf them? When I remove the str = "Hello" statement str and &i are same. And if str and &i are same then I believe when I say str="Hello" it should overwrite 'a' with 'H' and the rest 'ello\0' come into the subsequent bytes.
I think what you are missing here is that str = "Hello" does not copy the string to the location pointed to by str. It changes what str points to. "Hello" is in memory and you are assigning that memory location to the pointer. If you want to copy memory to a pointer, you need to use memcpy() or something similar.