strlen给出了意想不到的输出C.

时间:2017-07-19 05:16:52

标签: c string

这是我的示例代码。

#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

这是什么原因?欢迎任何详细的解释。

3 个答案:

答案 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