C Char Array Creation Differences - c++

In C I've noticed that there are a few ways to declare a char array. What's the difference between:
char arr[10] = "abcdefghij";
char* arr2[10] = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"};
gcc says I need the star after char in 2 and not in 1.
when printing 1 I can use printf("%s\n", arr); and it prints abcdefghij#
when printing 2 I have to use a for loop
Why are they different?

Because 1 is a char array, while the second is an array of arrays as "a" is in fact an array of 2 chars 'a' and '\0'

arr is a vector of char of 10 elements, and arr2 is a vector of chars pointers of 10 elements
char arr2[10] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
It is equal arr.

In the first one you are just declaring a string, but in the second one you are creating 10 pointers to 10 strings. As an example
char* arr2_0 = "a" ;
char* arr2_1 = "b" ;
char* arr2_2 = "c" ;
char* arr2_3 = "d" ;
char* arr2_4 = "e" ;
char* arr2_5 = "f" ;
char* arr2_6 = "g" ;
char* arr2_7 = "h" ;
char* arr2_8 = "i" ;
char* arr2_9 = "j" ;

To understand this behavior, you have to know the difference between strings and chars. The former are created with " and can contain several chars, while the latter are created with ' and represent only one char. Since you used " in your array initialisation, you created an array of strings, not chars. Now strings are represented via pointers to chars. Therefore the compiler wanted you to create an array of pointers to chars, instead of an array of chars.

Related

Could I get help finding the output of this function? (C++)

What would the output of this code be, with all of the appropriate includes?
I understand what everything does up until *(x+4) = x[n];, and from there I got a little lost.
int main(){
int n;
char y[10] = "tasked";
char *x = y;
n = strlen (x);
*(x+4) = x[n];
x++;
printf ("%s",x);
}
Edit: I didn't understand what *(x+4) = x[n]; did to the string, thank you all!
The output of the program will be
ask
After this declaration
char y[10] = "tasked";
the array y is initialized the following way
char y[10] = { 't', 'a', 's', 'k', 'e', 'd', '\0', '\0', '\0', '\0' };
That is all characters that do not have a corresponding initializing character from the string literal are zero-initialized.
After this statement
n = strlen (x);
n is equal to 6.
So this statement
*(x+4) = x[n];
do the following. It substitutes the character 'e' (at index 4) for the character '\0' (at index 6);
So after that the array has the following content
{ 't', 'a', 's', 'k', '\0', 'd', '\0', '\0', '\0', '\0' }
Then the pointer advances one position and points to the second character of the array (with index 1) that is to the character 'a'.
So starting from this character 'a' until the terminating zero is encountered the characters 'a', 's', and 'k' are outputted.
Open this site : and paste your code, then add the following before the "int main()" line:
#include <string.h>
This will allow you to use the "strlen" function.
Click the green "Run" button to get the output.
Then follow #Vlad from Moscow's answer and you will be informed.

Is there a way to initialize arrays with mixed chars and "strings"

I would want to initialize char array during compilation time with least amount of manual work.
Is there a working shorthand format for this
char arr[5] = {0x4, 'a', 's', 'd' 'c'};
such as
char arr[5] = {0x4, "asdc"};
You could integrate the char int the string with escape sequences:
char arr[6] = { "\x04asdc"};
edit: corrected the wrog length of the array.
No that's not possible. But you could do
char arr[] = "\04asdc";
The problem with this is that is would not be exactly like the original array you show, since it would include the string terminator and therefore have six elements.

Understanding multidimensional string array in C++

I am new to c++. I can not understand why the following code prints the "r" string. I think the it should be an array of 2X3X4 elements, so by pointing to the arr[0][0][0] i would expect the first char in the first string of the first arr=a, but this prints abcd. Can anyone explain it?
#include <iostream>
using namespace std;
int main()
{
string arr [2] [3] [4]={
{"abcd","efgh","ijkl"},
{"mnop","qrst","xywz"}
};
cout<<arr [1] [0] [1] [1]<<endl;
return 0;
}
Edit:
What makes me confused is the behavior in python. The following python code prints a:
arr=[["abcd","efgh","ijkl"],["mnop","qrst","xwyz"]]
print arr[0][0][0]
It addresses to the first letter of the first string in the first list.
I would think that the equivalent of this in c++ would be:
#include <iostream>
using namespace std;
int main()
{
string arr [2] [3] [4]={
{"abcd","efgh","ijkl"},
{"mnop","qrst","xywz"}
};
cout<<arr[0][0][0]<<endl;
return 0;
}
by pointing to the first letter in the first string of the first array. But this prints the first string abcd. My question is why should i put another [0] in order to get to the a?
Your initializer populates the array as follows:
arr[0][0][0] = "abcd";
arr[0][0][1] = "efgh";
arr[0][0][2] = "ijkl";
arr[1][0][0] = "mnop";
arr[1][0][1] = "qrst";
arr[1][0][2] = "xywz";
All other elements are default-initialized to empty string.
Thus, arr[1][0][1] is the string containing "qrst", and arr[1][0][1][1] is the second character of that string, namely 'r'.
You've confused the standard library string object with the concept of a c-string/string literal, and you've helped yourself with this by avoiding the use of the std:: prefix. If we add this, it starts to make more sense:
std::string arr [2] [3] [4]={
{"abcd","efgh","ijkl"},
{"mnop","qrst","xywz"}
};
What you are declaring here is an array of 2 x 3 x 4 instances of std::string. But what you wrote looks like you thought you were declaring character arrays:
char arr [2] [3] [4] = {
{"abcd","efgh","ijkl"},
{"mnop","qrst","xywz"}
};
would almost have the effect you were trying to achieve -- in this case arr[0][0][0] does point to a rather than the string.
Unfortunately the problem here is that you've specified a final dimension of 4 and then supplied 5-character c-strings to the initializer. Remember:
"abcd"
is equivalent to
{ 'a', 'b', 'c', 'd', 0 }
because c-strings are nul-terminated. So you would need to write
char arr [2] [3] [5] = {
{"abcd","efgh","ijkl"},
{"mnop","qrst","xywz"}
};
or, if what you actually want is specifically arrays of characters, not nul-terminated c-strings:
charr arr[2][3][4] = {
{ { 'a', 'b', 'c', 'd' }, { 'e', 'f', 'g', 'h' }, ...
std::string is a discrete object, not an alias for a c-string.
#include <iostream>
#include <string>
int main() {
std::string arr[2][3] = {
{ "abcd", "efgh", "ijkl" },
{ "mnop", "qrst", "wxyz" }, // who needs 'u' or 'v'?
};
std::cout << "arr[0][0] = " << arr[0][0] << "\n";
std::cout << "arr[0][0][0] = " << arr[0][0][0] << "\n";
}
http://ideone.com/JQrDxr
The array you initialized is probably not what you wanted to initialize.
One dimension string array
string arr [2]= {"abcd","efgh"};
Two dimensional string array
string arr [2][2]= {{"abcd","efgh"}, {"ijkl","mnop"}};
Three dimensional string array
string arr [2][2][2]= {
{
{"abcd","qwer"},
{"efgh","tyui"}
},
{
{"ijkl","zxcv"},
{"mnop","bnmo"}
}
};
so, cout<<arr [1] [0] [1] [1]<<endl; will output 'x'
You can't compare python to c++ because in python a list and a string is nearly the same while in c++ there completely different. In Python it doesn't matter if you write
arr=[["abcd","efgh","ijkl"],["mnop","qrst","xwyz"]]
or
arr=[["a","b","c","d","e","f","g","h","i","j","k","l"],
["m", "n","o","p","q","r","s","t","x","w","y","z"]]
because there meaning the same. in c++ instead it treats a string as one "container" which leads to your observed behavior that it will assign these "containers" to the first indexes instead the individual chars. What you can instead do is
char[2][12] arr = {
{"a","b","c","d","e","f","g","h","i","j","k","l"},
{"m", "n","o","p","q","r","s","t","x","w","y","z"}
};

Char array allocation

In C++, if I do:
char myArray[] = {'1','2','3','4','5','6','7','8','9'};
Does that allocate 10 spaces? The last element being '/0'?
What about:
char myArray[9] = {'1','2','3','4','5','6','7','8','9'};
Did I allocate only 9 spaces in this case? Is this bad?
And, finally, what happens when I do:
char myArray[10] = {'1','2','3','4','5','6','7','8','9','/0'};
char myArray[] = {'1','2','3','4','5','6','7','8','9'};
Does that allocate 10 spaces? The last element being '/0'?
No. 9.
char myArray[9] = {'1','2','3','4','5','6','7','8','9'};
Did I allocate only 9 spaces in this case?
Yes.
Is this bad?
No.
and finally what happens when I do
char myArray[10] = {'1','2','3','4','5','6','7','8','9','/0'};
Assuming you meant '\0', exactly what it looks like.
There's no magic in any of these cases — you get precisely what you're asking for.
Automatic null-termination is something that comes into play with string literals:
char myArray1[10] = "123456789";
char myArray2[9] = "123456789"; // won't compile - wrong size
char myArray3[] = "123456789"; // still 10 elements - includes null terminator
No, you'll only get the trailing NUL when using a string literal, i.e.:
// Array of 10 bytes
char myArray[] = "123456789";
// same as:
char myArray[] = {'1','2','3','4','5','6','7','8','9','\0'};
char myArray[] = {'1','2','3','4','5','6','7','8','9'};
This only allocates 9 elements.
char myArray[9] = {'1','2','3','4','5','6','7','8','9'};
Yes, this line also allocates 9 elements.
char myArray[10] = {'1','2','3','4','5','6','7','8','9','/0'};
The last one should be '\0' instead of '/0'.
What you are thinking about should be
char myArray[] = "123456789";
which allocates 10 characters (1 for the trailing '\0' at the end of the string literal)
char arrays don't behave differently than any other arrays when you use list-initialization. Would you expect
int x[] = {1,2};
to magically append a 0 as the last element and make x have 3 elements?
In case you provide fewer elements, then the last ones are value-initialized, so
char myArray[10] = {'1','2','3','4','5','6','7','8','9'};
would be null-terminated, but
char myArray[9] = {'1','2','3','4','5','6','7','8','9'};
isn't.

Why the difference in size when declaring a string in C++?

I should know this, but I don't and I think its probably a major gap in my foundation knowledge so I thought I should ask the experts.
Given:
char s1[] = { 'M', 'y', 'W', 'o', 'r', 'd' };
char s2[] = "MyWord";
cout << strlen(s1)<<endl;
cout << strlen(s2)<<endl;
cout << sizeof(s1)<<endl;
cout << sizeof(s2)<<endl;
Why when declared as s1 is the strlen 9 but when declared as s2 is is 6? Where does the extra 3 come from, it it the lack of a null terminating character?
And I understand that sizeof(s2) is 1 byte larger than sizeof(s2) because s2 will have the null character automatically added?
Please be gentle, TIA!
char s2[] = "MyWord"; Auto adds the null terminator because of the "" declaration.
s1 declaration does not. When you do a strlen on s1 and it comes out to 9 it is because it eventually ran into a \0 and stopped. s1 shouldn't be used with strlen since it is not null terminated. strlen on s1 could have been 1,000. If you turn on memory violation detection strlen of s1 would crash.
The first one lacks the implicit \0 terminator present in the second. Thus:
The first is 1 less than the second, memory-wise
Doing strlen on the first is undefined behavior (since it lacks the terminator)
Lack of terminating null character as you say.
When the strlen function is called on s1, it counts the characters until it finds a terminating '\0'. You may have different result depending on how your memory is initialized.
Your definition of s2 is actually equivalent to
char s2[] = { 'M', 'y', 'W', 'o', 'r', 'd', '\0' };
s1 is only 9 by happenstance; you can only use strlen on terminated strings. Declare it as char s1[] = { 'M', 'y', 'W', 'o', 'r', 'd', '\0' }; and see what happens.
strlen(s1) can return any value > 6. because he is searching for the first '\0' char and you didn't provide it.
In your code,
s1 and s2 are arrays of char.
s1 last element is d, whereas s2 last element is \0.
That is, there is one more character in s2. It is a null-terminated string but s1 is not a null-terminated string.
Since s1 is not a null-terminated string, the expression strlen(s1) would invoke undefined behavior, as strlen will continue reading s1 beyond the last element.