How come printing &some_buf[0] and &some_buf give different outputs? - c++

char buffer[4];
std::cout << &buffer << std::endl;
std::cout << &buffer[0] << std::endl;
When I run this code the first line is the hex address of first element in the buffer. The second line is four question marks (unless I cast as a null-pointer).
How is the second statement different from the first (semantically, they are the same?)?
Why does the second line appear as question marks and not random garbage characters?

&buffer gives you the address of the buffer, in an appropriate pointer type. That type is char (*)[4].
&buffer[0] gives you the address of the first buffer element (a char), so the address is of type char*.
The standard stream classes have an overload that handles a char const*, but no overload that handles a char (*)[4]. There is however a general overload for pointers, that accepts a void*. So the pointer to array is converted implicitly to a void*, and passed to that overload. You therefore see the address of the buffer.
In the second case, if buffer was initialized properly, you'd see its contents printed (what the "c-string" overload does). However, since you did not initialize it, your code has undefined behavior. The mere attempt to print the buffer has no well defined consequence.

&buffer is the address of the buffer. &buffer[0] is the address of the first character in the buffer. here in your case a garbage value that is because you didn't initialize it. Try to initialize it:
char buffer[] = "Hello there!";
std::cout << &buffer << std::endl;
std::cout << &buffer[0] << std::endl; // print from first element to the end(until the first null-character)
std::cout << &buffer[4] << std::endl; // print from fifth element to the end
The output:
0018FF38
Hello there!
o there!
I think it is a problem of osstream insertion operator << which assumes you to pass a char* and you pass to it the address of a character so as I guess it's a UB.
To get the address of the character you have to cast it to void*:
std::cout << static_cast < void* >(&buffer[0]) << std::endl;
std::cout << static_cast < void* >(&buffer[1]) << std::endl;
The output:
0018FF38
0018FF39
To confirm that it's an ostream << issue try to use printf:
printf("&buffer[0]: %p \n", &buffer[0]);
The output:
&buffer[0]: 0018FF38

Related

How to correctly use vector<uint8_t>.data()?

vector.data() should return a pointer to the first element, but when I use it on a vector<uint8_t>, it somhow returns somthing else:
int main() {
std::string myString = {"a b c all the way long"};
std::vector<uint8_t> myVec(myString.begin(), myString.end());
std::cout << myVec.data() << std::endl;
std::vector<int> anotherVec = {4,5,2,3};
std::cout<< anotherVec.data() << std::endl;
return 0;
}
program prints:
a b c all the way long
0x124bf00
Why does the first print show all of the vector, and the second print shows the pointer? I was expecting both to print a pointer.
The real issue is that on another big program, when I print vector<uint8_t>.data() with cout, it prints garbage after it (when I look at it in the debugger, I don't see the garbage).
The data() function returns a pointer to the first element.
myString is a vector of uint8_t values, so data() will return a value of type uint8_t*. uint8_t is a type based on char, so the << stream output operator will treat it as a null-terminated string. The problem here is that myVec doesn't contain a null-terminated string, so this is technically undefined behavior.
For anotherVec, that's a vector of int values, which means that data() returns a value of type int*, which has no specific overload for the << stream output operator. Instead, it uses the closest possible overload, which is the one to print generic pointers of type void*.
If you want the first to print the pointer itself, then you need to explicitly cast the pointer to void*:
std::cout << static_cast<void*>(myVec.data()) << '\n';

Are there any exceptions to const char*?

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

Weird output when using char double pointer

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.

c++ pointer to specific element in char array returns all elements after the specified one

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

Why doesn't a character array return a memory address when called directly?

I understand from here that the name of an array is the address of the first element in the array, so this makes sense to me:
int nbrs[] = {1,2};
cout << nbrs << endl; // Outputs: 0x28ac60
However, why is the entire C-string returned here and not the address of ltrs?
char ltrs[] = "foo";
cout << ltrs << endl; // Outputs: foo
Because iostreams have an overload for char * that prints out what the pointer refers to, up to the first byte that contains a \0.
If you want to print out the address, cast to void * first.
cout has operator<<() overloaded for char* arrays so that it outputs every element of the array until it reaches a null character rather than outputting the address of the pointer
cout, and generally, C++ streams, can handle C strings in a special way. cout operators <<, >> are overloaded to handle a number of different things, and this is one of them.