【问题标题】:How to check if plain chars are signed or unsigned?如何检查普通字符是否已签名或未签名?
【发布时间】:2013-08-15 18:56:32
【问题描述】:

显然,普通char 有可能默认为已签名或未签名。 Stroustrup 写道:

普通字符被认为是有符号还是无符号是实现定义的。这将打开 一些令人讨厌的惊喜和实现依赖的可能性。

如何检查我的字符是已签名还是未签名?稍后我可能想将它们转换为int,并且我不希望它们为负数。我应该始终明确使用unsigned char 吗?

【问题讨论】:

  • @MitchWheat:是的。我遇到的例子:Cray T90、Cray SV1、Cray T3E、SGI MIPS IRIX、IBM PowerPC AIX。任何使用 EBCDIC 的系统都必须将char 设为无符号。
  • @KeithThompson:您应该将您的列表添加为this question的答案
  • 您阅读了编译器的文档。
  • @PeteBecker:如果您想在编译时或运行时检查,这不一定有帮助(尽管通常最好编写不关心 char 是签名还是未签名的代码,或使用signed charunsigned char,如果你关心的话)。
  • @KeithThompson - 是的,很明显,这就是我发表评论而不是答案的原因。

标签: c++ syntax char


【解决方案1】:

来自标头<limits>

std::numeric_limits<char>::is_signed

http://en.cppreference.com/w/cpp/types/numeric_limits/is_signed

【讨论】:

    【解决方案2】:

    一些替代方案:

    const bool char_is_signed = (char)-1 < 0;
    
    #include <climits>
    const bool char_is_signed = CHAR_MIN < 0;
    

    是的,有些系统确实将普通的char 设为无符号类型。我遇到的例子:Cray T90、Cray SV1、Cray T3E、SGI MIPS IRIX、IBM PowerPC AIX。并且任何使用 EBCDIC 的系统几乎都必须将char 设为无符号,以便所有基本字符都具有非负值。 (并且一些编译器可以选择控制char 的签名,例如gcc 的-fsigned-char-funsigned-char。)

    但是std::numeric_limits&lt;char&gt;::is_signed,正如Benjamin Lindley's answer所建议的那样,可能更清楚地表达了意图。

    (另一方面,我建议的方法也可以应用于C。)

    【讨论】:

      【解决方案3】:

      你可以使用预处理命令:

       #define is_type_signed(my_type) (((my_type)-1) < 0)
      

      【讨论】:

      • 为什么要将它设为宏而不是 const bool
      • @KeithThompson 这是更“通用”的构造,不仅适用于 char 类型。
      • numeric_limits&lt;&gt;::is_signed 已经涵盖了您试图传达的任何“普遍性”感。
      【解决方案4】:

      使用unsigned char“always”可能会给你一些有趣的惊喜,因为大多数 C 风格的函数,如printffopen,将使用char,而不是unsigned char

      编辑:使用 C 风格函数的“有趣”示例:

      const unsigned char *cmd = "grep -r blah *.txt";
      FILE *pf = popen(cmd, "r"); 
      

      会报错(事实上,*cmd = 行有一个错误,popen 行有一个错误)。使用 const char *cmd = ... 可以正常工作。我选择了popen,因为它是一个用一些标准 C++ 功能替换的函数 - 显然,printffopen 可以很容易地替换为一些 iostreamfstream 类型的功能,通常有采用unsigned charchar 的替代方案。

      但是,如果您对超过 127 的字符使用 &gt;&lt;,则需要使用 unsigned char(或其他一些解决方案,例如转换为 int 并屏蔽较低的 8位)。尽量避免直接比较可能会更好(特别是在涉及非 ASCII 字符时——它们无论如何都是混乱的,因为根据语言环境、字符编码等通常有几种变体)。然而,比较平等应该有效。

      【讨论】:

      • @chux:还没有完成编辑...(自我说明:先写编辑,然后评论说“查看编辑”)
      【解决方案5】:

      是的,如果您想使用char 类型并且您总是希望它是无符号的,请使用unsigned char。请注意,与其他基本整数类型不同,unsigned char 是与char 不同的类型——即使在char 是无符号的系统上也是如此。另外,从char 转换为int ought to be lossless 所以如果你的结果不正确,你的源char 值也可能不正确。

      测试char 是否无符号的最简洁方法取决于您是否需要将其作为预处理器测试以及您所针对的 C++ 版本。

      要使用预处理器测试有条件地编译代码,CHAR_MIN 的值应该有效:

      #include <climits>
      
      #if (CHAR_MIN==0)
      // code that relies on char being unsigned
      #endif
      

      在 C++17 中,我会使用 std::is_signed_vstd::is_unsigned_v

      #include <type_traits>
      
      static_assert(std::is_unsigned_v<char>);
      // code that relies on char being unsigned
      

      如果您针对 C++11 或 C++14 编写代码,则需要稍微冗长的 std::is_signedstd::is_unsigned

      #include <type_traits>
      
      static_assert(std::is_unsigned<char>::value, "char is signed");
      // code that relies on char being unsigned
      

      对于所有 C++ 版本,@benjamin-lindley 的解决方案是一个不错的选择。

      【讨论】:

        猜你喜欢
        • 2017-12-24
        • 2011-10-28
        • 1970-01-01
        • 2016-11-26
        • 1970-01-01
        • 1970-01-01
        • 2010-10-14
        • 2018-04-02
        • 1970-01-01
        相关资源
        最近更新 更多