我有一个结构数组,一些结构成员是常量 我想制作一个数组的深层副本。 该副本也将具有与常量相同的结构成员。 如何在不违反 const 指令的情况下将值初始化为新数组。
以下是我的代码的摘录。实际的程序很长,但我想我已经包含了所有相关的代码。在此示例中, keys 被声明为全局变量,我想从中创建新实例。我把它当成具有预设值的模板。
当我尝试使用gcc在Debian中编译它时,我收到以下错误:
main.c:216:9: error: assignment of read-only location ‘*(new_keys + (unsigned int)((unsigned int)index * 540u))’make: *** [main.o] Error 1
makefile使用以下限定符:
CFLAGS=-c -g -std=gnu99 -D_XOPEN_SOURCE=700
有趣。即使为C语言方言GNU99设置了Xcode,我也可以在Xcode中编译相同的代码而不会出现错误或警告[-std = gnu99]
我可以简单地通过删除const关键字来使我的代码工作。但这些价值确实应该是常数。一旦这些数组初始化,它们将永远不会改变。我想了解如何正确地做到这一点,并且我想知道为什么这在Xcode中工作而不是gcc。
标头文件
typedef struct {
char * name;
char * alias;
int number;
} pair_int_t;
typedef struct {
const char * const name;
const kind_t kind; // kind is enum type
const pair_int_t * const enum_array;
bool received;
const char * const alias;
} key_descriptor_t;
typedef key_descriptor_t keys_descriptor_t[_END_OF_KEYS+1];
main()之前的.c程序体。
const pair_int_t command_list[] = {
{.name = "numeric data response", .alias = "num", .number = RES_NUMERIC_DATA},
{.name = "read attribute", .alias = "readat", .number = CMD_READ_ATTR},
//..
}
// declare a global variable *keys* with constants assigned to it
key_descriptor_t keys[] = {
[_COMMAND] = {.name = "command", .kind = ENUMERATED, .alias = "com", .enum_array = command_list},
[_RESPONSE] = {.name = "response", .kind = ENUMERATED, .alias = "res", .enum_array = command_list},
[_UNIT] = {.name = "unit number", .kind = NUMBER, .alias = "uni", .enum_array = NULL},
//..
}
int initialize_new_keys(keys_descriptor_t new_keys) {
int index;
for (index = _FIRST_KEY; index <= _END_OF_KEYS; index++){
new_keys[index] = keys[index]; // line 216, keys is a global variable
}
return index;
}
主程序
int main(int argc, const char * argv[]){
keys_descriptor_t 2nd_set_of_keys;
initialize_new_keys(2nd_set_of_keys);
}
答案 0 :(得分:5)
您只能在定义变量时初始化const
个变量。创建一个包含const
成员的数组,将其发送到一个函数,然后尝试分配给这些成员,表明您首先并不真正意味着const
。 &#34; const
除了第一个作业&#34;之外没有C语法。
一个合理的选择是制作一个opaque类型,将定义封装在一个单独的翻译单元中,然后纯粹通过一个函数接口访问所有成员。这样,即使事情可能不是const
,它们仍然无法改变(除非通过故意的颠覆,这至少不比不首先调用事物const
更好)因为没有使用它们的代码可以访问struct
的定义,或者因此可以访问成员。
编辑:在回答评论中的问题时,&#34;有没有办法创建一个复杂的常量变量并将其初始化为另一个相同类型的现有常量变量的值?&#34;,确定是 - 只是正常初始化它:
struct mystruct {
const int a;
const int b;
};
static const struct mystruct m = {1, 2};
int main(void) {
struct mystruct n = m;
return 0;
}
显然,struct
越复杂,这种情况就越复杂。
答案 1 :(得分:0)
“2nd_set_of_keys”是一个结构,它应该是一个静态数组(或者可以是一个指针并动态保留内存),“new_keys”参数也会出现同样的问题。 虽然有点奇怪,但您可以使用memcpy()将数据复制到const变量(覆盖const验证)。