tags:

views:

161

answers:

8

Hello,

I am new to C and reviewing some source code. But I am not sure what is happening with this code snippet.

I really don't think it is doing anything, as in the debugging the output seems to be the same for tempstr.

This is what I think, correct if I am wrong. *(tempstr + strlen(line)) is adding the length of line to tempstr and dereferencing and assigning the 0x0 converted to a char?

char line[128], tempstr[128]

strcpy(line, "AUTO_ANSWER_CALL = 1");
strcpy(tempstr,line);
*(tempstr + strlen(line)) = (char) 0x0; // Confusing part
+1  A: 

Yes, this code is zero-terminating the string.

JR
Isn't easier just to do the following tempstr[sizeof(tempstr)] = '\0'; this is much easier to understand.
robUK
sorry, that should be: tempstr[sizeof(tempstr) -0] = '\0';
robUK
sorry, maybe rushing too much here should have been minus 1 instead of zero.
robUK
Actually it needs to be -1 as originally stated, otherwise you would replace the last character of the original string with a zero byte. The total length of the string is sizeof(tempstr) if you include the null terminator, but the array is zero-based so you end up with the first solution being correct.
JR
+12  A: 

First, note that the code is crap.

*(tempstr + strlen(line)) = (char) 0x0;

It looks like the original author wasn't too sure if strcpy copied the terminating nul character so he made doubly sure instead of checking the manual (btw, strcpy does copy the terminating null).

That is basically the same as:

tempstr[ strlen(line) ] = (char) 0;

The cast to char is there, I guess, because of the possibility of a C++ compiler being used to compile this code.

I am not sure why

char line[128] = "AUTO_ANSWER_CALL = 1";

was not acceptable.

Sinan Ünür
Assumably, whoever originally wrote the code heard that `char *line = "whatever";` leaves an unmodifiable string, and didn't know that `char line[128] = "whatever"` works differently. Or didn't know about the latter at all.
derobert
+1  A: 
*(tempstr + strlen(line)) = (char) 0x0; // Confusing part
// or
tempstr[strlen(line)]) = '\0'; // null terminate

It's superfluous because strcpy() will do it anyway.

Nick D
+2  A: 

It does nothing. It tries to null-terminate a string which is already terminated.

ZZ Coder
+2  A: 

Looks to me like it is placing a null terminator (Char 0) at the end of the data it has copied into tempstr using strcpy().

strcpy(tempstr, line)

Copies the contents of line into tempstr, but the author is perhaps unsure whether tempstr will be null terminated after this operation. My C is rusty, and to be fair, I'm not sure either. :)

However, for the code to work as intended I think line, and therefore tempstr, must be already null terminated (strlen(line) will count to the first null terminator), so for the code to work as expected it must also be utterly redundant, as strcpy() will have copied the null terminator when it copied line in the first place!

i.e. // Confusing part is actually a null operation and can be removed. :)

Deltics
+1  A: 

It helps to understand that string constants like "AUTO_ANSWER_CALL = 1" must be assumed to be immutable. So what goes on here is two string buffers are declared:

char line[128], tempstr[128]; // <== better have the semicolon

at this point their contents are totally unknown.

Next a prepared text is copied into one of them.

strcpy(line, "AUTO_ANSWER_CALL = 1");

and then into the other

strcpy(tempstr,line);

Finally a little pointer arithmetic is used to stick a null character '\0' == 0x0 onto the end to ensure that the string is properly terminated:

*(tempstr + strlen(line)) = (char) 0x0; // Confusing part

which is equivalent to

tempstr[strlen(line)] = (char) 0x0;
dmckee
+2  A: 

This is a pointer value:

tempstr

This is another pointer value (which points to 5 elements beyond the tempstr pointer value):

tempstr + 5

This is an integer:

strlen(line)

Therefore, this is a pointer value (which points to strlen(line) elements beyond the tempstr pointer value):

tempstr + strlen(line)

And this is dereferencing that pointer:

*(tempstr + strlen(line))


This is what I think, correct if I am wrong. *(tempstr + strlen(line)) is adding the length of line to tempstr and dereferencing and assigning the 0x0 converted to a char?

It's ensuring that the character at index 20 of tempstr, immediately beyond the "AUTO_ANSWER_CALL = 1" characters, is null: i.e. it's ensuring that the string is null-terminated.

That string already is null-terminated, by the way (so that last statement is redundent): because strcpy copies the string including the implicit null-termination character.


Isn't easier just to do the following tempstr[sizeof(tempstr)-1] = '\0'; this is much easier to understand.

These aren't the same thing: strlen(line) equals 20, but sizeof(tempstr) equals 128.


would this work: tempstr[strlen(tempstr)] = '\0'

That's exactly the same things as:

*(tempstr + strlen(tempstr)) = '\0'

Just a different way of writing it.

However, if tempstr is NOT a null terminated string, the length would be 128 as well.

If tempstr is NOT a null terminated string then strlen(tempstr) is undefined ('undefined' means that it's meaningless and dangerous, a bug, and shouldn't be used): the strlen function isn't valid except when it's used on a string that's already null-terminated.

ChrisW
would this work: tempstr[strlen(tempstr)] = '\0'; However, if tempstr is NOT a null terminated string, the length would be 128 as well. Because I am getting the length of a undetermined length? Thanks.
robUK
appended to my answer
ChrisW
+2  A: 

As said by others here code is basically adding a '\0' at the end of the string even though it is already present. Is this all of the code or there are lines in between? It could make some sense if say a memcpy() is used in between those lines. On the lighter note the code was probably written by a myopic geek who suffered from a inferiority complex.

Rohin
The line is initialized by using fgets from a file pointer. I just added it here to make the code more simple. However, I am sure there are other ways to terminate a string?
robUK