我声明一个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,(((const u32) my_array) >> 8) & 0xFF,((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调用列表.
解决方法
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中,如果是这样,那么我认为我的最后一个建议是你唯一的希望,你可能想发表一个关于如何/是否可以这样做的问题您正在使用的特定工具链.)