0
#include <stdio.h>
#include <string.h>
int main()
{
    char ch[20] = {'h','i'};
    int k=strlen(ch);
    printf("%d",k);
    
    return 0;
} 

The output is 2.

As far as I know '\0' helps compiler identify the end of string but the output here suggests the strlen can detect the end on it's own then why do we need '\0'?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

5 Answers5

2

In this declaration:

char ch[20] = {'h','i'};

the first two elements are initialized explicitly and all other elements are initialized implicitly by zeroes.

The above declaration in fact (with one exceptions that the third element of the array is also explicitly initialized) is equivalent to:

char ch[20] = "hi";

Pat attention to that the string literal is represented as the following array:

{ 'h', 'i', '\0' }

That is the array contains a string that is terminated by the zero character '\0' and the function strlen can successfully find the length of the stored string.

If you would write for example:

char ch[2] = "hi";

then in this case the array ch does not have a space to store the terminating zero of the string literal. In this case applying the function strlen to this array invokes undefined behavior.

halfer
  • 19,824
  • 17
  • 99
  • 186
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

long story short: it's your compiler making proactive decisions based on the standard.

long story:

char ch[20] = {'h','i'}

in the line above what you are implying to your compiler is;

  • allocate a memory big enough to store 20 characters (aka, array of 20 chars).
  • initialize first two slices (first two members of the array) as 'h' & 'i'.
  • implicitly initialize the rest.

since you are initialing your char array, your compiler is smart enough to insert the null terminator to the third element if it has enough space remaining. This process is the standard for initialization.

if you were to remove the initialization syntax and initialize each member manually like below, the result is undefined behavior.

char ch[20];
ch[0] = 'h';
ch[1] = 'i';

Also, if you were to not have extra space for your compiler to put the null terminator, even if you used a initializer the result would still be an undefined behavior as you can easily test via this code snippet below:

char ch[2] = { 'h','i' };

int k = strlen(ch);
printf("%d\n%s\n", k, ch);

now, if you were to increase the array size of 'ch' from 2 to 3 or any other number higher than 2, you can see that your compiler initializes it with the null terminator thus no more undefined behavior.

EmreBugday
  • 36
  • 2
  • "list initializer" is not a C thing. The terminology you seem to be looking for is simply "initializer". The particular initializer given contains an "initializer list", but that detail is mostly inconsequential to the current case. – John Bollinger Jan 25 '22 at 21:31
  • More terminology: C does not have any built-in support for array slicing, so it is unusual to talk about "slices" of an array. The word "members" is ok, but the most idiomatic term is "elements". – John Bollinger Jan 25 '22 at 21:33
  • @JohnBollinger Thanks for the terminology fixes. Though for the array slicing, it's probably a grammar mistake done by me. I didn't meant it as an 'array slice'. I meant it as an slice in the chunk of memory you allocated. – EmreBugday Jan 25 '22 at 21:37
1

A null byte (i.e. the value 0) is what defines the end of a string in C.

When you defined ch, you gave less initializers than values in the array, so the remaining elements are set to 0. This results in a null terminated string.

The strlen function is basically looking for that value and counting how many elements it sees before it finds the null byte.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

As far as I know '\0' helps compiler identify the end of string

Technically, it helps user code and the C runtime library identify the ends of strings. To the extent that the compiler needs to know where strings end, it knows without looking for a terminator.

but the output here suggests the strlen can detect the end on it's own

That would be a misinterpretation. The actual fact is that your string is null-terminated even though you did not put a null terminator in it explicitly. This is a consequence of declaring your array with an initializer that specifies values for only some of the elements. As some of your other answers describe in more detail, that does not produce a partial initialization. Rather, elements for which the initializer does not specify values are default-initialized. For elements of type char, that means initialization with 0, which serves as a string terminator.

Moreover, if the array were without a terminator then the result of passing it to strlen() would be undefined. You could not then conclude anything from the result.

then why do we need '\0'?

So that user code and many standard library functions can recognize the ends of strings. You already know this.

But in many cases we do not need to provide terminators explicitly. In particular, we do not need to represent them in string literals (and it means something different than you probably intended if you do), and you don't need to represent them in the initializers for char arrays storing strings, provided that the array has more elements than you specify in the initializer.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
-3

It is likely that your array ch contained zeros thus the byte after i is already set to zero. You can view it with a debugger or simply test it in the code. Trust me, strlen needs the zero to work.

Mark Radbourne
  • 528
  • 3
  • 12