I can get non-const pointer to const object?!!
-
Badestrand schrieb:
So when you'll write
char* a = "abc"; char* b = "abc";
, both should point to the same location. If I'm right and these strings are placed in some readonly-section, then modifing these strings will cause an error. However, temporary objects would be fatal because no-one would be able to clean up afterwards.
But you are wrong. Just test it:
char* a = "abc"; char* b = "abc"; cout<<&a<<" "<<&b<<endl; a = "xyz"; cout<<a<<endl;
The addresses of a and b are not the same. b is 4 Bytes later.
And the char* variables aren't read-only, either. At the example above, I get "xyz" as output.
-
Try this out:
char* a = "abc"; char* b = "abc"; std::cout << reinterpret_cast<int>(a) << " " << reinterpret_cast<int>(b) << std::endl;
Of course do the variables a and b have different addresses, but what I wanted to claim is that the string-literals are at the same address*. And those string-literals should be constant, I'm getting a memory-error with
a[0] = 'h';
* So the variables a and b point to the same address. So even if no error occurs, this would give you something unexpected:
//Somewhere char* a = "abc"; a[0] = 'd'; // Somewhere else char* b = "abc"; std::cout << b << std::endl; // would print "dbc"
-
Badestrand schrieb:
* So the variables a and b point to the same address. So even if no error occurs, this would give you something unexpected:
//Somewhere char* a = "abc"; a[0] = 'd'; // Somewhere else char* b = "abc"; std::cout << b << std::endl; // would print "dbc"
No, it wouldn't. If you don't believe, just try it out. I get the output "abc".
But the thing that is strange, if you change a single character and diplay it, you get the first time the new (changed) character, but the 2nd time, it's the old one againchar* a = "abc"; a[0] = 'd'; // Somewhere else char* b = "abc"; std::cout << a[0] << std::endl; // output "d" std::cout << a[0] << std::endl; // output "a" std::cout << b[0] << std::endl; // output "a" std::cout << a << std::endl; // output "abc" std::cout << b << std::endl; // output "abc"
-
Hm. I think our compilers handle that differently and they possibly are allowed to, since this is undefined behaviour (as camper said). With my MSVC++ 2005 Express I'm not able to change a[0], so I cannot try what would be written
But it seems that you're right that I am wrong; at least the implementation of handling string-literals seems to be compiler-dependent. I thought it would be popular to put those string-literals to read-only-sections and let all pointers point to those locations.
PS: What compiler are you working with? GCC?
-
point-getter schrieb:
i dont get the point, why should the string be a const object?
The string-literal is a constant object with static storage duration because the standard says so.
point-getter schrieb:
well, a char array behaves just like a pointer to char, so i can use it in the same way and i can also do the same things with both.
almost. There is an implicit conversion from array of T to rvalue pointer to T. That doesn't mean that there aren't differences in any places, sizeof being a prominent example. Similarly, an expression of function can be converted to a pointer to function and thus behaves alsmost the same way. They are still distinct types though (more obvious too: one is an object type while the other is not).
Badestrand schrieb:
I think those constant strings are placed in a readyonly-section in the RAM. So when you'll write
char* a = "abc"; char* b = "abc";
, both should point to the same location.
That is unspecified. Two string-literals with the same content may share the same address but needn't to.
assert("foo"=="foo");
may fail sometimes and sometimes not (some compilers have switches to influence this behaviour).
Thinking of read-only RAM is probably not the best explanation - while that can be true sometimes, usually normal programs on your average desktop computer do not use such memory. The may-not-be-modified restriction allows the compiler to assume that it contents does not change and thus possibly enable more aggressive optimization, for examplechar* foo = "bar"; cout<<foo[0];
doesn't actually have to use foo but may directly call the <<-operator with 'b' as argument.
-
Thank you for clearing this
-
camper schrieb:
There is a (deprecated) conversion from array of const char (array of const wchar_t) to pointer to char (pointer to wchar_t) if and only if such a pointer object is being initialised by a string literal. This conversion exists as a compatibility feature. However, attempting to modify a string literal through such a pointer is undefined.
You see, this deprecated conversion is sometimes surprising people. Is there a way to disable this conversion (by compiler command-line switches, for example) ?
Undefined behaviour seams to be very undefined...
-
Badestrand schrieb:
And those string-literals should be constant, I'm getting a memory-error with
a[0] = 'h';
For me it depends of the compiler mode. In "debug" mode I'm getting memory-error. But in "release" mode there is no error (but some fancy results due to compiler optimisations, may be).
By the way, placing of the same (sub)strings in one memory location is called "string pooling". There is a key /GF in Microsoft compiler, allowing (but not forcing) it to do that pooling. It needed sometimes to reduce the size of .exe file.
-
Badestrand schrieb:
PS: What compiler are you working with? GCC?
No, I'm using Microsoft Visual C++ 2008 Express Edition.
Thank you, I didn't know about this undefined conversion behaviour... If you initialize char-Arrays always with []-bracks and without pointers, you won't get any problems, will you?
-
What about using C++ std::strings instead of oldscool C-Style memory-leak-prone char-arrays and pointers?