【问题标题】:Macro to test whether an integer type is signed or unsigned测试整数类型是有符号还是无符号的宏
【发布时间】:2010-09-09 01:19:08
【问题描述】:

您将如何(在 C/C++ 中)编写一个宏来测试整数类型(作为参数给出)是有符号还是无符号?

#define is_this_type_signed (my_type) ...

【问题讨论】:

  • C 和 C++ 是两种不同但相关的语言。你要记住这一点——宏在 C 中是一个很好的解决方案,但它们很危险,而且在 C++ 中大多不需要。宏完全缩短了 C++ 中的类型检查,只是为了初学者。
  • 有些事情你不能没有宏。无论如何,如果你想在 C++ 模板中做类似的事情,一些 C/C++ 代码是必要的。
  • 你能解释一下没有宏不能完成哪些“某些事情”吗?

标签: c++ c


【解决方案1】:

在 C++ 中,使用 std::numeric_limits<type>::is_signed

#include <limits>
std::numeric_limits<int>::is_signed  - returns true
std::numeric_limits<unsigned int>::is_signed  - returns false

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

【讨论】:

  • 技术上不是所要求的“宏”,但肯定是内置类型的最标准方法。
  • 同意,但在 C++ IMO 中应尽可能避免使用宏。
  • 对于现代 C++(C++11 及更高版本),这应该是公认的答案。根据需要如何使用,constexprSFINAE(或 C++20 中的概念)可用于在编译时做出决策等。
【解决方案2】:

如果你想要的是一个简单的宏,这应该可以解决问题:

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

【讨论】:

  • 这个答案有一个未初始化的变量;这可能并不总是有效。需要改成:#define is_type_signed(my_type) (((my_type(0))-1)
  • Patrick J:在 C++ 中,由于默认初始化,原来的工作正常。不过,你在 C 中是对的。
  • 只有临时变量0和-1时怎么会有未初始化的变量?
  • 如果有一个解决方案不会在 gcc (7.4) 错误上给出以下错误:比较无符号表达式
【解决方案3】:

对于 c++,有 boost::is_unsigned。我很好奇你为什么需要它,恕我直言,没有几个很好的理由。

【讨论】:

  • 我需要计算一个整数类型变量的最大值和最小值,给定它的类型。
  • 您可以使用 std::numeric_limits::max() 和 std::numeric_limits::min() 来获取类型的最大值和最小值。
  • 如果你想要那个,你为什么不一开始就问这个?
  • 这个宏的一个很好的用例是静态断言一个类型,以确保它在编译时是签名/未签名的。
【解决方案4】:

您的要求并不是最好的,但如果您想组合一个定义,一个选项可能是:

#define is_numeric_type_signed(typ) ( (((typ)0 - (typ)1)<(typ)0) && (((typ)0 - (typ)1) < (typ)1) )

但是,这并不被认为是不错或以任何方式便携。

【讨论】:

    【解决方案5】:

    我今天早些时候实际上只是想知道同样的事情。以下似乎有效:

    #define is_signed(t)    ( ((t)-1) < 0 )
    

    我测试过:

    #include <stdio.h>
    
    #define is_signed(t)    ( ((t)-1) < 0 )
    #define psigned(t) printf( #t " is %s\n", is_signed(t) ? "signed" : "unsigned" );
    
    int
    main(void)
    {
        psigned( int );
        psigned( unsigned int );
    }
    

    哪个打印:

    int is signed
    unsigned int is unsigned
    

    【讨论】:

      【解决方案6】:

      您可以使用模板函数更好地完成此任务,减少宏的讨厌业务。

          template <typename T>
              bool IsSignedType()
              {
                 // A lot of assumptions on T here
                 T instanceAsOne = 1;
      
                 if (-instanceAsOne > 0)
                 {
                     return true;
                 }
                 else
                 {
                     return false;
                 }
      }
      

      请原谅格式...

      我会试试这个,看看它是否有效......

      【讨论】:

        【解决方案7】:

        在 C++ 中你可以这样做:

        
        bool is_signed = std::numeric_limits<typeof(some_integer_variable)>::is_signed;
        

        numeric_limits 在 标头中定义。

        【讨论】:

        • C++ 中没有 typeof() 这样的东西。但是在 C++11 中有 decltype(variable),它可以做到这一点。
        【解决方案8】:

        在 C 语言中,您不能编写一个宏,该宏适用于尚未知的基本整数类型的 typedef。

        在 C++ 中,只要您的类型是基本整数类型或基本整数类型的 typedef,您就可以。下面是你在 C++ 中要做的事情:

        template <typename T>
        struct is_signed_integer
        {
            static const bool value = false;
        };
        
        template <>
        struct is_signed_integer<int>
        {
            static const bool value = true;
        };
        
        template <>
        struct is_signed_integer<short>
        {
            static const bool value = true;
        };
        
        template <>
        struct is_signed_integer<signed char>
        {
            static const bool value = true;
        };
        
        template <>
        struct is_signed_integer<long>
        {
            static const bool value = true;
        };
        
        // assuming your C++ compiler supports 'long long'...
        template <>
        struct is_signed_integer<long long>
        {
            static const bool value = true;
        };
        
        #define is_this_type_signed(my_type) is_signed_integer<my_type>::value
        

        【讨论】:

          【解决方案9】:

          如果你想要一个宏,那么这应该可以解决问题:

          #define IS_SIGNED( T ) (((T)-1)<0)
          

          基本上,将 -1 转换为您的类型,看看它是否仍然是 -1。在 C++ 中,您不需要宏。只需#include &lt;limits&gt; 和:

          bool my_type_is_signed = std::numeric_limits<my_type>::is_signed;
          

          【讨论】:

            【解决方案10】:

            尽管typeof 目前不是合法的C++,你可以使用模板推导代替。请参阅下面的示例代码:

            #include <iostream>
            #include <limits>
            
            template <typename T>
            bool is_signed(const T& t)
            {
              return std::numeric_limits<T>::is_signed;
            }
            
            int main()
            {
              std::cout << 
                is_signed(1) << " " << 
                is_signed((unsigned char) 0) << " " << 
                is_signed((signed char) 0) << std::endl;
            }
            

            此代码将打印

              1 0 1
            

            【讨论】:

              【解决方案11】:

              更“现代”的方法是使用type_traits

              #include <type_traits>
              #include <iostream>
              int main()
              {
                  std::cout << ( std::is_signed<int>::value ? "Signed" : "Unsigned") <<std::endl;
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-05-29
                • 1970-01-01
                • 1970-01-01
                • 2010-12-06
                • 2015-04-22
                • 1970-01-01
                • 1970-01-01
                • 2018-06-29
                相关资源
                最近更新 更多