7

Usually char array bulk initialized by memset.

I found in my project code the char array initialized by "\0". Also I compiled and checked, it's Working fine.

My question is this is a right way to bulk initialize the char array?

Eg:

char a[20]="\0";
printf("%s", a);
4
  • 2
    What do you mean by bulk initialise? Commented Jun 3, 2019 at 14:01
  • 1
    It's the same as char a[20]={0, 0} which works because of port70.net/~nsz/c/c11/n1570.html#6.7.9p21 Commented Jun 3, 2019 at 14:04
  • Also the same as char a[20] = ""; A string definition does not need an explicit terminator. Commented Jun 3, 2019 at 14:12
  • bulk initialise means initialise all the elements of array to particular value @EugeneSh. Commented Jun 4, 2019 at 13:33

3 Answers 3

8

Yes, this is one of the correct ways.

For

Quoting C11, chapter §6.7.9

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

and, regarding the initialization for static storage variables,

If an object that has static or thread storage duration is not initialized explicitly, then:

— if it has pointer type, it is initialized to a null pointer;

— if it has arithmetic type, it is initialized to (positive or unsigned) zero;

— if it is an aggregate, every member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;

— if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;

For

Quoting C++17, chapter § 11.6.2

If there are fewer initializers than there are array elements, each element not explicitly initialized shall be zero-initialized.


So, in your case,

char a[20]="\0";

try to initialize the a[0] to '\0', a[1] to '\0' (for null-terminator) and the remaining as 0. FWIW, '\0' has a decimal value of 0, so in this case, all the elements in the array are going to have a value 0.

Some similar initialization statements would be

char a[20] = "";
char a[20] = {0};
char a[20] = {'\0'};

For C++, as suggested in the other answer, including all the previous syntax,

char a[20] = {};

would also work.

Sign up to request clarification or add additional context in comments.

4 Comments

Perhaps it's because the code presented is very much C++. (Consider editing out the cout?)
@Bathsheba I actually linked to your answer for CPP part, but thanks for editing.
@zwol Agreed, added.
Historical note: the string literal zero-initializing the whole array was added in C99; old C89 compilers might not do it
6

It works almost, in a curious way, by accident and is, in my opinion, an exercise in obfuscation. An explanation:

In C++ "\0" is a const char[2] literal with value '\0' (Octal constant with value 0) followed by a NUL-terminator, i.e. both 0 values. In C it's a char[2] constant with the same value.

Initialising a to that also causes the other elements of a to be initialised to 0 too (by the C and C++ standards, the other elements are initialised as per static storage duration).

In C++ writing char a[20] = {} is sufficient, in C you need at least char a[20] = {0}.

Comments

1

Yes. It works because using an initializer to initialize some subobjects (here you're explicitly initializing the first two) causes the rest to be zero-initialized (more precisely initialized as if they were static--namely pointers get set to the null pointer constant even if it isn't all bits zero on the given architecture).

A more general versions of this is:

any_composite_type x={0};

Compilers may and do still implement such initializations with a call to memset

Example:

struct foo{
    char big[1000];
};
void take_foo(struct foo*);
int main()
{
    struct foo obj ={0};
    take_foo(&obj);
}

compiled with clang for x86-64:

main:                                   # @main
        push    rbx
        sub     rsp, 1008
        lea     rbx, [rsp + 8]
        mov     edx, 1000
        mov     rdi, rbx
        xor     esi, esi
        call    memset
        mov     rdi, rbx
        call    take_foo
        xor     eax, eax
        add     rsp, 1008
        pop     rbx
        ret

(In a similar fashion, they may and do replace explicit calls to memset with inlined assembly if they see the object to be memsetted is small.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.