15

In my class we are writing our own copy of C's malloc() function. To test my code (which can currently allocate space fine) I was using:

char* ptr = my_malloc(6*sizeof(char));
memcpy(ptr, "Hello\n", 6*sizeof(char));
printf("%s", ptr);

The output would typically be this:

Hello
Unprintable character

Some debugging figured that my code wasn't causing this per se, as ptr's memory is as follows:

[24 bytes of meta info][Number of requested bytes][Padding]

So I figured that printf was reaching into the padding, which is just garbage. So I ran a test of: printf("%s", "test\nd"); and got:

test
d

Which makes me wonder, when DOES printf("%s", char*) stop printing chars?

Joe
  • 46,419
  • 33
  • 155
  • 245
user327406
  • 223
  • 2
  • 3
  • 5

4 Answers4

31

It stops printing when it reaches a null character (\0), because %s expects the string to be null terminated (i.e., it expects the argument to be a C string).

The string literal "test\nd" is null terminated (all string literals are null terminated). Your character array ptr is not, however, because you only copy six characters into the buffer (Hello\n), and you do not copy the seventh character--the null terminator.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
5

James is correct about printf stopping when it gets to the null character, and Uri is correct that you need to allocate a 7-character buffer to hold "hello\n".

Some of the confusion with terminators would be mitigated if you used the usual C idiom for copying a string: strcpy(ptr, "Hello\n"), rather than memcpy.

Also, by definition, sizeof(char) == 1 in C, so 6*sizeof(char) is redundant

David Gelhar
  • 27,873
  • 3
  • 67
  • 84
  • 2
    6*sizeof(char) may be redundant but it is, in my opinion, good practice for the simple reasons (1) if a char on some new architecture is not = 1 or (2) this code is ported to wchar_t.... – Eric May 10 '11 at 01:37
  • 4
    It wouldn't just be a new architecture, it would be a new language. If `sizeof(char) != 1`, you are no longer programming in C. http://stackoverflow.com/questions/2215445/are-there-machines-where-sizeofchar-1 – David Gelhar May 10 '11 at 05:03
3

C strings are null terminated (there's a \0 character at the end), that's how C knows when to stop printing or dealing with the buffer as a string . It is your responsibility to never put a string in a longer space than what you have allocated.

Note that Hello\n is not a six character string, it is actually a seven character string. You use five for the Hello, one for the newline, and one for the null terminator.

Trying to fit 7 characters into a six character buffer is considered a bug, I am not sure if it is responsible for the problems you are currently having, but it seems like the copying of 6 characters would not copy the null terminator. So I would actually expect your print to go beyond the Hello and into some actual junk.

Uri
  • 88,451
  • 51
  • 221
  • 321
  • Dur, I should be using \0 to terminate strings? Dur Dur Dur – user327406 Apr 28 '10 at 01:36
  • You don't have to add \0 yourself. When you create a literal string or get one as input, C adds it for you. You don't actually see the \0. That "Hello\n" string is seven characters if you looked at the actual assembly code. – Uri Apr 28 '10 at 01:37
0

when it reaches a zero. you need 7 chars.

Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58