简体   繁体   English

Bulk用“\\ 0”而不是memset()初始化char数组

[英]Bulk initialize the char array by “\0” instead of memset()

Usually char array bulk initialized by memset . 通常由memset初始化的char数组批量。

I found in my project code the char array initialized by "\\0" . 我在项目代码中找到了由"\\0"初始化的char数组。 Also I compiled and checked, it's Working fine. 我编译和检查,它的工作正常。

My question is this is a right way to bulk initialize the char array? 我的问题是这是批量初始化char数组的正确方法吗?

Eg: 例如:

char a[20]="\0";
printf("%s", a);

Yes, this is one of the correct ways. 是的,这是正确的方法之一。

For 对于

Quoting C11 , chapter §6.7.9 引用C11 ,章节§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, 并且,关于static存储变量的初始化,

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 引用C++17 ,第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 . 尝试将a[0]初始化为'\\0'a[1]初始化为'\\0' (对于空终止符),剩余为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 . FWIW, '\\0'的十进制值为0 ,因此在这种情况下,数组中的所有元素都将具有值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, 对于C++ ,正如其他答案中所建议 ,包括所有以前的语法,

char a[20] = {};

would also work. 也会有用。

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, ie both 0 values. 在C ++中, "\\0"是一个const char[2]文字,其值为'\\0' (八进制常量值为0),后跟一个NUL终结符,即两个0值。 In C it's a char[2] constant with the same value. 在C中,它是一个具有相同值的char[2]常量。

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). 初始化a到也导致的其它元件a将被初始化为0太(由C和C ++标准,其它元件被初始化为每static存储持续时间)。

In C++ writing char a[20] = {} is sufficient, in C you need at least char a[20] = {0} . 在C ++中编写char a[20] = {}就足够了,在C中你至少需要char a[20] = {0}

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 编译器可能并且仍然通过调用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: 用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 memset ted is small.) (以类似的方式,如果他们看到要设置为memset的对象很小,他们可以并且确实用内联汇编替换对memset显式调用。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM