What is the difference between int and char arrays? - c++

What is the difference between int and char arrays below:
int main()
{
int numbers[] = {2,1,3};
char letter[] = {'a','b','\0'};
cout<< numbers<<endl;
cout<< letter<<endl;
}
Output:
0x22ff12 // an address
ab
Why isn't the 213 displayed ?
I know the name of an array will point to the address of its first element, but why
does a char array display different behavior?

There is no operator<< overload that takes arrays, exactly, so the arguments you pass (eg numbers and letter) undergo array-to-pointer conversion, to void* and char* respectively.
There is an overload of operator<<() that takes a const void*, and another that takes a const char*. When you call:
cout<< numbers<<endl;
the const void* version is matched, but when you call:
cout<< letter<<endl;
the const char* version is matched.
In the const void* version, the pointer is displayed, while with the const char* version, the string is displayed up to the null terminator.

When you print an array with cout it will print the base address of the array.
The exception is with char arrays which have been overloaded to print it as a c-string.
If you want to print the elements of the int array, you need to do it element-by-element.

The reason is thatoperator<< overloaded for const char* which prints each character till it encounters \0.
There is no such overload corresponds to int[N] which prints each element in it. Instead when you write cout << numbers, it invokes operator<< which is overloaded for void*, and which prints the address.
However, if you overload operator<< for T[N], then you can print it like that as well.
Here is a simple illustration:
template<typename T, size_t N>
std::ostream & operator<<(std::ostream & out, const T (&a)[N])
{
for(size_t i = 0 ; i < N ; ++i)
out << a[i] << ' ';
return out;
}
int main()
{
int numbers[] = {2,1,3};
char letter[] = {'a','b','\0'};
cout<< numbers<<endl;
cout<< letter<<endl;
}
Output:
2 1 3
a b
Demo : http://ideone.com/O4T9N

In C, and therefore in C++, a string is often represented by an array of chars terminated in a 0. Therefore an overloaded operator<< is provide for the class std::ostream, of which std::cout is an instance , which prints the char* as a string. There is no such common use of int arrays, nor any convention so the operator would 'know' how many elements to output, so the pointer to the array is matched to the version of operator<< which outputs any other pointer by printing its address.

char arrays are special because there is an overload for operator << that displays the content as a string.
All other arrays will have the address displayed by default.

In C/C++ an array is in fact a pointer to the first element. A pointer holds the address where a value is stored. Therefore, if you print the pointer numbers, you will get the address where the first value (2) is stored in memory.
char* is an exception, as it will behave as a string when you try to print it.

Your code mostly refers C. An array of char is de-facto representation of strings in C. On the other hand, an array in C is also a pointer to the memory cell (an address of the cell) that holds the first element of the array.
So, when you print out an array of characters, you in fact print out a string (because C treats it that way). When you're printing an array of integers, you're printing out the address of the first element of the array.

numbers is a pointer. All arrays in C++ are in fact pointers, numbers[3] just means "the value at the memory address &number+3", so you're outputting the memory address of the first element in numbers.

There is no reason the compiler should know where your int[] array ends, but tradition and standard libraries dictate that C strings are null terminated char[] arrays. There is no such tradition or library support for null terminated int[] arrays.
There are C++ pretty printers templates available if you need this functionality. I vaguely recall that one employs an array's bound when the type actually knows the bound, i.e. your code still won't work since you use [] not [3].
Just fyi, your code cannot be fixed by replacing the [] with a [3] inside the STL, although perhaps operator<< could be overloaded.

A char array contains characters.
It can be initialized like:
char arr[4]={'a','b','c','\0'};
char arr[4]={"abc"};
An integer array contains integers.
It can be initialized like:
int arr[4]={1,2,3,4};

Related

What is the value we get on printing an array in cpp?

I'm a beginner to c++, I wrote this in my code:
int *ptr;
int arr[4] = {1, 2, 3, 4};
cout << arr << endl;
This outputs to '0x61ff00'.
What does the value mean ?
Thanks!
There is no standard overload for arrays. There is however an overload for const void*. The array decays to a pointer to first element, which further implicitly converts to const void*. The result is an implementation defined textual representation of the address that is the value of the const void* object.
Memory addresses are essentially numbers. 0x is a prefix for hexadecimal numbers.
Following doesn't apply to the example, but does apply to some other arrays: If the array element is char, then the behaviour of the character stream is different, because there is an overload for const char*. In that case, the behaviour is to treat the array as a null terminated string, and the result is the string contained within the array. String literals are null terminated arrays of char.
Example:
std::cout << "Hello, World!";
Output:
Hello, World!
If the array doesn't contain the null terminator, then the behaviour of the program is undefined. Don't ever insert such array into a character stream.

Pointers with character array variables

I'm learning C++ and was understanding pointers and created the following code
#include<string>
using namespace std;
int main()
{
char s[100] = "Today is a rainy day";
cout<<s[0]<<endl;
char *p;
p = s;
cout <<s<<endl;
cout<<p<<endl;
cout<<*p<<endl;
}
In this code, I assumed that as s points to the starting address of the array, printing the pointer p will give me the address and *p will give me the first element of the array.
My output was of the form
T
Today is a rainy day
Today is a rainy day
T
Here, p and s both print out the complete character array which I did not understand, also using the *p was printing out the first element even though p was now just an array.
How do the pointers function when we use them in arrays like this is what I would like to understand.
The difference between a pointer and an array exists only at compile time.
At runtime they are the same, decayed to pointers.
For an array at compile time you can find its dimensions, and use those as parameters in template code. See std::is_array, std::extent, etc.
When you dereference either the array or pointer, you end up with a char. This prints that char, as you might have expected.
However, when you provide a char* (which is what you get with both the array and pointer case, as the array decays to a pointer here), the overload of the operator<< for char* is called instead.
This overload treats any char* it sees as a C-string, which is why you see it printed out as such.

Initialization of pointers in c++

I need to clarify my concepts regarding the basics of pointer initialization in C++. As per my understanding, a pointer must be assigned an address before putting some value using the pointer.
int *p;
*p=10; //inappropriate
cout << *p <<"\n";
This would probably show the correct output (10) but this may cause issue in larger programs since p initially had garbage address which can be anything & may later be used somewhere else in the program as well.So , I believe this is incorrrect, the correct way is:
int *p;
int x=10;
p=&x; //appropriate
cout << *p <<"\n";
My question is, if the above understanding is correct, then does the same apply on char* as well?:
const char *str="hello"; // inappropriate
cout << str << "\n";
//OR
const string str1= "hello";
const char str2[6] ="world";
const char *str=str1; //appropriate
const char *st=str2; //appropriate
cout << str << st << "\n";
Please advice
Your understanding of strings is incorrect.
Lets take for example the very first line:
const char *str="hello";
This is actually correct. A string literal like "hello" is turned into a constant array by the compiler, and like all arrays it can decay to a pointer to its first element. So what you are doing is making str point to the first character of the array.
Then lets continue with
const string str1= "hello";
const char *str=str1;
This is actually wrong. A std::string object have no casting operator defined to cast to a const char *. The compiler will give you an error for this. You need to use the c_str function go get a pointer to the contained string.
Lastly:
const char str2[6] ="world";
const char *st=str2; //appropriate
This is really no different than the first line when you declare and initialize str. This is, as you say, "appropriate".
About that first example with the "inappropriate" pointer:
int *p;
*p=10; //inappropriate
cout << *p <<"\n";
This is not only "inappropriate", this leads to undefined behavior and may actually crash your program. Also, the correct term is that the value of p is indeterminate.
When I declare a pointer
int *p;
I get an object p whose values are addresses. No ints are created anywhere. The thing you need to do is think of p as being an address rather than being an int.
At this point, this isn't particularly useful since you have no addresses you could assign to it other than nullptr. Well, technically that's not true: p itself has an address which you can get with &p and store it in an int**, or even do something horrible like p = reinterpret_cast<int*>(&p);, but let's ignore that.
To do something with ints, you need to create one. e.g. if you go on to declare
int x;
you now have an int object whose values are integers, and we could then assign its address to p with p = &x;, and then recover the object from p via *p.
Now, C style strings have weird semantics — the weirdest aspect being that C doesn't actually have strings at all: it's always working with arrays of char.
String literals, like "Hello!", are guaranteed to (act1 like they) exist as an array of const char located at some address, and by C's odd conversion rules, this array automatically converts to a pointer to its first element. Thus,
const char *str = "hello";
stores the address of the h character in that character array. The declaration
const char str2[6] ="world";
works differently; this (acts1 like it) creates a brand new array, and copies the contents of the string literal "world" into the new array.
As an aside, there is an obsolete and deprecated feature here for compatibility with legacy programs, but for some misguided reason people still use it in new programs these days so you should be aware of it and that it's 'wrong': you're allowed to break the type system and actually write
char *str = "hello";
This shouldn't work because "hello" is an array of const char, but the standard permits this specific usage. You're still not actually allowed to modify the contents of the array, however.
1: By the "as if" rule, the program only has to behave as if things happen as I describe, but if you peeked at the assembly code, the actual way things happen can be very different.

How can i access individual elements of a string in an array of pointers?

#include<iostream>
using namespace std;
main()
{
char *p[4] = {"arp","naya","ajin","shub"};
cout<<*p[2]; // How is this printing 'a'
// how can i print the elements of each of the 4 strings
// except the first character
}
Visit http://cpp.sh/7fjbo
I'm having a lot of problems in understanding handling of pointers with strings. If you can help with that, please post some additional links. Underastanding the use of arrays with pointers is my primary concern.
p[2] is a pointer to the first element of "ajin". When you dereference it, you get a. If you want to print all of it, use the pointer itself
cout << p[2];
If you want to skip the first characters, pass a pointer to the second character to cout, i.e.
cout << p[2] + 1;
Here, p is basically array of string pointers with array length 4.
*p[2] is same as p[2][0]
p[2] is same as "start from index 0 and print till the compiler finds '\0'"
p[2] + i is same as "start from index i and print till the compiler finds '\0'"
Some more information in addition to Armen's answer to give you a better understanding.
C++ is not exactly C; it is a strongly typed language. In C, you use char * to denote a null-terminated string. But actually, it means a pointer to the char type. C++, being strongly typed, is invoking
std::ostream& std::ostream::operator<<(std::ostream& cout, char);
with
cout << *p[2];
since the second operand is of type char.
In C++, you may want to use std::string instead of char* because the former is safer and has an easier interface. For details, you can refer to Why do you prefer char* instead of string, in C++?

difference between int* and char* in c++

#include <iostream>
using namespace std;
int main() {
int * a[5];
char * b[5];
cout<<a[1]; // this works and prints address being held by second element in the array
cout<<b[1]; // this gives run time error . why ?
return 0;
}
Can anyone please explain to me cout<<b[1] gives run-time error ?
Shouldn't both int and char array behave similar to each other ?
Because IOStreams are designed to treat char* specially.
char* usually points to a C-string, so IOStreams will just assume that they do and dereference them.
Yours don't.
As others have said, iostream formatted output operators consider char* to point to C-style string and attempt to access this string.
What others have not said so far, is that if you are interested in the pointer, you need to cast the pointer in question to void*. For example:
std::cout << static_cast<const void*>(buf[1]);
An output stream such as cout gives special consideration to char * that it does not give to other pointers. For pointers other than char *, it will simply print out the value of the pointer as a hexadecimal address. But for char *, it will try to print out the C-style (i.e. null terminated array of char) string referred to by the char *. Therefore it will try to dereference the char pointer, as #AlexD points in the comment to your post.
C++ (inheriting it from C) treats character pointers specially. When you try to print a[1] of type int* the address is printed. But when you try to print b[1] of type char* the iostream library - following the rest of the language - assumes that the pointer points to the first character of zero-terminated string of characters. Both your output statements are initialised behaviour, but in the case of char* crash is much more likely because the pointer is dereferenced.