If cstring is a pointer, then why can it get a value directly? Secondly, Why wasn't the *cstring's result equal to whole of string? Third, cstring is a non-constant pointer to a constant character, so why change its value and not change its address?
#include <cstdio>
#include <conio.h>
#include <iostream>
using namespace std;
int main()
{
const char* cstring = "string";
cout << cstring << endl << *cstring << endl << &cstring << endl;
cstring = "foo";
cout << cstring << endl << *cstring << endl << &cstring << endl;
_getch();
return 0;
}
If cstring is a pointer, then why can it get a value directly?
The operator << of cout for const char* is specialized to behave that way. It will treat the pointer as a NULL terminated string and will print it instead of the pointer value. For different types you get different behaviour. For char* you have the whole string printed.
Why wasn't the *cstring's result equal to whole of string?
That is because the type of *cstring is char and again, operator << behaves correctly by just printing a single char. a const char* is essentially an array of char.An array is essentially a pointer to the first element of the array. If you use the * operator on a pointer you are accessing whatever the pointer points to. If it points to the first element, well, you get the first element.
Third, cstring is a non-constant pointer to a constant character, so why change its value and not change its address?
As you said, cstring is a non-constant pointer to constant data. You cannot change the place it points to (it is a constant pointer), but you can substitute the content of the pointed data with other stuff. You point to the same location but the content of that cell changes.
If cstring is a pointer, then why can it get a value directly?
Anyone can get the value pointed at by a pointer by dereferencing the pointer. That's what happens when you do std::cout << cstring. The proper overload gets chosen that prints the string represented by cstring assuming that is correctly formed, null-terminated C-style string.
Secondly, Why wasn't the *cstring's result equal to whole of
string?
cstring is a const char*, so *cstring is a const char. Pass that to std::cout and it will call an overload that prints one char. The function that is called internally doesn't even know that this is just one char in a string.
Third, cstring is a non-constant pointer to a constant character, so
why change its value and not change its address?
You can't change the address of a variable. cstring is in a fixed place on the stack. You change the value of cstring, which is the address of the string that it's pointing to (it is now pointing to a different string, which has a different address, "string" of course stil has the same address).
What you probably wanted to try is this:
const char* cstring = "string";
std::cout << (void*)cstring << std::endl;
cstring = "foo";
std::cout << (void*)cstring << std::endl;
Now you can see the different addresses. One is the address of "string" and one is the address of "foo".
Related
I have a const char pointer which I know for sure came from a string. For example:
std::string myString = "Hello World!";
const char* myCstring = myString.c_str();
In my case I know myCstring came from a string, but I no longer have access to that string (I received the const char* from a function call, and I cannot modify the function's argument list).
Given that I know myCstring points to contents of an existing string, is there any way to safely access the pointer of the parent string from which it originated? For example, could I do something like this?
std::string* hackyStringPointer = myCstring - 6; //Along with whatever pointer casting stuff may be needed
My concern is that perhaps the string's contents possibly cannot be guaranteed to be stored in contiguous memory on some or all platforms, etc.
Given that I know myCstring points to contents of an existing string, is there any way to safely access the pointer of the parent string from which it originated?
No, there is no way to obtain a valid std::string* pointer from a const char* pointer to character data that belongs to a std::string.
I received the const char* from a function call, and I cannot modify the function's argument list
Your only option in this situation would be if you can pass a pointer to the std::string itself as the actual const char* pointer, but that will only work if whatever is calling your function does not interpret the const char* in any way (and certainly not as a null-terminated C string), eg:
void doSomething(void (*func)(const char*), const char *data)
{
...
func(data);
...
}
void myFunc(const char *myCstring)
{
std::string* hackyStringPointer = reinterpret_cast<std::string*>(myCstring);
...
}
...
std::string myString = "Hello World!";
doSomething(&myFunc, reinterpret_cast<char*>(&myString));
You cannot convert a const char* that you get from std::string::c_str() to a std::string*. The reason you can't do this is because c_str() returns a pointer to the string data, not the string object itself.
If you are trying to get std::string so you can use it's member functions then what you can do is wrap myCstring in a std::string_view. This is a non-copying wrapper that lets you treat a c-string like it is a std::string. To do that you would need something like
std::string_view sv{myCstring, std::strlen(myCstring)};
// use sv here like it was a std::string
Yes (it seems), although I agree that if I need to do this it's likely a sign that my code needs reworking in general. Nevertheless, the answer seems to be that the string pointer resides 4 words before the const char* which c_str() returns, and I did recover a string* from a const char* belonging to a string.
#include <string>
#include <iostream>
std::string myString = "Hello World!";
const char* myCstring = myString.c_str();
unsigned int strPtrSize = sizeof(std::string*);
unsigned int cStrPtrSize = sizeof(const char*);
long strAddress = reinterpret_cast<std::size_t>(&myString);
long cStrAddress = reinterpret_cast<std::size_t>(myCstring);
long addressDifference = strAddress - cStrAddress;
long estStrAddress = cStrAddress + addressDifference;
std::string* hackyStringPointer = reinterpret_cast<std::string*>(estStrAddress);
cout << "Size of String* " << strPtrSize << ", Size of const char*: " << cStrPtrSize << "\n";
cout << "String Address: " << strAddress << ", C String Address: " << cStrAddress << "\n";
cout << "Address Difference: " << addressDifference << "\n";
cout << "Estimated String Address " << estStrAddress << "\n";
cout << "Hacky String: " << *hackyStringPointer << "\n";
//If any of these asserts trigger on any platform, I may need to re-evaluate my answer
assert(addressDifference == -4);
assert(strPtrSize == cStrPtrSize);
assert(hackyStringPointer == &myString);
The output of this is as follows:
Size of String* 4, Size of const char*: 4
String Address: 15725656, C String Address: 15725660
Address Difference: -4
Estimated String Address: 15725656
Hacky String: Hello World!
It seems to work so far. If someone can show that the address difference between a string and its c_str() can change over time on the same platform, or if all members of a string are not guaranteed to reside in contiguous memory, I'll change my answer to "No."
This reference says
The pointer returned may be invalidated by further calls to other member functions that modify the object.
You say you got the char* from a function call, this means you do not know what happens to the string in the mean time, is that right? If you know that the original string is not changed or deleted (e.g. gets out of scope and thus is destructed) then you can still use the char*.
Your example code however has multiple problems. You want to do this:
std::string* hackyStringPointer = myCstring - 6;
but I think you meant
char* hackyStringPointer = myCstring;
One, you cannot cast the char* to a string* and second you do not want to go BEFORE the start of the char*. The char* points to the first character of the string, you can use it to access the characters up to the trailing 0 character. But you should not go before the first or after the trailing 0 character though, as you do not know what is in that memory or if it even exists.
I get really weird output from the last cout statement, no idea what would be causing this:
char ex1_val = 'A';
char* ex1;
ex1 = &ex1_val;
cout << *ex1 << endl;
char** ex2;
ex2 = &ex1;
cout << *ex2 << endl;
Here's my output:
A
A����
ex2 is declared as char**, which means it's a pointer to a pointer to char.
When you print the contents of *ex2, you're dereferencing it once, so type of *ex2 is a pointer to char.
Effectively, the compiler assumes, that you want to print a C-style string, which is a NULL-terminated string. So it prints all bytes stored in memory, starting from A stored in ex1_val, followed by random values stored directly after that, until a NULL character is encoutered.
This is actually a very bad situation, as you never know when or if there's a NULL in memory. You might end up trying to access a memory area you're not allowed to use, which may result in crashing the application. This is an example of an undefined behaviour (UB).
To print out the actual contents of ex1_val via the ex2 pointer, you'd need to make it like this:
cout << **ex2 << endl;
where typeof(**ex2) is an actual char.
When you dereference ex2 (in *ex2) you get a pointer to a char (i.e. char*), and the operator<< overload to handle char* outputs it as a C-style zero-terminated string.
Since *ex2 doesn't point to a zero-terminated string, only a single character, you get undefined behavior.
You want to do cout << **ex2 << endl;
ex2, as you have declared it, as a pointer to a pointer to a character. Doing *ex2 only gets you the address of the pointer it is pointing to.
To recreate this little problem of mine use this code (Yes it's bruteforced and could be slimmed down):
char hello[] = "John";
char *ptr1 = &hello[0];
char *ptr2 = &hello[1];
char *ptr3 = &hello[2];
char *ptr4 = &hello[3];
std::cout << ptr1 << "$";
std::cout << ptr2 << "$";
std::cout << ptr3 << "$";
std::cout << ptr4 << "$";
as you may see after trying this code, it returns the following:
John$ohn$hn$n$
I have no idea why it takes all elements after the specified one.
Any help?
It's because you're printing the pointer, not the thing it points to. And char pointers in C programs often point to the start of a char[] which represents a '\0'-terminated string. That is why std::ostream (of which cout is an instance) has an overloaded << operator that outputs the entire string, up to the terminator.
To print just the character, dereference the pointers first:
std::cout << *ptr1 << "$";
You could also use references instead, which are treated largely as a substitute for the value itself:
char &ptr1 = hello[0];
ptr1 through ptr4 are also pointers to characters, therefore << will treat them as strings, and print them as such, giving you what you saw.
If you just want the characters at each location, lines of the form:
char ch1 = hello[0];
will work, as will changing the output to:
std::cout << *ptr1 << "$";
Your question seems to be based on some completely unfounded expectations. It looks like you expected your code to print a single character for each cout << ... line. But why did you expect it to do that? What you send to cout in your code is actually a char * pointer. Why did you expect cout to dereference that pointer for you and print the character? A normal thing to expect would be to see the pointer value in the output (the address), not the character value.
So, the question you should really be asking is not "why it prints several characters from my array?". The question you should really be asking is "why it prints any of my characters at all?". You never dereferenced your pointer. Yet, instead of pointer value the output contains a sequence of char objects that pointer was pointing to. I.e. apparently cout decided to dereference your pointer for you, even though you never explicitly asked it to. That is the question you should be asking: why did my pointer get dereferenced at all?
And the answer is that [const] char * pointers receive special treatment when sent to cout using << operator. There's a dedicated overloaded version of << operator introduced specifically for that purpose. That version of << operator will treat char * pointers as pointing to the beginning of a C-string. And that operator will output the entire C-string all the way to the zero terminator character. That is exactly what is happening in your experiment.
Note that if you use any other pointer type (like int *) for example, you will not see the pointed value (or values) in the output. You will see the implementation-dependent representation of the pointer itself.
if you want to print value at particular address then :
std::cout << *ptr1 << "$";
std::cout << *ptr2 << "$";
std::cout << *ptr3 << "$";
std::cout << *ptr4 << "$";
I am not entirely sure but if it cout receives a char pointer, it will print, everything until it reaches a blank in memory, (C style character string), and if you just want to print a character, you should print only the content of the variable, that means just pass the content not the memory location...
This question already has answers here:
C++ return string keeps getting junk
(1 answer)
ostream cout and char *
(3 answers)
Closed 8 years ago.
I'm new in c++. I wrote this program.
#include <iostream>
using namespace std;
int main(void) {
int x=24;
char y='A';
char* pchar=&y;
int* pint=&x;
cout <<"pchar= "<<hex<<&pchar<<endl;
cout <<"pint = "<<hex<<&pint<<endl;
cout <<endl;
cout <<"pchar= "<<hex<<pchar<<endl;
cout <<"pint = "<<hex<<pint<<endl;
pchar=NULL;
pint=NULL;
getchar();
return 0;
}
and its result
Can you help me to understand why I can't print the address of variables without &?
I think pchar is already the address of y.
thanks
When you use a char* (like your variable pchar) the string overload of operator<< function is used, and when treating it as a string it will print characters until it find the string terminator character ('\0'). Unfortunately in this case pchar points only to a single character, so you have undefined behavior as the function goes out looking for characters in memory not allocated to you.
To print a pointer you have to cast it to void*:
std::cout << "pchar = " << std::hex << reinterpret_cast<void*>(pchar) << '\n';
It works when you print the address of the variable pchar (when you print &pchar) because then the type of the expression is of type char** which have no direct overload, and instead uses the generic pointer overload (case 7 in this reference).
Operator << treated char* as a string. But you can change your code to following
cout <<"pchar= "<<hex<<(void*)pchar<<endl;
It should work.
I cannot access std code now, but cout implementation should contain something like this
operator << (char* char_ptr)
{
//interpret char * as pointer to null-terminated string
... code to output string
}
So there is impossible to print char* as address without casting to something.
You'll need
cout <<"pchar= "<<hex<<static_cast<void*>(pchar)<<endl;
to print the value of pchar (not its address, that would be the address of the variable pchar, not the address to which it points to).
It behaves like this because std::ostream (cout's type) has an overloaded operator<< which takes a char* and treats it specifically to print out a string.
Change this statement
cout <<"pchar= "<<hex<<pchar<<endl;
to
cout <<"pchar= "<<hex<< ( const void * )pchar<<endl;
The problem is that when you write this way
cout <<"pchar= "<<hex<<pchar<<endl;
the compiler considers pchar as an address of the first element of a string and tries to output this string. There is an overloaded operator << for type char * and it is called in this case.
pchar value is address of y. So if you print pchar it will print address of y. &pchar, it will print address of pchar. Remember pchar also have some address.
I have doubts regarding following statments;
int intvalue = 3;
int *pointInt = &intvalue;
char* p = "string";
cout << pointInt << std::endl; // this will give memory location of intvalue which is ok.
cout << p<< std::endl; // why this will give string value rather than memory location of where string is stored?
Because there is an overload of std::ostream& operator<<(std::ostream&, const char*), which assumes the char* is the first element of a null-terminated string and prints out the whole string.
You can have a lot of fun by attempting to stream a char* that is not the first element of a null-terminated string:
#include <iostream>
int main()
{
char c = 'x';
std::cout << &c << std::endl;
}
char* and const char* are most commonly used to point to C-style null-terminated strings. The standard I/O library takes this into account when being passed one of those types to insert from or extract into. The functions were simply designed to have this special case based on how common it is to want to print out a C-style string.
To get the pointer value, you can try casting to a different pointer type:
std::cout << static_cast<void*>(p) << std::endl;
keyword operator overloading - simply another method of the iostream instance std::cout is responsible for chars and handles that differently. The exact implementation could also yield "Hello World"
cout << (void *) p << std::endl;
I expect it's because << operator has a specific override for char* argument, to output the string.
This is operator<<() overload for the type of the cout object as first parameter and type char* or const char* as second.
There are many such overloads, and you can write some too.
And the reason for this particular overload is to "print" C-style string (null-terminated array of char)