【问题标题】:Defining a static array into a C or C++ source file将静态数组定义为 C 或 C++ 源文件
【发布时间】:2011-06-06 10:30:44
【问题描述】:

我知道这是每个程序员都应该知道的问题,但我不知道。好久没有C编程了,很多东西都忘记了。

我的问题是:

我在一个头文件中定义了三个巨大的静态数组。有人告诉我,最好在头文件中将它们声明为extern,然后在单个 C 或 C++ 源文件中定义它们。

我该怎么做?

这是我的头文件:

#ifndef _TEMPLE_OBJECT_H_
#define _TEMPLE_OBJECT_H_


#define NUM_TEMPLE_OBJECT_VERTEX 10818

static const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
static const float TEMPLENormals[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
static const float TEMPLETexCoords[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};

#endif

如果使用 C++ 源文件,是否需要定义一个类?

更新:
我认为问题是:
每个包含这些头文件的源文件(甚至是间接的)都会为这些静态数组生成自己的定义。无法保证编译器/链接器会将它们优化为单个定义,即使在未使用它们的源文件中也是如此。事实上,在许多情况下,编译器无法将它们优化掉。这可能会导致您的静态数据占用大量磁盘空间,并且可能还会占用运行时内存。

谢谢。

【问题讨论】:

  • 对于 GCC 和启用优化的构建不应如此。以下是来自 [gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html]https://…" 的“-fkeep-static-consts”的信息“当优化未打开时,即使未引用变量,也会发出声明为静态 const 的变量。GCC 默认启用此选项。如果你想要要强制编译器检查是否引用了变量,无论是否打开优化,请使用 -fno-keep-static-consts 选项。"

标签: c++ c arrays static


【解决方案1】:

staticextern 同时没有意义。文件范围内的static 使其他文件无法访问该数组,而extern 告诉编译器您的数组是在其他地方定义的。

你可以按照 321008 的建议去做,除了你没有声明你的数组是静态的,这是非法的 C 和 C++。这为您提供了三个全局变量,您可以在包含头文件的任何位置使用它们。

例如这样:

// .h file:

extern const float TEMPLEVertices[];

// .cpp (or .c) file:

const float TEMPLEVertices[] = { 1.0, 2.0, 5.6 /* or whatever*/ };

或者您可以按照 fortran 的建议进行操作,但这只会为您提供文件范围的访问权限,而不是全局变量。

如果您使用 C++ 源文件,则不必以任何方式定义一个类。与 Java 不同,C++ 不会强迫您进行面向对象的设计(这是否好可能可以讨论,但无论如何)。

编辑:至于您的问题更新,那是因为您将它们定义为static。如果您只需要全局变量,则不应这样做,而是保留一个定义 (const float) 并使用 extern 引用它,就像我上面的示例一样。

【讨论】:

  • 它可以编译,但链接器会抛出一个错误:undefined reference to TEMPLEVertices'` 和其他两个数组一样。
  • +1 提到“您不必以任何方式在 C++ 源文件中定义类。”
  • @VansFannel:你的代码是什么?你能用它更新你的问题吗?请注意,您必须在要使用数组的任何位置包含 .h 文件。
  • @VansFannel:那你抄错了。提供的代码必须编译和链接。
  • 和@jweyrich:你是对的。我忘记添加新的 C 源文件来生成文件。对不起。
【解决方案2】:

我曾经在 Quake2 源代码中看到一个有趣的“技巧”,实际上这只是使用包含的一种不寻常的方式:

只是做:

static const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {
#include "TEMPLEVertices.txt"
};

等等

只保留包含文件中的数据。

您仍然可以在编译单元中将它们声明为extern,但这会使事情变得更整洁。

【讨论】:

  • 感谢您的回答,但我想我会遇到同样的问题。我已经更新了我的问题,提供了有关该问题的更多详细信息。
【解决方案3】:

你的头文件变成:

#ifndef _TEMPLE_OBJECT_H_
#define _TEMPLE_OBJECT_H_


#define NUM_TEMPLE_OBJECT_VERTEX 10818

extern const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3];
extern const float TEMPLENormals[NUM_TEMPLE_OBJECT_VERTEX * 3];
extern const float TEMPLETexCoords[NUM_TEMPLE_OBJECT_VERTEX * 3];

#endif

当你的源文件变成:

// include header
const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
const float TEMPLENormals[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
const float TEMPLETexCoords[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};

// rest of the source

更新:如果您明确指定数组,则不必提及大小。那是你可以做的:

const float TEMPLEVertices[] = {...};

const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3];

【讨论】:

  • 你就是这样做的! @Øystein:你认为它有什么问题?
  • @341008:不能在static 变量中使用extern,否则会出现链接错误。
  • 你为什么用extern const float *TEMPLEVertices而不是extern const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3]
  • @VansFannel:你在尝试我的吗?如果是这样,请评论我的答案并告诉我有什么问题:) 如果您正在尝试上面答案中的代码,那是不合法的,应该会失败。
  • 对不起,伙计们。被叫走了,回来发现有很多人在为这个代码sn-p工作。你们都是对的。 static 关键字应该被删除(责备复制粘贴在这里)。始终使用 []/[n] 而不是在标题和源代码中混合[]/*(在这里怪我)。对困惑感到抱歉。更新了代码。
【解决方案4】:

其实很简单;我将用一个更简单的例子来演示,一个简单的原始常量。

在您的项目中,您有两个文件pi.hpi.cpp

pi.h 的内容是这样的:

#ifndef _PI_H
#define _PI_H

extern const double PI;

#endif

pi.cpp 的内容如下所示:

#include "pi.h"

const double PI = 3.1415926535;

如果你想使用这个常量,你只需在必要的地方包含pi.h。该值将始终从同一位置读取。

几乎任何东西都可以做到这一点——数组、对象、对象数组、STL 容器等。只要确保不要过度使用这种技术——尤其是当声明为extern 的对象不是const 时,你可能创建一些非常难以跟踪的副作用。但是对于常量数据,这是你做的。

【讨论】:

    【解决方案5】:


    我通常使用一个简单的技巧。

    a) 在每个 C/CPP 文件中我定义 文件名_C
    b) 在每个 H/HPP 文件中我定义 filename_H

    比...

    这将是您的包含文件

    #ifndef _TEMPLE_OBJECT_H_
    #define _TEMPLE_OBJECT_H_
    
    #define NUM_TEMPLE_OBJECT_VERTEX 10818
    
    #ifdef _TEMPLE_OBJECT_C
    const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...} ; /* Put here your const values */
    #else
    extern const float TEMPLEVerticies[] ;
    #endif
    
    #endif
    

    如果我没记错的话,这应该可以工作(或类似的东西)... :o)

    【讨论】:

    • 我想将数组定义放在 C 或 C++ 源文件中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 2011-08-17
    • 1970-01-01
    • 2012-05-30
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多