C 将数组打印为字符串会在末尾返回奇怪的字符

C 将数组打印为字符串会在末尾返回奇怪的字符,c,arrays,string,C,Arrays,String,我想切掉*argv[]的前两个字符,并将它们存储在一个数组中 int main (int argc, char *argv[]) { char salt[2] = {argv[1][0], argv[1][1]}; printf("%s\n",salt); } 编译后,当我通过键入./program_name asdf在终端上运行此程序时,我希望“asdf”作为*argv[]传入。所以我希望程序会打印出“as”。然而,实际情况是,它将打印出“as”,后跟相同的随机字符。以下是最

我想切掉*argv[]的前两个字符,并将它们存储在一个数组中

int main (int argc, char *argv[])
{
    char salt[2] = {argv[1][0], argv[1][1]};
    printf("%s\n",salt);
}
编译后,当我通过键入./program_name asdf在终端上运行此程序时,我希望“asdf”作为*argv[]传入。所以我希望程序会打印出“as”。然而,实际情况是,它将打印出“as”,后跟相同的随机字符。以下是最近几次发布的内容:

灰烬
asX
询问

as8\8

字符串在C中基本上是以空结尾的字符序列。在数组中只有两个非空字符,因此当您尝试将其打印为字符串时,其结尾是不确定的。这会导致未定义的行为

如果要从字符数组构造字符串,请将数组的大小扩展1,并在末尾添加空字符:

char salt[3] = {argv[1][0], argv[1][1], '\0'};
//        ^ Extend                      ~~~~ Terminate

您没有为终止的NUL字符留出足够的空间,因此它会一直读取,直到在内存中找到下一个NUL为止(这是未定义的行为,如果它没有找到NUL,最终会与SIGSEGV崩溃)

你也可以这样做

char salt[] = {argv[1][0], argv[1][1], 0};
照你做的去做,或者按你做的去做

printf("%c%c\n", argv[1][0], argv[1][1]);

通过将未终止的
char
数组传递给函数
printf()
,调用未定义的行为,该函数需要以null结尾的数组。因此,必须按如下方式存储
'\0'
字符:

int main (int argc, char *argv[])
{
    char salt[3] = {argv[1][0], argv[1][1], '\0'};
    printf("%s\n",salt);
}

别忘了增加你的数组大小

因为字符串在C.NUL终止符Q 35; 00023523761中以null结尾,所以答案不错,特别是注释。
char salt[3]
不是必需的
char salt[]
在计算大小时更好automatically@Jean-弗朗索瓦·法布:或者,如果给定了维度,则不需要显式终止符。C中没有部分初始化器。@Olaf你无处不在:)是的。指定大小或nul-terminate。我个人喜欢nul terminate,这样以后来维护代码并添加另一个字符的人就不会因为大小而出错。@Jean-Françoisfare:我完全不会使用数组。与使用
%c
将字符直接传递给
printf
相比,它几乎不那么复杂。无论如何,这是非常基本和具体的,我认为不值得在这里多呆一天。
int main (int argc, char *argv[])
{
    char salt[3] = {argv[1][0], argv[1][1], '\0'};
    printf("%s\n",salt);
}