-3

I wonder the difference of same char* between when it resides in struct and in main() function.

Here is the code:

struct student {
    char* name;
};

int main() {

    // char* in struct
    struct student bob;
    bob.name = "alice";
    bob.name = "bob";
    printf("name: %s\n", bob.name);

    // char* in main()
    char *name = "kim";
    *name = "lee";
    printf("name: %s\n", name);

    return 0;
}

Output:

name: bob
name: kim

In the case of using struct, the value of student bob.name was changed from "alice" to "bob". However, in the latter case, the value of char* name wasn't changed.

I think that the reason why "kim" didn't changed to "lee" is char *name was pointing literal "kim".

If I'm right, why bob.name was changed from "alice" to "bob"? It shoudn't have changed to "bob" because "alice" was also literal.

What's the difference?

Hongmin Yang
  • 71
  • 2
  • 7
  • 6
    one is `name = ...` the other is `*name = ...`? – stijn Oct 16 '17 at 09:17
  • 1
    `*name = "lee";` should not even compile, or you should get at least a warning. – Jabberwocky Oct 16 '17 at 09:19
  • Try `* bob.name = "bob"` to be the same as `* name =`. And always try to have 0 warnings! – i486 Oct 16 '17 at 09:20
  • @MichaelWalz unfortunately it does compile. Unless you have warnings enabled and treat warnings as errors. This is `C` – bolov Oct 16 '17 at 09:21
  • @MichaelWalz I also guessed Visual Studio would show complie error, but it compiled successfully.(i think that line was ignored) – Hongmin Yang Oct 16 '17 at 09:22
  • The compiler doesn't just ignore lines; and VS2017 will show a warning if you use at least /W1 – stijn Oct 16 '17 at 09:26
  • 2
    @bolov The compiler is _required_ to give a diagnostic message for this, by the C standard. If it does so in the form of a warning or error is up to the compiler. And if the programmer chose to ignore the warning, it is then the programmer's problem that the code doesn't work. – Lundin Oct 16 '17 at 09:27
  • @stjin Yeah, There are 1 warning as you said. It was just warning, not compile error as bolov mentioned above. – Hongmin Yang Oct 16 '17 at 09:30
  • Apart from the C syntax violation - the code is not valid C, see [What is the difference between char s and char *s?](https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s) and [Crash or “segmentation fault” when data is copied/scanned/read to an uninitialized pointer](https://stackoverflow.com/questions/37549594/crash-or-segmentation-fault-when-data-is-copied-scanned-read-to-an-uninitializ). – Lundin Oct 16 '17 at 09:33
  • A warning is not "just a warning". While the compiler doesn't immediately stop compiling at this point, it is still some issue that needs to be looked into. – Gerhardh Oct 16 '17 at 10:45

2 Answers2

3

Your code invokes Undefined Behavior,

since you do:

struct student { char* name;};
struct student bob;
bob.name = "alice";

i.e. you are making the pointer name, point to a string literal.

Then you just:

bob.name = "bob";

make the pointer point to another string literal, which is OK, since you just modify where the pointer points to, not the string literal that it points to (for example bob.name[3] = 'f';, which would lead in a Segmentation Fault, since it would attempt to modify a string literal - forbidden).

If you plan to make your pointer point to string literals, then I suggest you declare it that way:

const char* name;

which allows you to change where the pointer points to, but not the contents of the string literal the pointers points to.


Now this:

char *name = "kim";

is a string literal, where its contents cannot be modified. And when you do:

*name = "lee";

you just do something that it's not allowed, resulting an ill-formed program.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 1
    1st case: he doesn't need memory allocation. He just points the pointer to a string literal. That is OK. The only thing that is dangerous is having `char*` instead of `const char*` to point to a string literal, but since he doesn't modify it's contents he gets lucky: it's OK. No UB as far as I can recall the rules for `C` – bolov Oct 16 '17 at 09:22
0

Your example does not compile.

*name = "lee"; // Error 1 error C2440: '=' : cannot convert from 'const char [4]' to 'char'

The reason is that *name points to a char and "lee" is a char[4].

jwdonahue
  • 6,199
  • 2
  • 21
  • 43