【问题标题】:Define Array in C在 C 中定义数组
【发布时间】:2012-04-08 11:15:00
【问题描述】:

我有几个 450 元素字符数组(存储位图数据以显示在 lcd 屏幕上。)我想将它们放在头文件和 #define 它们下,但我不断收到编译错误。我将如何在 C 中执行此操作?

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

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

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

还有更多...

【问题讨论】:

  • 您为什么不发布您目前拥有的代码以及您遇到的编译器错误?
  • 你不能#define 那样的东西。想想看;每次使用它时,您都会声明一个新数组。当然,这将导致多次重新定义。宏只是文本替换。自己替换文本,看看是否有意义。

标签: c arrays header-files c-preprocessor


【解决方案1】:

嗯...您当然不需要使用定义。只需将它们作为 const 静态数组添加到标题中即可。

/* 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

另外,如果您需要有关编译错误的帮助,那么您应该发布您的代码。

【讨论】:

  • 是的,但是当多次调用标头时(程序的多个部分都需要它)我会出错。
  • 然后使用include guard 并再次显示示例。我不知道“调用标题”是什么意思,但我假设你的意思是包含。所以,就像我说的......例子。你知道,我们不是通灵者。 :)
  • 谢谢。我会试试我没想到的#ifndef
【解决方案2】:

因为您在 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 somewhere 的数组变量。如果链接器没有(从其他地方)获得该定义,那么它将引发错误,因为分配的变量没有空间。

变量的定义(注意没有extern),例如。 byte numbers2[MAX_NUMBERS2]; 有效地告诉 C 编译器有一个名为 numbers2 的数组变量,它应该在此源文件的结果目标代码中分配空间,这将用于保存最终变量的值,链接程序。

numbers2 的空间不是由 C 编译器在看到声明时分配的(前面是 extern),它是在看到实际定义时分配的(没有 extern )。

因此,如果您将任何变量的实际定义放在头文件中,并将其包含在多个源代码文件(.c)中,C 编译器将多次为该变量分配空间。那么链接器就会报错(通常是同名的多个定义)。

还有一个更微妙的问题。如果在第一次开发程序时,头文件只包含一个源文件,那么程序将正确编译和链接。然后,在以后的日期,如果第二个源文件包含标头(可能有人刚刚将原始源代码文件拆分为两个文件),链接器将引发“多个定义”错误。这可能会非常令人困惑,因为用于编译和链接的程序显然没有任何改变。

总结
切勿通过将定义放在头文件中来为变量分配空间。仅将变量 declarations 放在头文件中。

【讨论】:

  • 是不把它包含在头文件中的原因,因为它是一个嵌入式系统,它会占用更多的磁盘空间?
  • @Abdul - 我希望这更清楚。如果是嵌入式系统,那么它可能没有磁盘。
  • 没有磁盘的嵌入式系统中存储的可执行二进制文件在哪里?
  • @Abdul - 对于大多数微控制器(例如 ATmega、Arm Cortex-M)或外部闪存芯片,可执行文件通常存储在片上闪存中。 PC 的初始引导加载过程存储在主板上的 Quad SPI Flash (en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus) 中,当它在上电或重置时运行时,它开始从磁盘加载操作系统。
  • @Abdul - 最小化程序大小是为了确保它们只是数据的一个实例。在标头中定义数据可能会导致程序链接时失败,或者可能会浪费空间。如果链接器找到多个具有相同名称的数据实例并且没有足够的信息来丢弃除一个之外的所有实例,则链接器将失败。或者创建多个数据实例。这是由于将标头包含在多个源代码 (.c) 文件中,这些文件在标头中将数据定义为“静态”。 ` 链接器将它们构建到可执行程序中,浪费空间(在磁盘和内存中)。
【解决方案3】:

我也遇到过类似的问题。就我而言,我需要一个常量数组才能用作其他静态数组的大小。当我尝试使用

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

【讨论】:

    猜你喜欢
    • 2014-04-10
    • 2013-12-08
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多