静态 c 函数 return 可以是本地字符数组吗?

Can a static c function return a local char array?

在 zflog 库中我看到了这段代码

static char* lvl_char(const int lvl)
{
    switch (lvl)
    {
    case ZF_LOG_VERBOSE:
        return "VERBOSE[=11=]";
    case ZF_LOG_DEBUG:
        return "DEBUG[=11=]";
    case ZF_LOG_INFO:
        return "INFO[=11=]";
    case ZF_LOG_WARN:
        return "WARN[=11=]";
    case ZF_LOG_ERROR:
        return "ERROR[=11=]";
    case ZF_LOG_FATAL:
        return "FATAL[=11=]";
    default:
        ASSERT_UNREACHABLE("Bad log level");
        return "?[=11=]";
    }
}

这对我来说似乎很奇怪。我们真的可以 return 来自静态函数的本地 c 字符串吗?

你错了,返回的指针不是指向本地的char array,而是指向string literal,也就是进程的static

来自c-standard

6.4.5 String literals

Sematics

In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals.78) The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.[...]

强调我的

函数(这里是静态的)的链接根本不重要。 "string" returned 也不是;相反,returned 是指向 char 的指针。 return 指向字符串文字的第一个字符的指针是完全合法的 - 字符串文字保证在程序的整个持续时间内存在。 C11 6.4.5p6 states that the string literals as they're used here are used to initialize *"an [anonymous] array of static storage duration and length just sufficient to contain the sequence". Static storage duration means that its "lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup." (C11 6.2.4p3).


确实看起来奇怪的是字符串文字末尾的[=10=],因为文字字符串总是以0结尾,所以本质上"VERBOSE[=11 =]" 将以 2 个零字节而不是通常的一个字节结尾;该字符串的 strlen 将 return 7 就像 "VERBOSE" 的 return 一样,依此类推。

Can a static c function return a local char array?

TL;DR 无论 static 还是 extern,函数都不应该 return 局部数组,因为它不能被有意义地使用。


现在,详细说明手头的问题,

....static functions?

你有它,static 与 "function" 的链接相关联,而不是 return 值或类型

此处,static 存储说明符表示该函数具有内部链接,即只能从翻译单元访问。

相关 C11,章节 §6.2.2

If the declaration of a file scope identifier for an object or a function contains the storage class specifier static, the identifier has internal linkage.

OTOH,return 语句如

return "FATAL[=10=]"; 
return "DEBUG[=10=]"; ///and so on

实际上return指向string literal的第一个元素的指针,根据定义具有静态存储持续时间注1,所以return 值为

  • 匹配return类型,char * 注2
  • 在return语句之后有效。 注3

注一:

引用 C11,章节 §6.4.5/ P6

In translation phase 7, a byte or code of value zero is appended to each multibyte character sequence that results from a string literal or literals.78) The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence. For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence.

注2:

引用章节 §6.3.2.1/P3,

Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.

注3:

引用章节 §6.2.4/P3

An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.

  • 静态 c 函数可以 return 本地字符数组吗?不,这会导致未定义的行为。
  • 您的代码 return 是本地字符数组吗?不,它 return 是一个指向字符串文字的指针,它驻留在只读内存中。此内存不在本地。
  • 你能 return 从任何函数得到一个指向字符串文字的指针吗?是的
  • 这里的常规函数​​和内部链接 static 之间有区别吗?编号