char *str; str=“HELLO”; How does that work without

2019-04-12 07:58发布

问题:

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:

  1. 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?

  2. 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:

  1. 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.

  2. 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.