C++ char array

JC724

Weaksauce
Joined
Jan 20, 2016
Messages
118
I have not used a char array in close to two years. I also have not coded in C++ in a while so I think I keep making dumb mistakes. I am just practicing converting char array to strings now.

I was running a few tests cases and I don't understand why some cases work and a couple do not.

I was trying to convert a string to a char array and I was trying to get the first 4 chars of a string and store it in a char array of size 4.

First off, why does this not work?

char testA[4];
testA[0] = "a";

It gives me an error in VS.

Next why does this work if the above case doesn't?

for (int i = 0; i < line.size(); i++) {

testA = line;
}

If I do this below, it will give me the first 4 characters but then more characters of gibberish behind it?

cout << testA <<endl;
 
First off, why does this not work?
Code:
char testA[4];
testA[0] = "a";
"a" is a C string literal of size = 2. There is an implicit null terminator appended to all C string literals. As a char array, this would be the equivalent of { 'a', '\0' }.

(Also worth noting is that C++ additionally treats C string literals as immutable, thus const. Const is an important topic in the additional type safety of C++)

With that in mind...

In C/C++, "a", a C string literal, is not the same type as 'a', a character literal. There are subtle but important differences here.

To the C/C++ type system:
  • "a" is of type char[] which the compiler decays to a char* type (const char* in C++) when on the right hand side of the assignment operator (=)
  • 'a' is of type char
Basically, you are attempting to assign a char array type to a char type which the compiler detects as a programming error. When you use the array index operator ([]), the compiler expects the type on the right hand side of the assignment operator (=) to be of type char. For this particular assignment, use single quotes around the character not double quotes.
Next why does this work if the above case doesn't?
Code:
for (int i = 0; i < line.size(); i++) {

testA = line;
}
Since you are posting incomplete code fragments, I'm going to assume that the variable line is of type std::string.

(Some refer to std::string objects as C++ strings. I prefer to call them STL strings to avoid confusion with C strings)

This code as it stands won't compile. You can't assign anything to testA without using the array index operator. I'm going to take a wild guess that you meant to paste this line as such:
Code:
testA[i] = line[i];
Now this will compile and makes the most sense given the context of what you are saying. Let's assume this for the time being...
If I do this below, it will give me the first 4 characters but then more characters of gibberish behind it?
Code:
cout << testA <<endl;
Most likely what you are seeing are the chars copied plus a whole lot of garbage after it because you didn't ensure your char array is null terminated (btw, STL strings manage their null terminator internally and hide it from the user) printf, std::cout, etc. all expect char arrays, thus C strings, to be null terminated. When you declared testA as a char array, you, as the programmer, must ensure that your C string is null terminated. This means if you intend to store at most 4 characters in a char array, you need to declare your char array of size = 4 + 1 to account for the null terminator.

The fact your program didn't crash here at the print statement is somewhat luck. printf, std::cout will keep printing characters until either reaches a null character (i.e. '\0'). If these print operations don't randomly encounter a null character soon'ish, they could start attempting to read memory outside your process space. Most Operating Systems silently terminate applications when they do this.

When you started copying characters from the STL string into the char array, you probably copied exactly four characters or less ( size() probably returns 4 ). You may or may not see the same garbage if the STL string is initialized less than 4 characters - this will highly depend on how testA is initialized. If testA is zero initialized, and large enough to hold the string plus the null terminator, then you can safely copy STL string elements up until the char array size - 1. You have to be careful to not allow your loop to overwrite that last (array) element in a zero-initialized array.

To be a defensive programmer, you could improve your loop by adding a guard for testA:
Code:
for (int i = 0; i < (sizeof(testA) / sizeof(testA[0])) - 1 && i < line.size(); i++) {

testA[i] = line[i];
}
Where things would have gotten really nasty is if you had initialized STL string line more than 4 characters. This could result in a nasty stack corruption or unexpected behavior because your loop would be writing outside testA's array bounds.

Char arrays, thus C strings, are a pain in the ass to manipulate if you are not careful. C++ string classes, however, are much easier and less prone to bugs due to human error. Your loop example is what C++ veterans call mixed-mode string code. It's where you are bouncing back and forth using C strings and STL strings. If you are new to C/C++, I would advise you don't do this. Stick to one or the other, don't mix both. You'll just end up confusing yourself more and end up writing sloppy code, assuming you don't infuriate yourself beforehand. That said, if you can master C strings (which is no small task), then going back and forth between C strings and STL strings will be less daunting.
 
Last edited:
"a" is a C string literal of size = 2. There is an implicit null terminator appended to all C string literals. As a char array, this would be the equivalent of { 'a', '\0' }.

(Also worth noting is that C++ additionally treats C string literals as immutable, thus const. Const is an important topic in the additional type safety of C++)

With that in mind...

In C/C++, "a", a C string literal, is not the same type as 'a', a character literal. There are subtle but important differences here.

To the C/C++ type system:
  • "a" is of type char[] which the compiler decays to a char* type (const char* in C++) when on the right hand side of the assignment operator (=)
  • 'a' is of type char
Basically, you are attempting to assign a char array type to a char type which the compiler detects as a programming error. When you use the array index operator ([]), the compiler expects the type on the right hand side of the assignment operator (=) to be of type char. For this particular assignment, use single quotes around the character not double quotes.

Since you are posting incomplete code fragments, I'm going to assume that the variable line is of type std::string.

(Some refer to std::string objects as C++ strings. I prefer to call them STL strings to avoid confusion with C strings)

This code as it stands won't compile. You can't assign anything to testA without using the array index operator. I'm going to take a wild guess that you meant to paste this line as such:
Code:
testA[i] = line[i];
Now this will compile and makes the most sense given the context of what you are saying. Let's assume this for the time being...

Most likely what you are seeing are the chars copied plus a whole lot of garbage after it because you didn't ensure your char array is null terminated (btw, STL strings manage their null terminator internally and hide it from the user) printf, std::cout, etc. all expect char arrays, thus C strings, to be null terminated. When you declared testA as a char array, you, as the programmer, must ensure that your C string is null terminated. This means if you intend to store at most 4 characters in a char array, you need to declare your char array of size = 4 + 1 to account for the null terminator.

The fact your program didn't crash here at the print statement is somewhat luck. printf, std::cout will keep printing characters until either reaches a null character (i.e. '\0'). If these print operations don't randomly encounter a null character soon'ish, they could start attempting to read memory outside your process space. Most Operating Systems silently terminate applications when they do this.

When you started copying characters from the STL string into the char array, you probably copied exactly four characters or less ( size() probably returns 4 ). You may or may not see the same garbage if the STL string is initialized less than 4 characters - this will highly depend on how testA is initialized. If testA is zero initialized, and large enough to hold the string plus the null terminator, then you can safely copy STL string elements up until the char array size - 1. You have to be careful to not allow your loop to overwrite that last (array) element in a zero-initialized array.

To be a defensive programmer, you could improve your loop by adding a guard for testA:
Code:
for (int i = 0; i < (sizeof(testA) / sizeof(testA[0])) - 1 && i < line.size(); i++) {

testA[i] = line[i];
}
Where things would have gotten really nasty is if you had initialized STL string line more than 4 characters. This could result in a nasty stack corruption or unexpected behavior because your loop would be writing outside testA's array bounds.

Char arrays, thus C strings, are a pain in the ass to manipulate if you are not careful. C++ string classes, however, are much easier and less prone to bugs due to human error. Your loop example is what C++ veterans call mixed-mode string code. It's where you are bouncing back and forth using C strings and STL strings. If you are new to C/C++, I would advise you don't do this. Stick to one or the other, don't mix both. You'll just end up confusing yourself more and end up writing sloppy code, assuming you don't infuriate yourself beforehand. That said, if you can master C strings (which is no small task), then going back and forth between C strings and STL strings will be less daunting.

THANK YOU!! This was very helpful!
 
Back
Top