Please explain the difference in the output of two programs.
cout << branch[i] in first program gives output as:
Architecture
Electrical
Computer
Civil
cout << *branch[i] in second program gives output as:
A
E
C
C
Why?
What is the logic behind *branch[i] giving only first character of each word as output and branch[i] giving full string as an output?
Program 1
#include <iostream>
using namespace std;
int main()
{
const char *branch[4] = { "Architecture", "Electrical", "Computer", "Civil" };
for (int i=0; i < 4; i++)
cout << branch[i] << endl;
system("pause");
return 0;
}
Program 2
#include <iostream>
using namespace std;
int main()
{
const char *branch[4] = { "Architecture", "Electrical", "Computer", "Civil" };
for (int i=0; i < 4; i++)
cout << *branch[i] << endl;
system("pause");
return 0;
}
When you declare a const char* with assignment operator, for example:
const char* some_string = "some text inside";
What actually happens is the text being stored in the special, read-only memory with added the null terminating char after it ('\0'). It happens the same when declaring an array of const char*s. Every single const char* in your array points to the first character of the text in the memory.
To understand what happens next, you need to understand how does std::cout << work with const char*s. While const char* is a pointer, it can point to only on thing at a time - to the beginning of your text. What std::cout << does with it, is it prints every single character, including the one that is being pointed by mentioned pointer until the null terminating character is encountered. Thus, if you declare:
const char* s = "text";
std::cout << s;
Your computer will allocate read-only memory and assign bytes to hold "text\0" and make your s point to the very first character (being 't').
So far so good, but why does calling std::cout << *s output only a single character? That is because you dereference the pointer, getting what it points to - a single character.
I encourage you to read about pointer semantics and dereferencing a pointer. You'll then understand this very easily.
If, by any chance, you cannot connect what you have just read here to your example:
Declaring const char* branch[4]; you declare an array of const char*s. Calling branch[0] is replaced by *(branch + 0), which is derefecencing your array, which results in receiving a single const char*. Then, if you do *branch[0] it is being understood as *(*(branch + 0)), which is dereferencing a const char* resulting in receiving a single character.
branch[i] contains a char* pointer, which is pointing to the first char of a null-terminated string.
*branch[i] is using operator* to dereference that pointer to access that first char.
operator<< is overloaded to accept both char and char* inputs. In the first overload, it prints a single character. In the second overload, it outputs characters in consecutive memory until it reaches a null character.
This is because of operators precedences.
Subscript operator [] has a higher precedence than an indirection operator *.
So branch[i] returns const char * and *branch[i] returns const char.
*branch[i] prints a single char located at the address pointed to by branch[i].
branch[i] prints the whole char* array starting with the address pointed to by branch[i].
Related
I'm using C++ to understand how exactly pointers work. I have this piece of code using arrays, which I'm using just to understand how the equivalent works with pointers.
int main() {
int arr[10] = {1,2,3};
char arr2[10] = {'c','i','a','o','\0'};
cout << arr << endl;
cout << arr2 << endl;
}
However when I run this, arr outputs the address of the first element of the array of ints (as expected) but arr2 doesn't output the address of the first element of the array of chars; it actually prints "ciao".
What is it that I'm missing or that I haven't learned yet about this?
It's the operator<< that is overloaded for const void* and for const char*. Your char array is converted to const char* and passed to that overload, because it fits better than to const void*. The int array, however, is converted to const void* and passed to that version. The version of operator<< taking const void* just outputs the address. The version taking the const char* actually treats it like a C-string and outputs every character until the terminating null character. If you don't want that, convert your char array to const void* explicitly when passing it to operator<<:
cout << static_cast<const void*>(arr2) << endl;
Because cout's operator << is overloaded for char* to output strings, and arr2 matches that.
If you want the address, try casting the character array as a void pointer.
There is a standard overload for char* that outputs a NUL terminated string.
While casting is probably a more meaningful approach, you could also use the addressof operator:
cout << &arr2 << endl;
I'm using C++ to understand how exactly pointers work. I have this piece of code using arrays, which I'm using just to understand how the equivalent works with pointers.
int main() {
int arr[10] = {1,2,3};
char arr2[10] = {'c','i','a','o','\0'};
cout << arr << endl;
cout << arr2 << endl;
}
However when I run this, arr outputs the address of the first element of the array of ints (as expected) but arr2 doesn't output the address of the first element of the array of chars; it actually prints "ciao".
What is it that I'm missing or that I haven't learned yet about this?
It's the operator<< that is overloaded for const void* and for const char*. Your char array is converted to const char* and passed to that overload, because it fits better than to const void*. The int array, however, is converted to const void* and passed to that version. The version of operator<< taking const void* just outputs the address. The version taking the const char* actually treats it like a C-string and outputs every character until the terminating null character. If you don't want that, convert your char array to const void* explicitly when passing it to operator<<:
cout << static_cast<const void*>(arr2) << endl;
Because cout's operator << is overloaded for char* to output strings, and arr2 matches that.
If you want the address, try casting the character array as a void pointer.
There is a standard overload for char* that outputs a NUL terminated string.
While casting is probably a more meaningful approach, you could also use the addressof operator:
cout << &arr2 << endl;
Going by the books, the first cout line should print me the address of the location where the char variable b is stored, which seems to be the case for the int variable a too. But the first cout statement prints out an odd 'dh^#' while the second statement correctly prints a hex value '
ox23fd68'. Why is this happening?
#include<iostream>
using namespace std;
int main()
{
char b='d';
int a=10;
char *c=new char[10];
c=&b;
int *e=&a;
cout<<"c: "<<c<<endl;
cout<<"e: "<<e;
}
There is a non-member overload operator<<(std::basic_ostream) for the const char* type, that doesn't write the address, but rather the (presumed) C-style string1). In your case, since you have assigned the address of a single character, there is no NUL terminator, and thus no valid C-style string. The code exhibits undefined behavior.
The behavior for int* is different, as there is no special handling for pointers to int, and the statement writes the address to the stream, as expected.
If you want to get the address of the character instead, use a static_cast:
std::cout << static_cast<void*>( c ) << std::endl;
1) A C-style string is a sequence of characters, terminated by a NUL character ('\0').
Actually this program has problem. There is a memory leak.
char *c=new char[10];
c=&b;
This allocates 10 characters on heap, but then the pointer to heap is overwritten with the address of the variable b.
When a char* is written to cout with operator<< then it is considered as a null terminated C-string. As the address of b was initialized to a single character containing d op<< continues to search on the stack finding the first null character. It seems the it was found after a few characters, so dh^# is written (the d is the value of variable b the rest is just some random characters found on the stack before the 1st \0 char).
If you want to get the address try to use static_cast<void*>(c).
My example:
int main() {
char *c;
char b = 'd';
c = &b;
cout << c << ", " << static_cast<void*>(c) << endl;
}
An the output:
dÌÿÿ, 0xffffcc07
See the strange characters after 'd'.
I hope this could help a bit!
I am learning pointers and i tried this following program
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
char* getword()
{
char*temp=(char*)malloc(sizeof(char)*10);
cin>>temp;
return temp;
}
int main()
{
char *a;
a=getword();
cout<<a;
return 0;
}
To my level of understanding, a is a pointer to a character, and in the function getword() I returned temp which I think the base &temp[0]. I thought that the output would be the first character of the string I enter, but I got the entire string in stdout. How does this work?
In the tradition of C, a char* represents a string. Indeed, any string literal in your program (e.g. "hello") will have a type of const char *.
Thus, cout::operator<<( const char * ) is implemented as a string-output. It will output characters beginning at the address it is given, until it encounters the string terminator (otherwise known as null-terminator, or '\0').
If you want to output a single character, you need to dereference the pointer into a char type. You can choose one of the following syntaxes:
cout << *a; // Dereference the pointer
cout << a[0]; // Use array index of zero to return the value at that address
It should be noted that the code you provided isn't very C++ish. For starters, we generally don't use malloc in C++. You then leak the memory by not calling free later. The memory is uninitialised and relies on cin succeeding (which might not be the case). Also, you can only handle input strings of up to 9 characters before you will get undefined behaviour.
Perhaps you should learn about the <string> library and start using it.
It's true that char* "points to a character". But, by convention, and because with pointers there is no other way to do so, we also use it to "point to more than one character".
Since use of char* almost always means you're using a pointer to a C-style string, the C++ streams library makes this assumption for you, printing the char that your pointer points to … and the next … and the next … and the next until NULL is found. That's just the way it's been designed to work.
You can print just that character if you like by dereferencing the pointer to obtain an actual char.
std::cout is an overloaded operator and when it receives a char * as an operand then it treats it as a pointer to c style string and it will print the entire string.
If you want to print the first character of the string then use
cout << *a;
or
cout << a[0];
In your code, std::cout is an ostream and providing a char* variable as input to operator<< invokes a particular operator function overload to write characters to the ostream.
std::ostream also has a operator overload for writing a single character to itself.
I'm assuming you now know how to dereference a char* variable, but you should be using std::string instead of an unsafe char* type.
Here is the correct code
#include <stdio.h>
#include <stdlib.h>
char* getword()
{
char*temp=(char*)malloc(sizeof(char)*10);
scanf("%s",temp);
return temp;
}
int main()
{
char *a;
a = getword();
int currChar = 1;
printf("%c",*(a + currChar)); //increment currChar to get next character
return 0;
}
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.