c - 常量数组的声明

标签 c arrays constants

我有可能是声明的问题:

我声明了一个 const int 数组:

const int my_array[] = {
    // data...
}

然后我需要声明另一个形式的字节数组:

00 aa 01 bb 02 cc

其中 aabbcc 是 const int 内存中的 24 位地址(我精确地为一个非常特殊的平台编写代码,这解释了这一点),所以我写道:

const char my_other_array[] = {
    00, (my_array >> 16) & 0xFF, 01, (my_array >> 8) & 0xFF, 02, my_array & 0xFF
}

但是我得到这个错误:

error: invalid operands to binary >>
error: initializer element is not constant

我考虑过转换 my_array :

const char my_other_array[] = {
    00, (((const u32) my_array) >> 16) & 0xFF, 01, (((const u32) my_array) >> 8) & 0xFF, 02, ((const u32) my_array) & 0xFF
}

但随后我收到警告 + 错误:

warning: initializer element is not computable at load time
error: initializer element is not computable at load time

我做错了什么?

这是实际的代码,对于那些提问的人(我删掉了不相关的部分):

#include <genesis.h>
#include "snake.h"

const u32 snake_patterns[] = {
    0x00024666,
    // ... some 100ths of lines
};

const u16 temp[] = {
    1, 0x9370, 0x9400, ((const u32) snake_patterns) & 0xFF, (((const u32) snake_patterns) >> 8) & 0xFF, (((const u32) snake_patterns) >> 16) & 0xFF
};

您会注意到事情有点复杂,但我认为前面的基本示例(用适当的括号固定)以更清晰的方式说明了问题。有些人可能会认出 Genesis VDP 的 DMA 调用列表。

最佳答案

用于初始化数组的元素必须是常量表达式。这些在 the C99 standard 的第 6.6 节或 C11 中的相同位置定义。见第 7 段:

More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:

  • an arithmetic constant expression,
  • a null pointer constant,
  • an address constant, or
  • an address constant for an object type plus or minus an integer constant expression.

现在 my_array 是一个地址常量,但您可以对它做的只是加上或减去一个整数常量。通过移位或屏蔽,您正在创建不再是常量表达式的东西,因此在初始化程序中是不允许的。

我猜这个限制的基本原理是 C 旨在可用于可重定位代码,其中程序在内存中的位置可能直到它被加载以准备执行时才知道。在这样的系统上,加载程序必须根据它在加载时读取的二进制文件中的表来填充对程序中地址的引用(例如,“在程序中的相对地址 0x12345678 中,填写绝对地址对象 my_array 一旦已知”)。该表通常具有相当严格的格式,并且可能有一种表示常量偏移量的方法(“填写对象 my_array 的绝对地址,加上 42”)但通常不支持任意算术。

可能对你来说最简单的解决方案是让 my_other_array 不是 const 并在运行时填充它,方法是编写一个函数来提取地址的必要位my_array 并将它们插入到 my_other_array 中,并在需要使用 my_other_array 之前调用此函数。

如果出于某种原因很重要 my_other_array 在加载程序时已经填写,并且您的目标平台是您知道程序在内存中的位置,那么您可能是能够使用您的汇编器或链接器的设施来实现您想要的。但这当然是系统特定的。

(编辑:你在另一条评论中提到这个数组需要进入 ROM。如果是这样,那么我认为我最后的建议是你唯一的希望。你可能想发布另一个关于如何/是否可以做的问题这与您正在使用的特定工具链有关。)

关于c - 常量数组的声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36182463/

相关文章:

c - 如何生成与直方图匹配的点?

c - 需要帮助解释混淆的 C++ 代码吗?

c - 带有字符串参数的 fprintf

arrays - Excel VBA Array() 函数导致类型不匹配?

PHP array_reduce 初始参数为数组

c++ - 为什么 'const' 在这两种情况下表现不同?

c++ - 我应该声明所有不抛出 noexcept 的成员/函数吗?

c - 如何访问asm中的数组?

Java-判断数组的位置变化

c++ - 比较迭代器和 const_iterators