Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么是16字节有符号整数数据类型?”;_C++_C_Types_Integer - Fatal编程技术网

C++ 什么是16字节有符号整数数据类型?”;

C++ 什么是16字节有符号整数数据类型?”;,c++,c,types,integer,C++,C,Types,Integer,我制作这个程序是为了测试计算任意整数文本的数据类型。本程序的灵感来自于阅读有关StackOverflow的其他一些问题 在这些问题中,我们遇到了一个问题:程序员希望将INT_MIN写成-2^31,但2^31实际上是一个文本,-是一元否定运算符。由于INT_MAX通常是2^31-1,具有32位INT,因此文字2^31不能表示为INT,因此它会被提升为更大的数据类型。第三个问题中的第二个答案有一个图表,根据该图表确定整数文本的数据类型。编译器从顶部向下搜索列表,直到找到一个适合该文本的数据类型

我制作这个程序是为了测试计算任意整数文本的数据类型。本程序的灵感来自于阅读有关StackOverflow的其他一些问题

在这些问题中,我们遇到了一个问题:程序员希望将INT_MIN写成
-
2^31,但2^31实际上是一个文本,
-
是一元否定运算符。由于INT_MAX通常是2^31-1,具有32位INT,因此文字2^31不能表示为
INT
,因此它会被提升为更大的数据类型。第三个问题中的第二个答案有一个图表,根据该图表确定整数文本的数据类型。编译器从顶部向下搜索列表,直到找到一个适合该文本的数据类型

后缀小数常量
无整数
长整型
长整型

=========================================================================

在我的小程序中,我定义了一个宏,它将以C字符串的形式返回变量、文字或表达式的“名称”。基本上,它返回在宏内部传递的文本,与您在代码编辑器中看到的完全相同。我用它来打印文本表达式

我想确定表达式的数据类型,以及它的计算结果。我必须对我如何做到这一点有点聪明。如何确定C中变量或表达式的数据类型?我的结论是,只需要两个“位”的信息:以字节为单位的数据类型的宽度和数据类型的符号性

#include <stdio.h>   /* C standard input/output - for printf()     */
#include <stdlib.h>  /* C standard library      - for EXIT_SUCCESS */

/**
 * Returns the name of the variable or expression passed in as a string.
 */
#define NAME(x) #x

/**
 * Returns 1 if the passed in expression is a signed type.
 * -1 is cast to the type of the expression.
 * If it is signed, -1 < 0 == 1 (TRUE)
 * If it is unsigned, UMax < 0 == 0 (FALSE)
 */
#define IS_SIGNED_TYPE(x) ((typeof(x))-1 < 0)

int main(void)
{

    /* What data type is the literal -9223372036854775808? */

    printf("The literal is %s\n", NAME(-9223372036854775808));
    printf("The literal takes up %u bytes\n", sizeof(-9223372036854775808));
    if (IS_SIGNED_TYPE(-9223372036854775808))
        printf("The literal is of a signed type.\n");
    else
        printf("The literal is of an unsigned type.\n");

    return EXIT_SUCCESS;
}
我使用
sizeof()
操作符来确定数据类型的宽度(以字节为单位)。我还使用另一个宏来确定数据类型是否已签名
typeof()
是一个GNU编译器扩展,它返回变量或表达式的数据类型。但我无法读取数据类型。我将
-1
类型转换为任何数据类型。如果是有符号的数据类型,它仍然是
-1
,如果是无符号的数据类型,它将成为该数据类型的
UINT\u MAX

#include <stdio.h>   /* C standard input/output - for printf()     */
#include <stdlib.h>  /* C standard library      - for EXIT_SUCCESS */

/**
 * Returns the name of the variable or expression passed in as a string.
 */
#define NAME(x) #x

/**
 * Returns 1 if the passed in expression is a signed type.
 * -1 is cast to the type of the expression.
 * If it is signed, -1 < 0 == 1 (TRUE)
 * If it is unsigned, UMax < 0 == 0 (FALSE)
 */
#define IS_SIGNED_TYPE(x) ((typeof(x))-1 < 0)

int main(void)
{

    /* What data type is the literal -9223372036854775808? */

    printf("The literal is %s\n", NAME(-9223372036854775808));
    printf("The literal takes up %u bytes\n", sizeof(-9223372036854775808));
    if (IS_SIGNED_TYPE(-9223372036854775808))
        printf("The literal is of a signed type.\n");
    else
        printf("The literal is of an unsigned type.\n");

    return EXIT_SUCCESS;
}

我看到相当于2^63的整数文本计算为16字节有符号整数类型!据我所知,C编程语言中没有这样的数据类型。我也不知道有哪个Intel x86_64处理器有16字节寄存器来存储这样的右值。如果我错了,请纠正我。解释一下这里发生了什么?为什么没有溢出?另外,是否可以在C中定义16字节的数据类型?你会怎么做?

经过一些挖掘,这就是我发现的。我把代码转换成C++,假设C和C++在这种情况下的行为类似。我想创建一个模板函数,以便能够接受任何数据类型。我使用
\uuuu PRETTY\u FUNCTION\uuuu
这是一个GNU编译器扩展,它返回一个包含函数“原型”的C字符串,我指的是返回类型、名称和输入的形式参数。我对形式参数感兴趣。使用这种技术,我能够准确地确定传入的表达式的数据类型,而无需猜测

/**
 * This is a templated function.
 * It accepts a value "object" of any data type, which is labeled as "T".
 *
 * The __PRETTY_FUNCTION__ is a GNU compiler extension which is actually
 * a C-string that evaluates to the "pretty" name of a function,
 * means including the function's return type and the types of its
 * formal parameters.
 *
 * I'm using __PRETTY_FUNCTION__ to determine the data type of the passed
 * in expression to the function, during the runtime!
 */
template<typename T>
void foo(T value)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

foo(5);
foo(-9223372036854775808);
我看到传入的表达式的类型是
\uu int128
。显然,这是GNU编译器特定的扩展,不是C标准的一部分


在启用所有警告的情况下-Wall gcc将发出
警告:整数常量太大,以至于它是无符号的
警告。Gcc将类型
\uuuu int128
sizeof(\uuuu int128)=16

您可以使用_genericmacro检查:

#define typestring(v) _Generic((v), \
    long long: "long long", \
    unsigned long long: "unsigned long long", \
    __int128: "__int128" \
    )

int main()
{
    printf("Type is %s\n", typestring(-9223372036854775808));
    return 0;
}

或带有来自printf的警告:

int main() {
    printf("%s", -9223372036854775808);
    return 0;
}
将编译并警告:

warning: format '%s' expects argument of type 'char *', but argument 2 has type '__int128' [-Wformat=]

您的平台可能有
\uuu int128
,并且
9223372036854775808
正在获取该类型

让C编译器打印类型名的一种简单方法如下:

int main(void)
{

    #define LITERAL (-9223372036854775808)
    _Generic(LITERAL, struct {char x;}/*can't ever match*/: "");

}
在我的x86_64 Linux上,上面的代码生成了一个
错误:“\u int128”类型的“\u Generic”选择器与任何关联不兼容
错误消息,这意味着
\u int128
确实是文本的类型


(这样一来,
警告:整数常量太大,以至于它是无符号的
是错误的。好吧,gcc不是完美的。)

宽度和有符号性不足以识别类型,甚至是整数类型。例如,
long
几乎总是与
int
long
大小相同。显然
long
long
都不是16字节!为了识别整数数据类型,您有什么建议?我相信某些版本的gcc实现了128位类型,尽管它通常是“在软件中模拟的”,因为您是对的,大多数CPU没有寄存器,ALU的操作也没有这样的大小。如果您想根据表达式的类型做出决定,将是标准方式。要打印
sizeof
的结果,您应该使用
%zu
聪明的方法找出传入表达式或文本的数据类型!没有演员参与。我想您的意思是GCC使用了<代码> >类型128 < /代码>这个常数。对,它只有<代码> Scott Mayers的128版/代码>类型。对于C++,在推荐的但未定义的模板<代码>模板类TP中,Grac推荐了打印类型;TP-TP。我的答案基本上是使用基于
\u Generic
的C版策略。(无论如何,你可能不想用C++代码回答C标记问题。大家都知道我们C程序员经常讨厌C++:D)。@ PSKOCIK没有问题,添加了<代码> C++ >代码>标签!无论如何,我倾向于使用C++特性与C特性互换。如果我想使用C++中缺少C的东西,我只需做< >代码> IFDEF-*CPLUS PLUS ,并将其直接放入<代码> .c/code >源代码文件中,或者使用<代码>外部“C”<代码> >
warning: format '%s' expects argument of type 'char *', but argument 2 has type '__int128' [-Wformat=]
int main(void)
{

    #define LITERAL (-9223372036854775808)
    _Generic(LITERAL, struct {char x;}/*can't ever match*/: "");

}