我写了以下代码:
unsigned char *cPtr[] =
{
"First",
"Second",
"Third"
};
typedef struct
{
int a;
char *lut; /* or char lut[20]*/
}Grp_t;
const Grp_t Grp_st[]=
{
{ 0, cPtr[0] },
{ 1, cPtr[1] },
{ 2, cPtr[2] }
};
当我尝试编译此代码时,出现以下错误:
错误:初始化元素不是常量
错误:(接近初始化'Grp_st [0] .lut [0]')
但当我将*cPtr[]
替换为cPtr[][16]
unsigned char cPtr[][16] =
{
"First",
"Second",
"Third"
};
我能够成功编译代码。
任何人都可以向我解释我在这里缺少的概念。
答案 0 :(得分:6)
这是C.的限制。
6.7.8.4初始化:
具有静态的对象的初始值设定项中的所有表达式 存储持续时间应为常量表达式或字符串文字。
和 6.6.9常量表达式:
地址常量是空指针,是指向左值的指针 指定静态存储持续时间的对象,或指向a的指针 功能指示符;它应该使用一元& amp; 运算符或整数常量强制转换为指针类型,或隐式地通过 使用数组或函数类型的表达式。该 array-subscript []和成员访问。和 - >运营商,地址& 和间接*一元运算符,以及指针强制转换可以用于 创建一个地址常量,但对象的值应该是 不能通过使用这些操作符来访问。
如果您可以更改代码以使Grp_st
不是静态存储持续时间,则编译:
#include <stdio.h>
const char *cPtr[] =
{
"First",
"Second",
"Third"
};
typedef struct
{
int a;
const char *lut;
} Grp_t;
int main(void) {
Grp_t Grp_st[]= {
{ 0, cPtr[0] },
{ 1, cPtr[1] },
{ 2, cPtr[2] }
};
return 0;
}
在第二种情况下,您设法编译代码,因为您没有访问给定索引处的数组元素,只有一个指针(如果是char cPtr[][16]
,cPtr[0]
会给出第一个地址16个字符的数组和cPtr[0]
衰减到表达式中的char *
- 因此您没有违反 6.6.9 规则。
答案 1 :(得分:1)
静态对象的初始化程序必须是常量 1 。
由于您正在尝试初始化静态对象的成员,该成员具有指向char的类型指针,因此您需要一个地址常量 2 。
cPtr[0]
不是地址常量,因为在尝试创建此地址常量 3 时会访问对象cPtr
的值。
另一方面,cStr[0]
无法访问对象cStr
的任何值。表达式cStr[0]
与&cStr[0][0]
相同,显然无法访问该值,但只能访问该值的地址。
1 (引自:ISO / IEC 9899:201x 6.7.9初始化4)
具有静态或线程存储持续时间的对象的初始值设定项中的所有表达式
应该是常量表达式或字符串文字。
2 (引自:ISO / IEC 9899:201x 6.6常数表达式9)
地址常量是空指针,指向指定静态对象的左值的指针
存储持续时间,或指向功能指示符的指针;它应该使用明确创建
一元&amp;运算符或整数常量强制转换为指针类型,或隐式使用
数组或函数类型的表达式。 array-subscript []和member-access。
和 - &gt;运营商,地址&amp;和间接*一元运算符,以及指针强制转换
用于创建地址常量,但对象的值不应该是
通过使用这些运算符访问。
3 但是对象的值不应该是 通过使用这些运算符访问。
答案 2 :(得分:0)
这主要是对@where_is_ftp的答案的补充,以添加有关facts.foreachRDD(fact -> { JavaEsSpark.saveJsonToEs(fact, esIndex
+ "/" + esType, ImmutableMap.of("es.mapping.id", "your_column_name"));});
和*cPtr[]
之间差异的详细信息。
前一种情况是指针数组。在这种情况下,地址cPtr[][16]
,cPtr[0]
,cPtr[1]
是不相关的,并且是运行时值,即指向字符串的地址。
后者是2D阵列。在这种情况下,地址cPtr[2]
,cPtr[0]
和cPtr[1]
是2D数组中的地址,具体为cPtr[2]
,并且原始字符串已被复制到2D数组中数组初始化。这就是为什么它们现在是恒定值的原因。