使用简单函数的静态字符数组初始化说长度是 6,但它不应该是 1 吗?

Static char array initialization with simple function says length is 6, but shouldn't it be 1?

我发现这个程序一直返回 6,直到我开始返回 16 或更大而不是 1,此时程序打印 0。为什么?我的意图是将函数的结果直接传递给静态数组初始化。

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

int ret_1() { return 1; }
int main( int argc, const char* argv[] ) 
{   
    char arr[ret_1()];  
    int l = strlen(arr); 

    printf("The size is: %d\n", l);     
    return 0; 
}

The size is: 6

我想知道这是否是生成任意值的未定义行为,或者是否存在我遗漏的潜在问题。

TL;DR 是的,您的代码调用了 undefined behavior.

在您的代码中,arr 是一个自动本地数组,并且未初始化,数组的内容是不确定的。

数组 上应用 strlen() 调用 undefined behavior,因为您正在尝试读取不确定的值。

解决方案: 正如评论中已经提到的,您可以对数组使用 sizeof 运算符,它处理 type 并且不会尝试 使用 变量的值,从而使您免于 UB。

Static char array initialization with simple function

此声明

char arr[ret_1()]; 

定义了一个数组,其中的元素与ret_1()给定的元素一样多,但未初始化.

然后这个调用

int l = strlen(arr); 

读取(未初始化的)数组的 content/elements 并由此调用未定义的行为。从这一刻起,任何事情都可能发生。

要解决此问题,请执行以下操作:

char arr[ret_1()]; 
memset(arr, 0, sizeof arr); /* Initialise array by (all) zero(s). */

应用修复后,strlen(arr) returns 0,意味着 arr 中的 0 个元素用于表示 "string" .它存储相当于 "" 的空字符串。

注:

此表达式 sizeof arr 实际上 returns 分配给 arr 的字节数,在您的示例中为 1.

除了基本问题 - 初始化 - 您的代码几乎没有其他问题。

strlen() 的 return 类型是 size_t,因此您可能希望执行以下操作:

/* Do the initialization of the array */

size_t l = strlen(arr);
printf("The size is: %zu\n", l); 
/* zu is the specifier for size_t as specified in ANSI C99 */

另请注意,可变长度数组 (VLA) 是一种扩展,可能无法在所有编译器中使用。例如,做

gcc -pedantic your_code.c -o your_code

应该给你

 warning: ISO C90 forbids variable length array 'arr' [-Wvla ]

这里的标志 -pedantic 警告使用的 gnu C 扩展 & -pedantic-errors 标志将此类诊断警告转换为错误。

在像您的问题这样的情况下,printf() 可以成为一个强大的调试工具。为了调试,您可以扩展代码,添加此初始化并观察差异:

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

int ret_1() { return 1; }
int main( int argc, const char* argv[] ) 
{   
    int r = ret_1();
    printf("%d\n", r);
    char arr[r + 1];     //define the char array
    int i = 0;
    for ( ; i < r; i++ ) //initialize char the array
        arr[i] = '0';   
    arr[r] = '[=10=]';       //terminate it

    size_t l = strlen(arr); 

    printf("The size is: %zu\n", l);     
    return 0; 
}