我正在考虑这个问题,并开始考虑const ints与#defines,并意识到我实际上并不理解为什么编译器无法解决这个问题.有人可以解释为什么以下代码
const int FOO = 10;
int main(int argc, char** argv)
{
switch(argc)
{
case FOO: { printf("foo\n"); }
default: { printf("default\n"); }
}
}
Run Code Online (Sandbox Code Playgroud)
结果是
error: case label does not reduce to an integer constant
Run Code Online (Sandbox Code Playgroud)
我阅读了ISO-C99规范,该规范在6.8.4.2.3中说明
每个case标签的表达式应为整数常量表达式,并且同一switch语句中的两个case常量表达式在转换后不应具有相同的值.
我理解为什么case表达式必须是常量,但不是为什么只有一个文字让编译器(gcc 4.2.1)满意.
我有一些常量值和数组定义他们的标签和他们的哈希码.例如,
#define LABEL_A 0 //or const int LABEL_A = 0;
#define LABEL_B 1
#define LABEL_C 2
#define LABEL_D 3
const char *VALUE[] = {"LABEL_A", "LABEL_B", "LABEL_C", "LABEL_D"};
const int VALUE_HASH[] = {67490, 67491, 67493, 67459);
Run Code Online (Sandbox Code Playgroud)
在运行时,这些标签可以按任何顺序排列,需要进行相应的解析.我正在使用开关盒来达到这个目的.此代码在编译时生成错误"需要常量表达式.
function(const char* LabelAtRuntime){
int i = getHashCode(LabelAtRuntime);
switch(i){
case VALUE_HASH[LABEL_A]: //line giving compile time error
break;
default:
break;
}
Run Code Online (Sandbox Code Playgroud)
但是,当我提供实际常量时,它是有效的.这段代码效果很好.
function(const char* LabelAtRuntime){
int i = getHashCode(LabelAtRuntime);
switch(i){
case 67490: //line not giving compile time error
break;
default:
break;
}
Run Code Online (Sandbox Code Playgroud)
是否可以有一个宏:
CHAR_LIST(鸡肉)
扩展到:
'鸡'
[我想要它的原因:因为即使是中等大小的字符串,宏也比手动扩展方便得多。我需要扩展的原因是将字符串传递给可变参数模板]
我需要能够得到以下内容:
#define MY_MACRO(PARAM1,PARAM2) \
MY_OTHER_MACRO(TYPENAME_OF(PARAM1),PARAMNAME_OF(PARAM1));\
MY_OTHER_MACRO(TYPENAME_OF(PARAM2),PARAMNAME_OF(PARAM2));\
Run Code Online (Sandbox Code Playgroud)
引起
MY_MACRO(int x,char *z)
Run Code Online (Sandbox Code Playgroud)
编译为
MY_OTHER_MACRO(int,x);
MY_OTHER_MACRO(char*,z);
Run Code Online (Sandbox Code Playgroud)
如果它编译为:它不会是世界末日:
MY_OTHER_MACRO(int,x);
MY_OTHER_MACRO(char,*z);
Run Code Online (Sandbox Code Playgroud)
或者甚至这也可以:(我可以编码MY_OTHER_MACRO来处理任何一个结果)
MY_OTHER_MACRO(int,x);
MY_OTHER_MACRO(char,z);
Run Code Online (Sandbox Code Playgroud)
或者,如果有一些方法来计算由空格分隔的标记(并假设"*"是单独的标记,我也可以使用它 - 例如2对3)通常,标记用逗号分隔,至我知道.有没有办法使用另一个角色?
使用不同的编译器编译时,以下程序打印"unknown".为什么会这样?
#include "stdio.h"
const char OPTION = (char)(unsigned char)253;
int main(int argc, char* argv[])
{
unsigned char c = 253;
switch (c)
{
case OPTION:
printf("option\n");
break;
default:
printf("unknown\n");
break;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在查看C++标准(N3690 2013-05-05)时,我看到了一个switch子句:
6.4.2 switch语句
2条件应为整数类型,枚举类型或类类型.如果是类类型,则将条件在上下文中隐式转换(第4节)为整数或枚举类型.执行整体促销.switch语句中的任何语句都可以用一个或多个case标签标记,如下所示:
Run Code Online (Sandbox Code Playgroud)case constant-expression :其中constant-expression应该是切换条件的提升类型的转换常量表达式(5.19).在转换为提升类型的开关条件后,同一开关中的两个外壳常数不应具有相同的值.
引用的转换条款:
4标准转换
2 [注意:具有给定类型的表达式将在多个上下文中隐式转换为其他类型:
[...]
- 在switch语句的表达式中使用时.目的地类型是积分(6.4).
[...] - 结束
说明]
变量c的类型为unsigned char,它是一个整数类型.所以不需要晋升!?
如果推广类型是unsigned char我希望比较c == (unsigned char)OPTION,如果产生真实.如果提升类型,int我会期望比较(int)c == (int)OPTION)明显产生错误.
我的问题是:上述计划中使用的推广类型是什么?C和C++标准中的相关条款是什么?
我已经在我的IDE中定义了一个AES-128密钥作为构建符号,因此它像这样调用GCC:
arm-none-eabi-gcc -D"AES_KEY=3B7116E69E222295163FF1CAA1681FAC" ...
Run Code Online (Sandbox Code Playgroud)
(相当于#define AES_KEY 3B7116E69E222295163FF1CAA1681FAC)
优点是相同的符号也可以作为参数自动传递给构建后的CLI脚本,该脚本使用此密钥加密编译的代码(例如,用于安全的固件更新)...
但是如何在代码中将此键存储为字节数组?我想定义一个执行转换的预处理器宏:
uint8_t aes_key[] = { SPLIT_MACRO(AES_KEY) };
Run Code Online (Sandbox Code Playgroud)
至
uint8_t aes_key[] = {0x3B, 0x71, 0x16, 0xE6, 0x9E, 0x22, 0x22, 0x95, ...};
Run Code Online (Sandbox Code Playgroud)
换句话说,GCC预处理器是否可以在2-char块中拆分密钥字符串并, 0x在它们之间添加" "?