在C语言中定义数组

15
我有几个450元素的字符数组(存储用于在液晶屏幕上显示的位图数据)。我想把它们放在一个头文件下并#define它们,但是我一直得到编译错误。我该如何在C语言中做到这一点?

#define numbers[450] {0, 1,etc...}

#define numbers {0, 1, etc...}

#define numbers[450] 然后稍后设置数字

还有很多其他方法...


6
你为什么不把你目前的代码和编译器错误贴出来呢? - Erik Dietrich
2
你不能这样 #define。想一想,每次使用它时,你都会声明一个新的数组。当然,这将导致多个重新定义。宏只是文本替换。自己替换文本,看看是否有意义。 - Ed S.
4个回答

16

嗯……你肯定不需要使用宏定义。只需将它们作为常量、静态数组添加到头文件中即可。

/* prevents multiple, redundant includes */
/* make sure to use a symbol that is fairly sure to be unique */
#ifndef TEST_H
#define TEST_H

/* your image data */
const char image[] = { 1, 2, 3, 4, ... };

#endif

另外,如果你想获得编译错误的帮助,那么你应该发帖发布你的代码。


是的,但当头文件被多次调用时(在程序的多个部分中需要),我会遇到错误。 - Reid
4
那么您需要使用一个“包含保护器”(include guard),并且再次展示一些例子。我不知道“调用头文件”的意思,但我猜您是指包含它。就像我说的...给一个例子吧。我们又不是通灵的。 :) - Ed S.
谢谢。我会尝试使用#ifndef,我之前没有想到过。 - Reid

12

因为您正在LCD上显示,我假设这是一个嵌入式系统。

不要将数据放入头文件中。

将数据放入普通的C或C++文件中。编译这个文件。它可能只包含数据,这没问题,也很容易更新。

然后使用头文件来访问数据。

例如,在一个images.c文件中:

#include "images.h"
const byte numbers1[MAX_NUMBERS1] = { ... };
byte numbers2[MAX_NUMBERS2];       // will be initialsied to 0

images.h的内容如下:

#ifndef _IMAGES_H_
#define _IMAGES_H_

typedef unsigned char byte;
#define MAX_NUMBERS1 (450)
        // different constants in case you change something        
#define MAX_NUMBERS2 (450)      
       // even better if you can do const static int MAX_NUMBERS1=450; 
       // but depends on the compiler
extern const byte numbers1[MAX_NUMBERS1] = { ... };
extern byte numbers2[MAX_NUMBERS2];       // will be initialised to 0

#endif
然后程序中的所有其他.c文件都可以访问它们。
将一个变量的定义放在头文件中(几乎)总是一个坏主意。
变量的声明,例如 extern byte numbers2 [MAX_NUMBERS2]; 告诉C编译器在最终链接的程序中的某个地方有一个名为numbers2的数组变量。如果链接器没有从其他地方得到该定义,则会引发错误,因为未分配变量的空间。
变量的定义(注意没有外部),例如 byte numbers2 [MAX_NUMBERS2]; 有效地告诉C编译器有一个名为numbers2的数组变量,并且应该在此处分配空间,在此源文件生成的目标代码中使用它来保存变量的值,最终链接的程序中。
当看到一个声明(由extern前缀符号)时,C编译器不会为numbers2分配空间,而是在看到实际的定义(没有extern)时分配空间。
因此,如果将任何变量的实际定义放在头文件中,并将其包含到多个源代码文件(.c)中,则C编译器将为该变量分配多次空间。然后,链接器将给出错误(通常是相同名称的多个定义)。
还有一个更微妙的问题。如果在首次开发程序时,头文件仅包含在一个源文件中,则程序将正确编译和链接。然后,在稍后的日期,如果第二个源文件包含头文件(可能有人将原始源代码文件拆分为两个文件),链接器将引发“多重定义”错误。这可能非常令人困惑,因为程序以前可以编译和链接,并且似乎没有任何变化。
总之,永远不要通过在头文件中放置定义来为变量分配空间。只需在头文件中放置变量的声明即可。

不将其包含在头文件中的原因是它是嵌入式系统,这样做会占用更多的磁盘空间。 - Honinbo Shusaku
@Abdul - 我希望现在更清楚了。如果它是嵌入式系统,那么很可能没有磁盘。 - gbulmer
我想我把磁盘内存和闪存混淆了。当我说磁盘空间时,我指的是非易失性存储空间。 - Honinbo Shusaku
1
@Abdul - 对于大多数微控制器(例如ATmega,Arm Cortex-M),可执行文件通常存储在片上闪存或外部闪存芯片中。PC的初始引导过程存储在主板上的Quad SPI Flash(https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus)中,当电源启动或重置时运行该过程,然后开始从磁盘加载操作系统。 - gbulmer
1
@Abdul - 最小化程序大小是确保数据只有一个实例。在头文件中定义数据可能会导致程序链接失败,或者浪费空间。如果链接器发现具有相同名称的数据有多个实例,并且没有足够的信息来丢弃所有但一个,则链接器将失败。或者创建多个数据实例。这是由于在几个源代码(.c)文件中包含头文件并在头文件中将数据定义为“静态”的原因。链接器将它们构建到可执行程序中,浪费空间(在磁盘和内存中)。 - gbulmer
显示剩余2条评论

1
我遇到了类似的问题。在我的情况下,我需要一个常量数组来作为其他静态数组的大小。当我尝试使用时,出现了问题。
const int my_const_array[size] = {1, 2, 3, ... };

然后声明:
int my_static_array[my_const_array[0]];

我从编译器中得到了一个错误:
array bound is not an integer constant

所以,最终我做了以下操作(也许有更优雅的方法来实现):
#define element(n,d) ==(n) ? d :
#define my_const_array(i) (i) element(0,1) (i) element(1,2) (i) element(2,5) 0

-1
#define ARRAY_SIZE 5
#define ARRAY (int[ARRAY_SIZE]){1, 2, 3, 4, 5}

但是看起来你需要安装gcc v4.0或更高版本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接