繁体   English   中英

C中的字符数组初始化

[英]Character array initialization in C

我试图理解字符串中的数组概念。

char a[5]="hello";

在这里,数组a是大小为5的字符数组。“ hello”占据数组索引的0到4。由于我们已将数组大小声明为5,所以在字符串末尾没有空间存储空字符。 。

所以我的理解是,当我们尝试打印a时,它应该一直打印到遇到空字符为止。 否则也可能会遇到分段错误。

但是,当我在系统中运行它时,它总是打印“ hello”并终止。

任何人都可以澄清我的理解是否正确。 还是取决于我们执行的系统。

像往常一样,答案是:

未定义的行为是未定义的

这意味着,尝试将此字符数组馈送到处理字符串的函数是错误的 这是错误的,因为它不是字符串 C中的字符串是一个以\\0字符结尾的字符序列。

C标准将告诉您这是未定义的行为 因此,任何事情都可能发生。 在C语言中,您没有运行时检查,仅执行代码。 如果代码具有未定义的行为 ,则必须做好任何准备。 这包括意外地进行预期的工作。

数组之后,内存中紧随其后的字节很可能是\\0字节。 在这种情况下,它将查找处理此“字符串”的任何函数,就像您将其传递给有效字符串一样。 崩溃只是等待代码看似无关的更改发生。

您可以尝试添加一些char foo = 42; 在数组定义之前或之后,很可能会在输出中看到它。 但是当然,不能保证,因为再次,未定义的行为是未定义的:)

您所做的是未定义的行为。 显然,您使用的任何编译器都在将数组设置为0后碰巧初始化了内存。

在这里,数组a是大小为5的字符数组。“ hello”占据数组索引的0到4。由于我们已将数组大小声明为5,所以在字符串末尾没有空间存储空字符。 。

所以我的理解是,当我们尝试打印a时,它应该一直打印到遇到空字符为止。

是的,当您使用printf(“%s”,a)时,它将打印字符,直到命中'\\ 0'字符(或出现段错误或其他不良情况-未定义的行为)。 我可以用一个简单的程序演示一下:

#include <stdio.h>

int main()
{
    char a[5] = "hello";
    char b[5] = "world";
    int c = 5;
    printf("%s%s%d\n", a, b, c);
    return 0;
}

输出:

$ ./a.out 
helloworldworld5

在已经读取数组a所有字符之后,您可以看到printf函数继续读取字符。 我不知道什么时候它将停止阅读字符。

我对程序进行了一些修改,以演示这种未定义的行为如何造成严重问题。

#include <stdio.h>
#include <string.h>

int main()
{
    char a[5] = "hello";
    char b[5] = "world";
    int c = 5;
    printf("%s%s%d\n", a, b, c);

    char d[5];
    strcpy(d, a);
    printf("%s", d);
    return 0;
}

结果如下:

$ ./a.out 
helloworld��world��5
*** stack smashing detected ***: <unknown> terminated
helloworldhell�p��UAborted (core dumped)

这是由于行为未定义而导致的堆栈溢出(双关语)的经典案例。

编辑:

我需要强调:这是不确定的行为。 在此示例中发生的事情可能会或可能不会发生,具体取决于您的编译器,体系结构,库等。您可以基于对不同平台上各种库和编译器的不同实现的了解来猜测会发生什么,但是永远无法确定会发生什么。 我的示例是在具有gcc版本7的Ubuntu 17.10上进行的。我的猜测是,如果我在具有不同编译器的嵌入式平台上进行此尝试,则可能会发生完全不同的事情,但是我不能肯定地说。 实际上,如果我将此示例放在同一台计算机上的更大程序中,则可能会发生不同的事情。

暂无
暂无

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

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