I have troubles understanding strings as pointers. Apparently a string is understood as a pointer which points to the first address of the string. So using the "&"-operator I should receive the address of the first character of the string. Here's a small example:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main(){
char text[101];
int length;
cout << "Enter a word: ";
cin >> text;
length = strlen(text);
for (int i = 0; i <= length; i++) {
cout << " " << &text[i];
}
return 0;
}
When entering a word such as "Hello", the output is: "Hello ello llo lo o". Instead I expected to receive the address of each character of "Hello". When I use the cast long(&text[i]) it works out fine. But I don't understand why. Without the cast, apparently the "&"-operator gives the starting address of the string to be printed. Using a cast it gives the address of every character separately.
Maybe sb. can explain this to me - I'd be really grateful!
&text[i] is equivalent to text + i and that shifts the pointer along the char[] array by i places using pointer arithmetic. The effect is to start the cout on the (i)th character, with the overload of << to a const char* called. That outputs all characters from the starting point up to the NUL-terminator.
text[i] however is a char type, and the overload of << to a char is called. That outputs a single character.
In C++, if you want a string, then use std::string instead. You can still write cin >> text; if text is a std::string type! Your code is also then not vulnerable to overrunning your char buffer.
If you have a character array storing a string as for example
char text[] = "Hello";
then the array is initialized like
char text[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
In this statement
std::cout << text;
there is used operator << overloaded for the type const char * and the array text is converted implicitly to pointer to its first element.
You could write instead
std::cout << &text[0];
because in the both statements the expressions text and &text[0] have type char *.
The operator overloaded for the type const char * outputs characters starting from the address at the pointer until a zero character is encountered.
So if instead of the statement
std::cout << &text[0];
you'll write
std::cout << &text[1];
then the only thing that is changed is the starting address of the string and nothing more. That is in fact you are outputting string that is represented like
{ 'e', 'l', 'l', 'o', '\0' }
If to write
std::cout << &text[2];
that is if the pointer in the right side of the expression is moved one position right then it means that you'll deal with the string
{ 'l', 'l', 'o', '\0' }
and so on.
That is the operator << overloaded like
template<class traits>
basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&,
const char*);
just outputs entities pointed to by the second parameter as strings.
If you want to output the value of the pointer itself instead of the string pointed to by the pointer you should use another overloaded operator << declared like
basic_ostream<charT, traits>& operator<<(const void* p);
Tp invoke it you should write for example
std::cout << ( void * )text;
or
std::cout << ( void * )&text[i];
where i is some index.
Instead of the C casting you can use C++ casting like
std::cout << static_cast<void *>( &text[i] );
To print the address of an array element, you could do:
cout << " " << (void*)&text[i];
This:
cout << " " << &text[i];
is equivalent to this:
cout << " " << text + i;
which means that you ask to print the string, starting from index i.
Related
#include <iostream>
using namespace std;
char* input(char **S);
int main()
{
char **S = new char *;
char *K = input(S);
//cout << K << endl;
cout << *K << endl;
}
char* input(char **S)
{
cout << "Enter string: ";
cin >> *S;
cout << S << endl; // Prints address of S
cout << *S << endl; //Prints content of address stored in S
return *S;
}
I am failing to understand why when I print out *K, I just get the first character of the input string but if I print out the commented line(just K alone) I get the whole string. Any help with explaining what I am not able to see or understand is appreciated.
Let's understand how arrays work:
// Let's say I have one character array
char arr[] = {'a', 'b', 'c', 'd'};
In here, the name of the array i.e. arr acts as the pointer to the first element of the array. However, do note that it is NOT the pointer to the first element to avoid confusion, it just have an implicit conversion to pointer of element type. More details can be found here: https://stackoverflow.com/a/1641963/10821123
Now since array is contiguous, the rest of the elements can be determined.
// so ideally, the below two statements would print the same thing
cout << &arr << endl;
cout << (void*) &arr[0] << endl;
// the above line just takes out the address of the first pointer
Now coming to your question, I'll convert my example to a string one:
char *K = "abc";
cout << *K << endl; // a
cout << K << endl; // abc
Note that the above assignment of char *K = "abc"; will give you a warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
The pointer only holds the address of the first element of the array, so when you dereference the pointer, it prints the first element, i.e. *K is interpreted as K[0]
Now there's an overload of operator <<, so what it does is if it sees a character pointer i.e. char*, it prints the complete null-terminated string, that's why in your case too, it is printing the whole string.
I'm rather new to C++ and while working with a pointer to a char array (C style string) I was confused by its behavior with the ostream object.
const char* items {"sox"};
cout << items << endl;
cout << items[0] << endl;
cout << *items << endl;
cout << &items << endl;
cout << &items[1] << endl;
Running this leads to:
sox
s
s
0x7fff2e832870
ox
In contrary to pointer of other data types, printing the variable doesn't output the address, but the string as a whole. By what I understand, this is due to the << operator being overloaded for char arrays to treat them as strings.
What I don't understand is, that cout << &items[1] prints the string from index 1 onward (ox), instead of the address of the char at index 1. Is this also due to << operator being overloaded or what is the reason for this behavior?
The type of &items[1] is const char *. Therefore the const char * overload of operator << is used, which prints the string from index 1 onwards.
OTOH, the type of &items is const char **, for which no specific overload exists, so the address of items is printed (via the const void * overload).
Back in the olden days, when C ran the world, there was no std::string, and programmers had to make do with arrays of char to manage text. When C++ brought enlightenment (and std::string), old habits persevered, and arrays of char are still used to manage text. Because of this heritage, you'll find many places where arrays of char act differently from arrays of any other type.
So,
const int integers[] = { 1, 2, 3, 4 };
std::cout << integers << '\n';
prints the address of the first element in the array.
But,
const char text[] = { 'a', 'b', 'c', '\0' };
std::cout << text << '\n';
prints the text in the array text, up to the final 0: abc
Similarly, if you try to print addresses inside the array, you get different behavior:
std::cout << &integers[1] << '\n';
prints the address of the second element in th array, but
std::cout << &text[1] << '\n';
prints the text starting at the second character of the array: bc
And, as you suspected, that's because operator<< has an overload that takes const char* and copies text beginning at the location pointed to by the pointer, and continuing up to the first 0 that it sees. That's how C strings work, and that behavior carries over into C++.
items[1] is the second character of the array and its address, i.e. &items[1], is a pointer to the second character (with index 1) as well. So, with the same rule that you have mentioned for operator <<, the second character of the string till the end is printed.
This question already has answers here:
Why is address of char data not displayed?
(8 answers)
print address of array of char
(3 answers)
C++ pointer assigning char array's address
(2 answers)
How do I get the address of elements in a char array?
(2 answers)
Closed 2 years ago.
I just started learning C++. I have confusion while printing out the int array it is printing the 0th element address of the array. And (array + 1) is the address after 4 registers since int is 4byte. But for char array, the behavior is not the same. Is char array implemented differently in C++?
code:
#include <iostream>
using namespace std;
int main()
{
char char_array [5] {'a', 'e', 'i', 'o', 'u'};
int int_array [5] {1,2,3,4,5};
cout << sizeof(char) << endl;
cout << sizeof(int) << endl;
cout << char_array << endl;
cout << char_array+1 << endl;
cout << int_array << endl;
cout << int_array + 1 << endl;
}
output:
1
4
aeiou≡r
eiou≡r
0x61fe00
0x61fe04
Process returned 0 (0x0) execution time : 0.428 s
Press any key to continue.
For starters the program has undefined behavior because the declared character array
char char_array [5] {'a', 'e', 'i', 'o', 'u'};
does not contain a string but using the overloaded operator << in these statements
cout << char_array << endl;
cout << char_array+1 << endl
for a pointer to char requires that the pointer would point to a string.
You could at least declare the array like
char char_array [6] {'a', 'e', 'i', 'o', 'u', '\0' };
Using an integer array as an expression in the operator << results that the overloaded resolution selects the operator for the type void * and the operator outputs the address of the first element of the integer array.
In these statements
cout << char_array+1 << endl;
cout << int_array + 1 << endl;
there is used the pointer arithmetic. The expression char_array+1 or int_array + 1 increases the value or the pointer (the array designator in such an expression is implicitly converted to pointer to its first element) by the value equal to sizeof( char ) or sizeof( int ) correspondingly.
sizeof( char ) is always equal to 1. sizeof( int ) depends on the used system and usually at least for 32-bit systems is equal to 4. And this output
0x61fe00
0x61fe04
demonstrates this.
If you want to output addresses for elements of the character array then you should write for example
cout << static_cast<void *>( char_array ) << endl;
cout << static_cast<void *>( char_array+1 ) << endl;
char[5] gets decayed to char const *, and then there is an overload for operator<< that writes out the string represented by the char const *.
int[5] decays to int const *, but there is not a similar overload for int const *, and so it simply prints the address.
std::cout is a variable of type std::basic_ostream which has an overload especially for formatting char*. Which is important because raw arrays will decay to pointers when passed by value.
The unique overload of operator<< for char* expects that the incoming data is a C String. Which is a string of characters that is nul terminated.
char char_array [5] {'a', 'e', 'i', 'o', 'u'};
Creates an array which is not nul terminated which is why you get seemingly random characters (via a buffer over read, leading to undefined behaviour). To rectify that you would just need to include a nul terminator. When char_array is declared as :
char char_array [6] {'a', 'e', 'i', 'o', 'u','\0'};
then
std::cout << char_array << std::endl;
will output aeiou and
std::cout << char_array + 1 << std::endl;
will output eiou
Here int_array is a pointer to an array of int. When you print int_array, you are printing the address of the start of the array (0x61fe00 in you case). When you print int_array + 1 your are doing what is called pointer arithmetic: int_array + 1 could be roughly translated as give me the next address holding and int and as int is 4 bytes, you can see that the next address is effectively the address plus four.
char_array is also a pointer to an array of char. Passing a pointer to an array of char while effectively print the underlying string. Here your string misses the end character `\0' which is UB.
You should definitively read on what is a pointer and a value because it is clear here that you are missing that knowledge.
A char array is a string and is being output as one.
I have come across a c++ code:
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
cout << "Greeting message: ";
cout << greeting << endl;
output: Hello
Since greeting is an array of size 6, displaying greeting should display only "H" because of greeting[0] in cout, since it is displaying first address of array. I don't know where I am wrong.
Except when it is the operand of the sizeof or unary & operators, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
This means that in the statement
cout << greeting << endl;
the expression greeting is converted from an expression of type char [6] to an expression of type char *, and the value of the expression is the address of the first element.
The stream operator << is defined such that if it receives an argument of type char *, it will write out the sequence of characters starting at that address until it sees the 0 terminator; here's a simplistic example of how it might work:
std::ostream& operator<<( std::ostream& s, char *p )
{
while (*p)
s.put( *p++ );
return s;
}
The real operator definition will be a bit more complex, but that's the basic idea.
If you want to print out just the first character of greeting, you must explicitly index or dereference it:
cout << greeting[0] << endl;
or
cout << *greeting << endl;
greeting decays to a pointer itself. But if it sounds complicated, you can look at it as a pointer to understand what cout does.
cout method prints characters starting from greeting[0] until \0.
If you want to see the address value write
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
cout << "Greeting message: ";
cout << (void*)greeting << endl;
// ^^^^^^^
The std::ostream& std::operator<<(std::ostream&, T type); provides specializations for the const char*, const char[] and char types.
yes greeting here is a pointer to first element in the array so if you do something like that :
cout << *greeting;
output will be H.
but in reality when you pass it to cout object it's smart enough to know that greeting is not just a pointer but it's more it's a string according to the internal implementation of operator overloading in handling .
so it's not a problem ,it's just cout can understand it.
I run the follow code:
#include <iostream>
using namespace std;
typedef struct Test
{
char a;
char b;
int i;
double d;
}Test;
int main()
{
Test test;
test.a = 'a';
test.b = 'b';
test.i = 478;
test.d = 4.7;
cout << &test.a << '\n'
<< &test.b << '\n'
<< &test.i << '\n'
<< &test.d << '\n';
return 0;
}
The output is:
ab#
b#
0x28fe94
0x28fe98
At first, i thought it is a result of the precedence between & and ..
But the 0x28fe94 and 0x28fe94 indicate it's not the problem of precedence.
I can figure out what does the ab# and b# mean?
When you write
cout << &test.a
because test.a is a char, this will invoke the operator<< (ostream&, const char*) overload, thinking that your char* is a pointer to a C-style string rather than a pointer to just one character. Consequently, the operation will start reading bytes starting at the memory address of &test.a until it finds a null terminator (a zero byte). This happens to print out ab#, since a has value 'a', b has value 'b', and the number 478, on your system, happens to correspond to an # character followed eventually by a null byte.
If you want to see the numeric addresses of test.a and test.b, cast the pointers to void*s, which will select the operator<< (ostream&, const void*) overload. For example:
cout << static_cast<void*>(&test.a)
Hope this helps!
It means undefined behaviour. There's a special overload for const char * that prints it as a null-terminated string. Yours has no terminator, so it goes beyond and triggers the aforementioned UB. Fix it with a cast:
std::cout << static_cast<void *>(&test.a) << '\n'
<< static_cast<void *>(&test.b) << '\n'
<< &test.i << '\n'
<< &test.d << '\n';
Because you are passing the address of a character when you use &test.a and &test.b, the cout operator is treating the addresses as the start of a string. That's why you get first ab# and then b#. The # is less obvious; it falls in the padding after the two char values and before the int value in the structure, and is quasi random junk. You're actually invoking undefined behaviour because you're asking the output code to access the padding. If you want to print addresses, cast to void *. If you want to print characters, don't supply the address.