【问题标题】:convert char type(not ascii) to int将 char 类型(不是 ascii)转换为 int
【发布时间】:2017-01-22 05:17:10
【问题描述】:

我想将char类型转换为int类型而不丢失带符号的含义, 所以我在文件 int_test.c 中编写代码并且它可以工作:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define c2int(x) \
({                         \
        int t;             \
        if (x > 0x80)      \
                t = x | (1 << sizeof(int) * 8) - (1 << sizeof(char) * 8); \
        else               \
                t = x;     \
        t;                 \
 })

int main()
{
        uint8_t a = 0xFE;
        int b;

        b = c2int(a);

        printf("(signed char)a = %hhi, b = %d\n", a, b);

        exit(EXIT_SUCCESS);
}

运行结果是:

(有符号字符)a = -2, b = -2

编译日志为:

gcc -o int_test int_test.c int_test.c:在函数“main”中: int_test.c:9:15:警告:左移计数 >= 类型宽度 [-Wshift-count-overflow] t = x | (1

我的问题是: 1。有没有简单高效的转换? 2. char转int时如何判断有符号展开式? 3、如何避免上述警告?

谢谢。

【问题讨论】:

  • 如果您的char 已签名,请执行以下操作:(int)c 如果未签名,“签名含义”是什么意思? uint8_t不是 char,请说明你到底需要什么。
  • uint8_t a 中没有符号位可以丢失。 b = a; 有什么问题?

标签: c type-conversion


【解决方案1】:

您正在进行手动、显式的符号转换。不要那样做。而是:

static int c2int(unsigned char x)
{
    return (signed char)x;
}

这确实为您签名扩展,并且不会产生警告。

【讨论】:

  • 在某些平台上char是未签名的,因此为了提高可移植性,它应该是return (signed char)x;
  • @LPs implementation-defined "当一个整数类型的值被转换成另一个整数类型时... -defined 或实现定义的信号被引发。” C11 6.3.1.3
  • @LPs 幸运的是,在所有主流实现中它都可以工作。但我确信有一些旧的(如 1970 年代)平台不会。不过,值得在答案中指出它取决于实现定义的行为。
  • @Klas Lindbäck 关于现代与 1970 年代计算机的问题没有考虑 modern 平台上的 modern 编译器。众所周知,许多人利用ID 行为和 UB 以创建高度优化的代码。依赖于对编译器 ID 的因果理解可能会导致代码无法按预期运行 - 因此 2016 年更加关注避免 ID 行为(以及 UB)。
  • @chux 我同意。您需要知道自己在做什么,并愿意为您支持的每个平台检查手册。您必须权衡这种努力与编写和维护不使用任何 ID(或 UB)的代码的努力。如果有人想深入研究如何避免这种情况,我建议(问题/答案涵盖 C 和 C++,甚至 C 标准不同版本之间的差异):stackoverflow.com/questions/13150449/…
【解决方案2】:

您是否想要符号扩展?如果您想要符号扩展,您必须首先通过 已签名 char。如果不是,那么只需使用赋值或初始化的隐式转换:

unsigned char x = 0xfe;
int y = (signed char) x;
int z = x;
printf("x = %hhx, y = %08x, z = %08x\n", x, y, z);

上面的代码应该打印出来

x = fe,y = fffffffe,z = 000000fe

【讨论】:

    【解决方案3】:
    1. 有没有简单高效的转换?

      // To convert a value to char and then to int
      // As a function or macro
      #define c2int(x) ((int)(char)(x))
      int c2int(char x) { return x; }
      
      // To convert a value to signed char and then to int
      #define c2int(x) ((int)(signed char)(x))
      int c2int(signed char x) { return x; }
      
    2. 简单地将char转换为int时如何确定带符号的扩展?

      不需要特殊代码,见上文。 C 为你做这件事。

    3. 如何避免上述警告?

      确保移位小于位宽。
      避免移入符号位。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-28
      • 2013-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多