C 中字符数组的未定义行为(?)
当我尝试
char bla[32] = "foobar";
int i;
putchar(bla[i]);
使用 strlen(bla)
我< 32
,bla[i]
始终为 \0
。但这实际上不是未定义的行为,应该避免吗?
when i try
char bla[32] = "foobar";
int i;
putchar(bla[i]);
with strlen(bla) < i < 32
, bla[i]
is always \0
. but isn't this in fact undefined behaviour, and should be avoided?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
C99 标准第 6.7.8 节第 21 段指出:
第 10 段指出静态算术类型(包括 char)被初始化为零。
基于此,当使用字符串文字作为初始值设定项时,您应该期望数组的其余部分被初始化为零。
In section 6.7.8 of the C99 Standard, paragraph 21 states:
And paragraph 10 states that static arithmetic types (which would include char) are initialized to zero.
Based on that, you should expect the rest of the array to be initialized to zero when using a string literal as the initializer.
C89 规范,第 8.7 节“初始化”:
因此,在您的使用中,尾随字符用零初始化。
C89 spec, section 8.7 "Initialization":
So, in your usage, the trailing characters are initialized with zeros.
C 语言在初始化时遵循全有或全无原则。该对象要么完全未初始化,要么完全初始化。后者意味着,如果您指定的初始值设定项少于初始化整个对象所需的数量,则编译器会为您隐式对对象的其余部分进行零初始化。
这适用于所有聚合类型。在您的情况下,它恰好是一个用字符串文字初始化的字符数组。例如,在本例中,
您将获得一个包含 100 个
int
的数组,其中第一个用1
初始化,其余设置为0
。C language follows the all-or-nothing principle when it comes to initialization. The object is either completely uninitialized or completely initialized. The latter means that if you specify fewer initializers than necessary to initialize the entire object, the rest of the object is implicitly zero-initialized for you by the compiler.
This applies to all aggregate types. In your case it just happens to be a character array initialized with a string literal. In this case, for example,
you get an array of 100
int
s with the very first one initialized with1
and the rest set to0
.我认为这是明确定义的行为,实际上是一个功能。只要初始化数组或
struct
中的一个元素,所有未显式初始化的剩余元素都会初始化为0
。I think this is well defined behavior, actually a feature. As long as you initialize one element in an array or
struct
all remaining elements that are not explicitly initialized are initialized to0
.事实上,它是未定义的行为,这意味着它可以做任何事情。它可能每次都会做同样的事情,但所做的事情是任何人的猜测。
The fact that it is undefined behavior means it can do anything. It may do the same anything everytime, but what is done is anyone's guess.
这不是编译器“功能”,而是有据可查的行为。 C 编程语言不保证未初始化变量的值。因此,您只是猜测 i 值是什么,您可以轻松访问不属于您的进程的内存,例如在 Windows 平台上,这将导致访问冲突异常。
有关详细信息,请参阅 http://en.wikipedia.org/wiki/Uninitialized_variable。
That's not a compiler 'feature' but a well documented behavior. The C programming language does not guarantee the value of an uninitialized variable. Therefore you are just guessing what i value is and you can easily access memory which does not belong to your process and on Windows platform, for example, this will lead to Access Violation exception.
See http://en.wikipedia.org/wiki/Uninitialized_variable for more information.
数组未初始化部分的内容取决于它所在的位置(即哪个数据段)。如果它在堆栈上,则未初始化的元素是随机值。一般来说,如果是全局范围的数组,初始内容也是未定义的。如果它提供了
static
说明符,编译器会在程序启动时用零初始化其内容。不禁止访问这个未初始化的部分,并且这不会假定未定义的行为,但结果可能是未定义的。如果
i > 则甚至可以访问
不是未定义的行为,因为您要么有随机值,要么有分段错误异常。bla[i]
sizeof(bla)The contents of uninitialized part of array depends on where it's located (i.e. on which data segment). In case it's on stack, the uninitialized elements are random values. Generally, if it's global-scope array, the initial contents is also undefined. In case it's supplied with
static
specificator, compiler is initialized its contents with zeroes at program start.Accessing this uninitialized part is not prohibited and this doesn't assume undefined behaviour, but the result maybe undefined. Even accessing
bla[i]
ifi > sizeof(bla)
is not an undefined behavior, since either you'd have random value or segmentation fault exception.