c++ - 在 C++ 中显示所有基本类型的数据大小的程序

标签 c++ c++11 templates types compiler-errors

当我处理特定数据类型时,我通常需要知道它在程序中占用的大小。最近我想到了通用解决方案,可以处理 C++ 语言中所有数据类型的这个问题,包括类型别名和用户定义的数据类型。

当我开始实现时,我意识到编写适用于所有平台的可移植程序并不容易,因为 C++ 中的数据类型实际上是编译器、体系结构和操作特定实体。

它主要是工作,但有一些我无法处理的边缘情况和一些我不确定的点。

程序简介:

程序使用Template Specialization来区分 基本数据类型。操作是编译时和决策机制 通过模板特化工作。问题在于,如果将两种类型推导为同一类型(包括类型别名),就会出现编译器错误。

一个简短的例子是:

“short”或“short int”或“signed short”可能都等同于编译器所感知的“short int”(当然这可能是特定于编译器的特性)。如果“short”和“short int”都提供给程序,模板专门化机制会提示其中一个已经被定义。

那么问题是:

例如,我如何确定类型“short”、“short int”或“signed short”是否会被推导为相同类型?有没有办法在编译时检查它?

类型别名的情况也是一样的,因为模板特化是通过它们的原始类型发生的。同样,如果同时提供了“short int”和“std::size_t”,并且“std::size_t”恰好被系统定义为“short int”,则程序无法编译,因为编译器会提示存在一个专门的模板。

我使用了以下 link以确保哪些类型彼此等效,但我怀疑并非所有编译器都遵循这些规则的实现。

我得到的输出。

bool                    : 1 bytes | 8 bits
char                    : 1 bytes | 8 bits
signed char             : 1 bytes | 8 bits
unsigned char           : 1 bytes | 8 bits
wchar_t                 : 4 bytes | 32 bits
char16_t                : 2 bytes | 16 bits
char32_t                : 4 bytes | 32 bits
short int               : 2 bytes | 16 bits
unsigned short int      : 2 bytes | 16 bits
int                     : 4 bytes | 32 bits
unsigned int            : 4 bytes | 32 bits
long int                : 8 bytes | 64 bits
unsigned long int       : 8 bytes | 64 bits
long long int           : 8 bytes | 64 bits
unsigned long long int  : 8 bytes | 64 bits
float                   : 4 bytes | 32 bits
double                  : 8 bytes | 64 bits
long double             : 16 bytes | 128 bits
nullptr_t               : 8 bytes | 64 bits
Example                 : 168 bytes | 1344 bits
NULL macro is of integral type.

这在概念上是我需要的:

bool                    : 1 bytes | 8 bits
char                    : 1 bytes | 8 bits
signed char             : 1 bytes | 8 bits
unsigned char           : 1 bytes | 8 bits
wchar_t                 : 4 bytes | 32 bits
char16_t                : 2 bytes | 16 bits
char32_t                : 4 bytes | 32 bits
short int               : 2 bytes | 16 bits
// -----------WHAT I NEED CONCEPTUALLY----------------
short                   : short is same as short int             //This would be a compile-time error normally.
signed short int        : signed short int is same as short int  //This would also be a compiler time error.
std::size_t             : std::size_t is of short int type.      //Since "short int" is already defined, this is compile-time error as well.
//-----------------------------------------------------
unsigned short int      : 2 bytes | 16 bits
int                     : 4 bytes | 32 bits
unsigned int            : 4 bytes | 32 bits
long int                : 8 bytes | 64 bits
unsigned long int       : 8 bytes | 64 bits
long long int           : 8 bytes | 64 bits
unsigned long long int  : 8 bytes | 64 bits
float                   : 4 bytes | 32 bits
double                  : 8 bytes | 64 bits
long double             : 16 bytes | 128 bits
nullptr_t               : 8 bytes | 64 bits
Example                 : 168 bytes | 1344 bits
NULL macro is of integral type.

这是代码。

#ifndef TYPE_INFO_CPP
#define TYPE_INFO_CPP

#include <iostream>
#include <iomanip>
#include <type_traits>

/*
    Just call:
        SYS_CHECK();
    In your main function
*/


//Types given into the template function as template parameters via macro
#define TYPES   bool,                       \
                char,                       \
                signed char,                \
                unsigned char,              \
                wchar_t,                    \
                char16_t,                   \
                char32_t,                   \
                short int,                  \
                unsigned short int,         \
                int,                        \
                unsigned int,               \
                long int,                   \
                unsigned long int,          \
                long long int,              \
                unsigned long long int,     \
                float,                      \
                double,                     \
                long double,                \
                std::nullptr_t,             \
                Example
//              std::size_t,                \
//              std::string::size_type

//Dummy Struct Declaration to enable Template Specialization
template <typename T>
struct TypeTraits;

//Template Specialization via macro
//Template Specialization is used to distinguish different types
#define REGISTER_TYPE(X)                                \
    template <>                                         \
    struct TypeTraits <X> {                             \
        static const char * name;                       \
    };                                                  \
    const char * TypeTraits<X>::name = #X;

//To get rid of std:: prefix during console output
#define INTRODUCE_NULLPTR_T()   \
    using std::nullptr_t;

//Example User-Defined Type Body
struct Example {
    char arr1[100];
    int a;
    double b;
    char arr2[50];
};

//These macros are short-hand for declaring specialized templates of the dummy template declared above
REGISTER_TYPE(bool)
REGISTER_TYPE(char)
REGISTER_TYPE(signed char)
REGISTER_TYPE(unsigned char)
REGISTER_TYPE(wchar_t)
REGISTER_TYPE(char16_t)
REGISTER_TYPE(char32_t)
REGISTER_TYPE(short int)
REGISTER_TYPE(unsigned short int)
REGISTER_TYPE(int)
REGISTER_TYPE(unsigned int)
REGISTER_TYPE(long int)
REGISTER_TYPE(unsigned long int)
REGISTER_TYPE(long long int)
REGISTER_TYPE(unsigned long long int)
REGISTER_TYPE(float)
REGISTER_TYPE(double)
REGISTER_TYPE(long double)

//Example User-Defined Type
REGISTER_TYPE(Example)

INTRODUCE_NULLPTR_T()
REGISTER_TYPE(nullptr_t)

template <bool T = std::is_integral<decltype(NULL)>::value, 
          bool U = std::is_pointer<decltype(NULL)>::value,
          bool Y = std::is_scalar<decltype(NULL)>::value>
void is_NULL_integral() {
    std::cout << "NULL macro is of ";
    if (T) {
        std::cout << "integral";
    }
    else if (U) {
        std::cout << "pointer";
    }
    else if(Y) {
        std::cout << "nulltpr_t";
    }
    else {
        std::cout << "neither pointer nor integral or scalar";
    }
    std::cout << " type." << std::endl;
}

template <typename T, short int byte = 8>
void convert_byte_to_bit() {
    std::cout << " | ";
    std::cout << byte * sizeof(T) << " bits" << std::endl;
}

template <typename T>
void _display_helper() {
    std::cout << std::left << std::setw(23) << TypeTraits<T>::name << " : " 
        << sizeof(T) << " bytes" << std::left;
    convert_byte_to_bit<T>();
}

template <typename T>
void display_default_size() {
    _display_helper<T>();
}

template <typename T, typename U, typename ... Args>
void display_default_size() {
    _display_helper<T>();
    display_default_size<U, Args...>();
}

void SYS_CHECK() {
    display_default_size<TYPES>();
    std::cout << std::endl;
    is_NULL_integral();
}
#endif

最佳答案

How can I make sure, for example, whether types "short", "short int" or "signed short" will be deduced to the same type or not? Is there a way to check that at compile-time?

您已将您的问题标记为 C++11,所以...这是针对类型特征的工作; std::is_same

它在编译时工作。

举例

#include <type_traits>
#include <iostream>

int main()
 {
   constexpr bool b1 { std::is_same<short, short int>::value };
   constexpr bool b2 { std::is_same<short, signed short int>::value };
   constexpr bool b3 { std::is_same<short, unsigned short int>::value };

   std::cout << b1 << std::endl;  // print 1
   std::cout << b2 << std::endl;  // print 1
   std::cout << b3 << std::endl;  // print 0
 }

En passant: shortshort intsigned short int 的别名

--- 编辑 ---

OP 询问

Is there any mention in C++11 standard which states "short" and "short int" are indeed are alias for "signed short int"? Is there any resource I can use for looking up other fundamentals types as well?

我不知道标准在哪里提到它,但它是从旧 C 开始的一个基本方面;你已经链接了一个很棒的(恕我直言)资源;在您链接的页面(this page)中,您可以阅读

  • “如果使用下面列出的任何修饰符,则可以省略关键字 int”,
  • 签名“如果省略则为默认值”
  • 并且“对于所有类型说明符,任何顺序都是允许的”。

因此(通过示例)signed short intshort signed intshort int signedsigned int shortint signed shortint short signedsigned shortshort signedshort code> 是同一类型的别名。

关于c++ - 在 C++ 中显示所有基本类型的数据大小的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41090782/

相关文章:

c++ - 仅在运行时给出签名时的函数指针调用

templates - C++11 MSVS vs GCC 静态成员初始化中模板参数名称的可见性

c++ - fstream 的 getline() 工作了一点......然后中断

c++ - 如何修复我的 "self-deleting".exe 以防止提前删除自身?

c++ - 类模板错误

c++ - 为什么我的模板特化不起作用?

来自模板参数的 C++ 通用模板方法名称

c++ - typedef Foo<> Foo 编译但它有效吗?

C++ Winsock2客户端未通过远程IP连接到服务器

c++ - 我在理解一段代码中使用的语法时遇到麻烦