这是我的示例代码。
#include <stdio.h>
#include <string.h>
int main() {
char a[3] = { 'H', 'E', 'L', 'L', 'O', '\0' };
printf("Length is %zd ", strlen(a));
}
我知道这会产生以下警告!
test.c:5:26: warning: excess elements in array initializer
char a[3] = {'H','E','L','L','O','\0'};
现在我的问题是,如果我将大小指定为a[6]
或任何大于我的输出的实际大小。
代表char a[100] = {'H','E','L','L','O','\0'};
输出:
Length is 5
代表char a[10] = {'H','E','L','L','O','\0'};
输出:
Length is 5
对于任何等于或大于数组大小的东西我都得到正确的输出。
但是,当我提供的东西少于实际尺寸总是我会得到 6 作为输出。
代表char a[5] = {'H','E','L','L','O','\0'};
或代a[4]
或a[3]
或a[2]
它总是
Length is 6
虽然是
char a[1] = {'H','E','L','L','O','\0'};
是Length is 1
。
这是什么原因?欢迎任何详细的解释。
答案 0 :(得分:7)
仅仅因为你给了一个包含6个字符的初始值设定项,并不意味着这些字符实际存储在那些小数组的任何地方。
丢弃过多的初始化程序。如果你不知道自己在做什么,可以回来让你的程序形成不良。
考虑a
有两个字符空间的情况。编译器知道这一点,因此它初始化为:
| 'H' | 'e' |
那就是它。虽然它是一个完全有效的字符数组,但它不是有效的C字符串。因为数组不是\0
终止的。将此数组提供给需要C字符串的库函数后,您无法保证任何内容。它使整个程序的行为未定义。
但实际上,strlen
只会访问超出您定义的数组范围的内存。不知道它在那里能找到什么,或者即使曾找到\0
并返回。
答案 1 :(得分:3)
未定义的行为,因为strlen(a)
的读取范围超出a
并导致未定义的行为(例如崩溃)。这意味着一切都会发生。
strlen
仅在空终结符&#39; \ 0&#39;存在于字符数组中。如果不存在则程序行为未定义。
C11 - 7.23.6.3 strlen功能:
strlen 函数返回前面的字符数 终止空字符。
答案 2 :(得分:2)
以下是使用gcc版本4.8.5编译的此程序的部分程序集列表,没有任何优化。
<script type="text/javascript">
$(document).ready(function(){
<% if session.has_key?(:js_code) %>
session.delete(:js_code)
// write your js code here
<% end%>
})
</script>
您可以看到数组 .cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movb $72, -16(%rbp)
movb $69, -15(%rbp)
movb $76, -14(%rbp)
leaq -16(%rbp), %rax
movq %rax, %rdi
call strlen
在堆栈上分配,距离堆栈的基址为0x16。只有字母a
被放在堆栈上。当调用strlen时,它会查看从rbp-16开始的内存,直到遇到第一个HEL
字节。初始化堆栈的方式是在rbp-10位置处遇到这个0字节,所以你的程序打印
0