相关疑难解决方法(0)

为什么gcc不允许将const int作为case表达式?

我正在考虑这个问题,并开始考虑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)满意.

c compiler-construction const objective-c

28
推荐指数
1
解决办法
8042
查看次数

有没有办法在C中使用带常量索引的常量数组作为开关案例标签?

我有一些常量值和数组定义他们的标签和他们的哈希码.例如,

#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)
  1. 我无法理解,为什么会这样?我的数组和它的索引都是常量,那么它不等同于常量文字吗?
  2. 有没有其他方法可以按要求的方式提供常量? …

c arrays switch-statement

9
推荐指数
2
解决办法
1201
查看次数

C++ 宏将字符串转换为字符列表

是否可以有一个宏:

CHAR_LIST(鸡肉)

扩展到:

'鸡'

[我想要它的原因:因为即使是中等大小的字符串,宏也比手动扩展方便得多。我需要扩展的原因是将字符串传递给可变参数模板]

c c++ macros

7
推荐指数
1
解决办法
3624
查看次数

C预处理器将"int x"拆分为int&x

我需要能够得到以下内容:

#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)通常,标记用逗号分隔,至我知道.有没有办法使用另一个角色?

c c-preprocessor variadic-macros

4
推荐指数
2
解决办法
2179
查看次数

什么促销类型用于switch-case表达式比较?

使用不同的编译器编译时,以下程序打印"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标签标记,如下所示:

case constant-expression :  
Run Code Online (Sandbox Code Playgroud)

其中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++标准中的相关条款是什么?

c c++ language-lawyer

4
推荐指数
1
解决办法
1386
查看次数

预处理器宏将十六进制字符串转换为字节数组

我已经在我的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在它们之间添加" "?

c macros gcc preprocessor c-preprocessor

3
推荐指数
1
解决办法
1562
查看次数