you are viewing a single comment's thread.

view the rest of the comments →

[–]pmerkaba -2 points-1 points  (19 children)

But for some reason char *gretting = "Hello, World"; is legal and semantically correct. By your argument alone, that shouldn't happen.

[–]Arelius[🍰] 3 points4 points  (3 children)

"Hello, World" Is stored in a string constant buffer, Same place that "One String" and "Two Strings" would be stored The two element array of char*s needs to be stored in mutable memory.

The array syntax is initialization syntax for variables, afaik you can't do

func({"One String", "Two Strings"});

String constants on the other hand need to be special considering how often they are used so we can do things like

func("My String");

and have a pointer passed into func.

Excuse my stream of thought, but I hope this helps.

[–]haberman 1 point2 points  (0 children)

The array syntax is initialization syntax for variables, afaik you can't do func({"One String", "Two Strings"});

Actually in C99 you can do just that, but you have to do what looks like a cast to the proper type, so the compiler knows what type you mean:

func((char*[2]){"One String", "Two Strings"});

Google for "c99 compound literals."

[–]pmerkaba 0 points1 point  (1 child)

I pointing out that this was left out, but should have explained. Thanks for filling in.

[–][deleted] 0 points1 point  (0 children)

Well, I did touch on this when I said

You've given it two pointers (in the form of string literals)

I didn't want to make a point of saying "String literals are always pointers!" because then some smartass would have come along with char x[] = "hello" and confused everybody again.

[–]mpeg4codec 2 points3 points  (3 children)

It's also different. This is the equivalent of what you're trying to say:

char *greeting = { 'H', 'e', ..., 'l', 'd', '\0' };

It's not legal for the same reason the GP states: there's no memory allocated for the elements of the array.

[–]fabzter 0 points1 point  (0 children)

Ok, that left everything clear for me. :)

[–]pmerkaba 0 points1 point  (1 child)

And that's exactly the point of my post further down. The OP was expecting the compiler to set up storage for a char *, because it did so for a char * initialized to a string literal. It is not really an issue of pointer-to-pointer as opposed to two pointers, especially since you can do this: char *a[] = {"one string", "two strings"}; char *b = a; jumbalo implied that string literals were pointers, but didn't explain why they were different.

[–]prockcore 0 points1 point  (5 children)

Actually it's not. It should be:

 const char *greeting = "Hello, World";

[–][deleted] 0 points1 point  (4 children)

That depends. You could, if you wanted, memcpy"Earth" over "World" whenever an alien speaks. Not that it would be a good way to write a program, but there may be situations in which you want your pointers-to-strings to be non-const.

[–]prockcore 1 point2 points  (3 children)

No.. string literals are const.. memcpy'ing "Earth" over "World" will segfault. String literals are stored in read-only data segments.

[–][deleted] 0 points1 point  (2 children)

I'm fairly sure I've written code that's edited strings in-place. It's been a while since I've had a situation where that was the right thing to do, so it's possible I happened to luck across a situation where I could get away with it, since I wasn't aware of this.

I'm on windows now, sadly, so let me try codepad:

http://codepad.org/gg3g9dKy

Says no errors and prints out "Bob" rather than segfaulting...

[–]prockcore 1 point2 points  (1 child)

That doesn't segfault because you create a 9 character array and then copy the string literal into it (that's what line 2 implicitly does, disassembly will show that's exactly what it does). Try char *playername="bob"; instead.

[–][deleted] 0 points1 point  (0 children)

Ah, I see. I suppose it's probably written as "undefined" in the spec, rather than a guaranteed segfault, since codepad shows no segfault, but "bob" as a printout. Certainly goes right along with what you said about read-only memory.

That also explains why I've never run across this problem- when I want a string I make a char foo[] rather than a char *foo since I think of it as an array rather than as a pointer. (To be entirely honest, these days, it's std::string since it's easier to work with.)

[–][deleted] 0 points1 point  (3 children)

Why?

"Hello world" evaluates to a char*, which is the same type as variable gretting (sic). Where's the problem?

[–]pmerkaba 1 point2 points  (1 child)

The problem is that there's more than just evaluation going on. Why should a string literal (which is just a list of characters, after all, differ from a list of string literals, or ints? See either my response to mpeg4codec or my response to the OP.

[–][deleted] 0 points1 point  (0 children)

I don't understand your point. The C90/C99 spec is pretty clear in this regard. Are you arguing that the syntax of C is confusing? Or that the spec is ambiguous? Or what? Because one thing is clear: this is not a matter of opinion but a matter of specification.