如何在 C 中引用出现在需要它的函数之后的静态数据?

How do I reference a static data in C that appears after the function that needs it?

#include <stdio.h>
typedef unsigned char uint8_t;
// I want this at the end of the file
//static const uint8_t hello[] = { 'H','e','l','l','o',' ','W','o','r','l','d','!','[=10=]'};
int main()
{   // how do I declare a forward reference to 'hello' here?
    printf("%s\n", hello);
    return;
}
// but down here, the linker can't resolve it
static const uint8_t hello[] = { 'H','e','l','l','o',' ','W','o','r','l','d','!','[=10=]'};

错误 C2065 'hello': 未声明的标识符

出于美观原因,我想将我的大型静态数据表放在我的 c 源文件的末尾。 但我如何引用它? 我在函数中使用了前向引用来解析文件中后面出现的函数,但是静态变量让我很头疼。 我尝试了 extern(作为最后的希望),但链接器看起来在模块外部(这是有道理的),但不会在需要它的函数后面几行解析到 darn 变量。 这是 C 的限制(我已经在两个编译器上试过了)还是我只是遗漏了一些非常明显的东西?

给你。

#include <stdio.h>
#include <stdint.h>

static const uint8_t hello[]; 

int main( void )
{
    printf("%s\n", hello);
}

static const uint8_t hello[] = { 'H','e','l','l','o',' ','W','o','r','l','d','!','[=10=]'};

这里

static const uint8_t hello[]; 

是数组hello的so-called暂定定义。

即名称hello应在使用前声明。

另一方面,由于名称具有内部链接,因此您可以放置​​其定义

static const uint8_t hello[] = { 'H','e','l','l','o',' ','W','o','r','l','d','!','[=12=]'};

在 header.

I would like to put my large, static data tables at the end of my c source file. But how do I reference it?

使用暂定定义

static const uint8_t hello[13 /* more */];

int main(void) {
  ...
}

static const uint8_t hello[] = { 
    'H','e','l','l','o',' ','W','o','r','l','d','!','[=10=]' };

引用如下。对于 static const uint8_t hello[]; 是否有效存在合理的分歧。我使用的编译器禁止它符合我对规范的阅读。

6.9.2 External object definitions A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.

If the declaration of an identifier for an object is a tentative definition and has internal linkage, the declared type shall not be an incomplete type. C17 § 6.9.2 2&3

J.2 Undefined behavior An identifier for an object with internal linkage and an incomplete type is declared with a tentative definition (6.9.2).