(09-13-2015, 10:54 AM)OversouL Wrote: cout outputs str_2 and it stops reading what's in an array if str_1[i] is the null terminator.
Thanks, but I still don't quite get some of what you said, except for the null terminator not being copied part. Can you please explain what (!str[i]) does exactly? Also what do you mean that I don't zero-initialize the buffer?
EDIT: Oh I get the !str[i] part now. The null terminator is kind of like a false value right? And putting a not operator makes the value true and therefore executing the if statement. Am I right?
Exactly "it stops when str_1[i] is the null terminator, before it copies the null terminator". The for loop conditional is a pre-condition. Thus if a null terminator is found, the for loop won't do that one iteration you need to copy the null-terminator to the new buffer.
!str[i] negates the character value. In terms of the standard, anything 0 is false, and anything non-zero is true. 1, 2, 3, 4, -5, -7, -1, -2, etc... Are all true, and 0 is false. There are other expressions that are false but you don't need to worry about them for now, and basically they are semantically 0 anyways. '\0' is a character with an integral value of 0 -- it's important to note that when looking at my code.
This is zero-initialization:
Or C++11:
In C, you have to use a 0:
Code:
char buf[MAX] = { 0 };
But that same line will work the same in C++.
You can also memset it, or use a function like calloc() if you want it to be zero-initialized. If you understand where the null-terminator should go though then there's really no need to waste time writing over the buffer with 0's when only 1 of those will act as a null terminator and most will be overwritten with string data... Unless, you are attempting to store 2 strings within the buffer or you have a chance that some pointer will potentially point within the allocated space but past the null-terminator which might result in a buffer overrun if you call functions like printf without a clever format specifier.
As for your question about why garbage is outputted, take a look at a function like this:
Code:
void print_string(const char *s) // s points to the first character within the buffer from what we passed in
{
while (*s != '\0') // while current character at pointer is not the null-terminator
{
putc(*s, stdout); // dereference char pointed to by pointer, and output that character to standard output
++s; // increment pointer to point to next character in buffer
}
// s points to the null terminator, we're done...
}
int main()
{
char str[] = { 't', 'e', 's', 't', '\0', 'i', 'n', 'g' }; // declaring strings like this we have to explicitly add null-terminators. In this case one doesn't exist after the 'g'
print_string(str); // print "test"
}
I wrote it to be explicit with clarity about what happens with lots of string functions in <string.h>, but a few functions for I/O stuff in <stdio.h>.
Functions like strcpy(), printf() with the plain old "%s" format string, puts, fputs, etc... All depend on the null terminator as one of their pre-conditions for outputting chars from a buffer.
Think about it, If I have a buffer, and I pass you a pointer to the first char in that buffer. From a pointer there's really no way to determine the size of a buffer once function scope has been entered. The only way is to pass the length of the buffer as a parameter along with the pointer that you passed in as one parameter. If no length is specified, chances are the function relies on the null terminator being there to tell them that this is where we want it to stop.