I am stuck with string and array - c++

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.

Related

Why does printing the 'address of index n' of c style strings lead to output of substring

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.

C++ int and char array adress [duplicate]

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.

Why don't char arrays with separate chars end with a null-terminator unlike string literals?

I was playing around with char arrays in c++ and wrote this program:
int main()
{
char text[] = { 'h', 'e', 'l', 'l', 'o' }; //arrays initialised like this
//will have a size of the number
//of elements that you see
char text2[] = "hello"; //arrays initialised like this will have a size of
//the number of elements that you see + 1 (0 on the
//end to show where the end is
cout << endl;
cout << "The size of the first array is: " << sizeof(text) << endl;
cout << endl;
for (int i = 0; i < sizeof(text); i++)
{
cout << i << ":" << text[i] << endl;
}
cout << endl;
cout << "The size of the first array is: " << sizeof(text2) << endl;
cout << endl;
for (int i = 0; i < sizeof(text2); i++)
{
cout << i << ":" << text2[i] << endl;
}
cout << endl;
cin.get();
return 0;
}
This program gives me the output:
The size of the first array is: 5
0:h
1:e
2:l
3:l
4:o
The size of the first array is: 6
0:h
1:e
2:l
3:l
4:o
5:
My question is: Is there a particular reason that initializing a char array with separate chars will not have a null terminator (0) on the end unlike initializing a char array with a string literal?
A curly braces initializer just provides the specified values for an array (or if the array is larger, the rest of the items are defaulted). It's not a string even if the items are char values. char is just the smallest integer type.
A string literal denotes a zero-terminated sequence of values.
That's all.
Informally, it's the second quotation character in a string literal of the form "foo" that adds the NUL-terminator.
In C++, "foo" is a const char[4] type, which decays to a const char* in certain situations.
It's just how the language works, that's all. And it's very useful since it dovetales nicely with all the standard library functions that model a string as a pointer to the first element in a NUL-terminated array of chars.
Splicing in an extra element with something like char text[] = { 'h', 'e', 'l', 'l', 'o' }; would be really annoying and it could introduce inconsistency into the language. Would you do the same thing for signed char, and unsigned char, for example? And what about int8_t?
A string literal like for example this "hello" has a type of a constant character array and initializwd the following way
const char string_literal_hello[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
As it is seen the type of the string literal is const char[6]. It contains six characters.
Thus this declaration
char text2[] = "hello";
that can be also written like
char text2[] = { "hello" };
in fact is substituted for the following declaration
char text2[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
That is then a string literal is used as an initializer of a character array all its characters are used to initialize the array.
You can terminate it yourself in multiple ways:
char text1[6] = { 'h', 'e', 'l', 'l', 'o' };
char text2[sizeof "hello"] = { 'h', 'e', 'l', 'l', 'o' };
char text3[] = "hello"; // <--- my personal favourite
Is there a particular reason that initializing a char array with separate chars will not have a null terminator (0)
The reason is because that syntax...
Type name[] = { comma separated list };
...is used for initializing arrays of any type. Not just char.
The "quoted string" syntax is shorthand for a very specific type of array that assumes a null terminator is desired.
When you designate a double quote delimited set of adjacent characters (a string literal), it is assumed that what you want is a string. And a string in C means an array of characters that is null-terminated, because that's what the functions that operate on strings (printf, strcpy, etc...) expect. So the compiler automatically adds that null terminator for you.
When you provide a brace delimited, comma separated list of single quote delimited characters, it is assumed that you don't want a string, but you want an array of the exact characters you specified. So no null terminator is added.
C++ inherits this behavior.

Understanding strings as pointers in C++

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.

char array not working: c++

Script
#include <iostream>
using namespace std;
int main()
{
float nums[3];
nums[0]=1.5;
nums[1]=2.75;
nums[2]=3.25;
const char* name[5]={"m", "i", "k", "e", "\0"};
int coords[2][3]={{1, 2, 3}, {4, 5, 6}};
cout << "nums[0]: " << nums[0] << endl;
cout << "nums[1]: " << nums[1] << endl;
cout << "nums[2]: " << nums[2] << endl;
cout << "name[0]: " << name[0] << endl;
cout << "Text String: " << name << endl;
cout << "coords[0][2]: " << coords[0][2] << endl;
cout << "coords[1][1]: " << coords[1][1] << endl;
return 0;
}
Output:
nums[0]: 1.5
nums[1]: 2.75
nums[2]: 3.25
name[0]: m
Text String: 0xffffcbb0
coords[0][2]: 3
coords[1][1]: 5
Question:
How can I make the "Text String: " say "mike"
I tried char name[5],
I tried char* name[5];
Please help
Thank You
I'm new to c++, don't judge
const char* name[5]={"m", "i", "k", "e", "\0"};
Is an array of pointers to characters. You have unintentionally created an array of pointers to strings rather than a string.
cout of a pointer results in the address being printed, except in the case of a pointer to a character where the << operator has been written to assume a null-terminated c-style string.
To fix this, you can
1 Use a pointer to a string literal
const char* name="mike";
2 Use an array of characters
const char name[5]={'m', 'i', 'k', 'e', '\0'};
Or 3 use a combination of the two
const char name[5]="mike";
As an added bonus, because in the latter two cases the initialization implies the size of the array you can leave it out,
const char name[]="mike";
and the compiler will figure it out. Very handy when you change from "mike" to "henry" as you don't have to adjust the size.
When you are done this exercise, take some time and read up on std::string. Use it wherever possible instead of C-Style strings. It will save you an amazing amount of time, blood, and tears.
const char name[5]={'m', 'i', 'k', 'e', '\0'};
What you need is an array of chars.
Character literals are written using single quotes ('). If you use double quotes ("), you get a string literal instead.
Using your notation, change the double quotes to single quotes and get rid of the asterisk.:
const char name[5]={'m', 'i', 'k', 'e', '\0'};
Or you could use:
const char name[] = "mike";