-2

I am stuck with some features that \0 has.

I know that \0 is a null character and it is a term to indicate that the formal is a string.

int j;

j = printf("abcdef\0abcdefg\0");

printf("%d", j);

return 0;

When I tried to print "abcdef\0abcdefg\0" out, C would only print string 'abcdef' and '6' instead of both 'abcdef' and 'abcdefg' which would sum up to 13. Why does this happen?

skkupharah
  • 17
  • 3
  • 2
    for the _printf_ point of view your string is "abcdef". Why do you expect it has to continue after the first null character ? – bruno Jun 30 '19 at 13:20
  • 3
    String literals can have any characters in them (including \0), but library functions determine the end of the string by the first \0 they see. – teppic Jun 30 '19 at 13:23
  • @bruno I thought printf would consider that there are two strings inside. I must be misunderstanding something. – skkupharah Jun 30 '19 at 13:30
  • @skkupharah _printf_ has no way to know how the string is built/coming, it does not know you use a literal string nor how you defined it. Like for any function managing string the character 0 indicates the end, that is all – bruno Jun 30 '19 at 13:32
  • 2
    @skkupharah a string literal is just a series of arbitrary bytes in memory, there's no string type in C. printf() or any other string function only gets an address in memory and has to "wing it" from there, the first \0 found is seen as the end of the string and it stops there. – teppic Jun 30 '19 at 13:38
  • @bruno I got the point now. Thanks! – skkupharah Jun 30 '19 at 13:44

3 Answers3

0

Here

j = printf("abcdef\0abcdefg\0"); /* printf stops printing once \0 encounters hence it prints abcdef */

printf() starts printing from base address of string literal "abcdef\0abcdefg\0" i.e from a until first \0 char encounters. So it prints abcdef.

 -----------------------------------------------------------------
| a | b | c | d | e | f | \0 | a | b | c | d | e | f | f | g | \0 |
 -----------------------------------------------------------------
0x100 0x101 ...............|                                0x100 - assume this as base address of the string literal      
  |                        |
starts printing      when printf sees
from 0x100 memory    first \0
location             it stops the printing & returns.

And then printf() returns number of printable characters i.e 6.

printf("%d", j); /* prints 6 */

From the manual page of printf

RETURN VALUE

Upon successful return, these functions return the number of characters printed (excluding the null byte used to end output to strings).

Achal
  • 11,821
  • 2
  • 15
  • 37
  • So to clarify, printf function accepts \0 as a signal to end reading. Did I get that right? – skkupharah Jun 30 '19 at 13:21
  • Yes. Thats right. – Achal Jun 30 '19 at 13:22
  • @skkupharah for plenty of functions the null character ends the strings, and fortunately it is automaticaly added by the compiler, you do not need to write"abcdef\0", just write "abcdef" – bruno Jun 30 '19 at 13:22
0

A string in C is a sequence of characters followed by a NUL character, which is '\0'. There is no separate "length" field.

When a string appears as a literal, such as "hello", what actually gets stored in memory is:

'h', 'e', 'l', 'l', 'o', '\0'

So you can see that if your string itself contains a '\0', as far as any of the C standard library functions are concerned, that's the end of the string.

Once printf see the first '\0' in your string, it stops printing and returns, because that's the end of the format string. printf has no way of knowing that there's another string after the '\0'. Maybe there is--or maybe there's just random other program data in memory after that point. It can't tell the difference.

If you want to actually print the '\0' characters, then you need to have some other way to track the "real" length of the string and use a function that accepts that length as a parameter. Alternately you could add the '\0' characters during the formatting process by specifying %c in the format string and passing 0 as the character value.

Willis Blackburn
  • 8,068
  • 19
  • 36
0

"abcdef\0abcdefg\0", the string literal, is effectively a static, const (for all intents an purposes) char array and so it has an associated size that the compiler maintains:

#include <stdio.h>
#define S "abcdef\0abcdefg\0" 
//^string literals implicitly add a(nother) hidden \0 at the end
int main()
{
    printf("%zu\n", sizeof(S)); //prints 16
}

But arrays are treated specially in C and passing them as a parameter to a function or almost any operator converts them to a pointer to their first element.

Pointers do not have an associated size.

When you pass a char const* to a function (e.g., printf), the function receives just one number--the address of the first element.

The way printf and most string functions in C obtain the size is by counting character until the first '\0'.

If you pass a pointer to the first element of a char array that has explicit embedded zeros in it, then for a function that counts until the first '\0', the string effectively ends at the first '\0'.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142