C++ Static Array Initialization - Memory Issue
I have a header file which contains a member variable declaration of a static char array:
class ABC
{
public:
static char newArray[4];
// other variables / functions
private:
void setArray(int i, char * ptr);
}
In the CPP file, I have the array initialized to NULL:
c开发者_如何学Pythonhar ABC::newArray[4] = {0};
In the ABC constructor, I need to overwrite this value with a value constructed at runtime, such as the encoding of an integer:
ABC::ABC()
{
int i; //some int value defined at runtime
memset(newArray, 0, 4); // not sure if this is necessary
setArray(i,newArray);
}
...
void setArray(int i, char * value)
{
// encoding i to set value[0] ... value [3]
}
When I return from this function, and print the modified newArray value, it prints out many more characters than the 4 specified in the array declaration.
Any ideas why this is the case. I just want to set the char array to 4 characters and nothing further.
Thanks...
How are you printing it? In C++ (and C), strings are terminated with a nul. (\0
). If you're doing something like:
char arr[4] = {'u', 'h', 'o', 'h'};
std::cout << arr;
It's going to print "uhoh" along with anything else it runs across until it gets to a \0
. You might want to do something like:
for (unsigned i = 0; i < 4; ++i)
std::cout << arr[i];
(Having a static
tied to instances of a class doesn't really make sense, by the way. Also, you can just do = {}
, though it's not needed since static
variables are zero-initialized anyway. Lastly, no it doesn't make sense to memset
something then rewrite the contents anyway.)
cout.write(arr, count_of(arr))
If count_of
isn't defined in a system header:
template<typename T, size_t N>
inline size_t count_of(T (&array)[N]) { return N; }
Are you printing it using something like
printf("%s", newArray); //or:
cout << newArray;
? If so, you need to leave space for the nul-terminator at the end of the string. C strings are just arrays of characters, so there's no indication of the length of the string; standard library functions that deal with strings expect them to end in a nul (0) character to mark the ending, so they'll keep reading from memory until they find one. If your string needs to hold 4 characters, it needs to be 5 bytes wide so you can store the \0
in the fifth byte
You'll need a 5th character with a 0 byte to mark the end of the 4 character string, unless you use custom char-array output methods. If you set value[3] to something other than 0, you'll start printing bytes next to newArray in the static data area.
There's also no need to explicitly 0 initialize static data.
You can best catch those kinds of errors with valgrind's memcheck tool.
It is printing out a string that starts at the address &newArray[0] and ends at the first 0 in memory thereafter (called the null terminator).
char strArr[] = {"Hello"};
char strArr[] = {'H', 'e', "llo");
char strArr[] = "Hello";
char* strArr = "Hello"; // careful, this is a string literal, you can't mess with it (read-only usually)
...are all null terminated because anything in double quotes gets the null terminator tacked on at the end
char strArr[] = {'H', 'e', 'l', 'l', 'o'};
...is not null terminated, single quotes contain a single character and do not add a null terminator
Here are examples of adding a null terminator...
strArr[3] = '\0';
strArr[3] = NULL;
strArr[3] = 0;
With a bit loss of performance, you can fit into 4 byte.. in 'c-style'.
Print either 4 characters or until \0 is reached:
#include <cstdio>
#include <cstring>
...
//calculate length
size_t totalLength = sizeof(ABC::newArray) / sizeof(ABC::newArray[0]);
char* arrayEnd = (char*)memchr(ABC::newArray, '\0', totalLength);
size_t textLength = arrayEnd != 0 ?
arrayEnd-ABC::newArray : totalLength;
//print
fwrite(
ABC::newArray, //source array
sizeof(ABC::newArray[0]), //one item's size
textLength, //item count
stdout); //destination stream
By the way, try to use std::string
and std::cout
.
精彩评论