是否有一种或多或少可靠的方法(不一定完美)来检测我正在编译的目标体系结构的机器字大小?
通过机器字大小我的意思是整数累加器寄存器(例如EAX在x86,RAX在x86_64等,尺寸不流扩展,段或浮点寄存器).
该标准似乎没有提供"机器字"数据类型.因此,我不是在寻找100%可移植的方式,只适用于大多数常见情况(Intel x86 Pentium +,ARM,MIPS,PPC - 即基于寄存器的现代商品处理器).
size_t并且uintptr_t听起来像是好的候选者(并且在实践中匹配我测试的所有寄存器大小)但当然是其他东西,因此不能保证总是如Is size_t中所描述的那样.
上下文
假设我正在对一块连续数据实现散列循环.将结果散列依赖于编译器是可以的,只有速度很重要.
示例:http://rextester.com/VSANH87912
在Windows上进行测试表明,在64位模式下,64位块的散列更快,在32位模式下散列为32位:
64-bit mode
int64: 55 ms
int32: 111 ms
32-bit mode
int64: 252 ms
int32: 158 ms
Run Code Online (Sandbox Code Playgroud) void fun(){
signed int a=-5;
unsigned int b=-5;
printf("the value of b is %u\n",b);
if(a==b)
printf("same\n");
else
printf("diff");
}
Run Code Online (Sandbox Code Playgroud)
它是印刷:
4294967291
相同
在第二行中,有符号值转换为无符号值.所以b的值为UINTMAX + 1 - 5 = 4294967291.
我的问题是比较操作中发生了什么.
1)是否再次转换为无符号并与b进行比较?
2)b(即无符号)是否会被转换为有符号值并自动进行比较?
3)由于int溢出,是否从unsigned转换为signed undefined?
我已阅读有关该主题的其他帖子.我只想澄清问题2和问题3.
很多类似问题的回答都指出,标准是这样的。但是,我无法理解标准制定者做出这一决定背后的原因。
根据我的理解, anunsigned char不会以 2 的补码形式存储值。所以,我没有看到让我们说XOR ing twounsigned chars会产生意外行为的情况。因此,将它们提升到int似乎只是浪费空间(在大多数情况下)和 CPU 周期。
此外,为什么int?如果一个变量被声明为unsigned,显然无符号对程序员很重要,因此在我看来,升级到 anunsigned int仍然比 an 更有意义int。
[编辑 #1] 如评论中所述,unsigned int如果int无法充分容纳unsigned char.
[编辑#2] 为了澄清这个问题,如果它是关于在intthan上运行的性能优势char,那么为什么它在标准中?这可以作为向编译器设计者提供更好优化的建议。现在,如果有人要设计一个不这样做的编译器,这将使他们的编译器不完全遵守 C/C++ 标准,即使假设该编译器确实支持该语言的所有其他必需功能。简而言之,我无法弄清楚为什么我不能直接操作的原因unsigned chars,因此将它们提升到 的要求ints似乎没有必要。你能举个例子证明这是错误的吗?
我想要得到的价值INT_MIN和INT_MAX,和我试过~0和~0 >> 1,因为最左边的位为符号位.我得到了他们两个-1.
它太混乱了,为什么不~0成为0xffffffff和~0 >> 1将来0x7fffffff?
即使在脚本中,开发人员也保证变量永远不会超过一个字节,有时甚至超过两个字节,这是很常见的.许多人决定使用int每种可能变量的类型来表示0-1范围内的数字.
为什么使用char或short反而伤害这么多?
我想我听到有人说int是"更标准"类型的..类型.这是什么意思.我的问题是数据类型int是否具有任何明确的优势short(或其他较小的数据类型),因为人们过去几乎总是诉诸于哪些优势int?
我有一个16位无符号变量.我需要将它分成8位块.
正在做以下事情:
chunk_lsb = (uint8)variable;
chunk_msb = (uint8)(variable >> 8);
Run Code Online (Sandbox Code Playgroud)
或者我应该使用面具:
chunk_lsb = (uint8)(variable & 0xFFu);
chunk_msb = (uint8)((variable >> 8) & 0xFFu);
Run Code Online (Sandbox Code Playgroud)
我知道这两种方法都有效,我只是在寻找最好的方法,如果有的话.也许没有,只是使用演员来减少计算是最好的方法?你们有什么感想?
我是C-Headers的新手- stdint.h和inttypes.h。我正在尝试一些代码以了解uint8_t工作原理。但是,似乎遇到了问题。
我已经声明了4 uint8_t个分别具有边界值0、255、256,-1的整数,并对其执行了一些简单的算术运算。我这样做是因为我想知道C编译器(我在Linux上使用)会产生什么错误/警告gcc 5.4.0。如果不是这样的话,我很想知道输出是什么样子。下面给出的代码。
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
int main() {
int a = 10;
printf("%d\n", a++);
printf("%d\n\n", a);
// 8 bit unsigned integer -> range[0, 255]
uint8_t ua81=0, ua82=255, ua83=256, ua84=-1;
printf("--------STDINT.H----uint8_t--DEMO--------\nua81 = %" PRIu8 "\n", ua81);
printf("ua82 = %" PRIu8 "\nua83 = %" PRIu8 "\nua84 = %" PRIu8 "\n\n", ua82, ua83, ua84);
printf("ua81+1 = %" PRIu8 "\nua82-3 = %" PRIu8 "\nua83-4+7 = %" PRIu8 …Run Code Online (Sandbox Code Playgroud) 想象一下这种情况.int32_t是一个扩展的整数类型,它以二进制补码表示(作为int32_t要表示的标准).这意味着INT32_MIN是-2147483648(0x80000000).
同时int是标准整数类型,它以一个补码表示(标准允许).这意味着INT_MIN是-2147483647.
现在纠正我,如果我错了,但我认为两种类型都有相同的宽度,这意味着,根据6.3.1.1.1(强调我的):
任何标准整数类型的等级应大于具有相同宽度的任何扩展整数类型的等级.
所以排名int32_t低于int.
现在6.3.1.8(通常的算术转换)说(强调我的):
<...>否则,将对两个操作数执行整数提升.然后将以下规则应用于提升的操作数:如果两个操作数具有相同的类型,则不需要进一步转换.否则,如果两个操作数都具有有符号整数类型或两者都具有无符号整数类型,则具有较小整数转换等级类型的操作数将转换为具有更高等级的操作数的类型.
因此,如果正确理解它,在此代码块中:
int32_t x = INT32_MIN;
int y = 1;
x + y; // What happens here?
Run Code Online (Sandbox Code Playgroud)
在表达式中x + y,x必须被提升为int,并且INT32_MIN超出范围int.
这是标准中的错误还是我遗漏了什么?
换句话说,x + y根据标准的定义,此上下文中的表达式评估了什么?
#include <iostream>
using namespace std;
int main()
{
int a;
long b;
cout<<sizeof(a+b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出为 8(长变量的大小)。为什么它不返回它们的总和?
我最近在写一些实际上应该测试其他代码的代码,但偶然发现了一个令人惊讶的整数提升案例。这是最小的测试用例:
#include <cstdint>
#include <limits>
int main()
{
std::uint8_t a, b;
a = std::numeric_limits<std::uint8_t>::max();
b = a;
a = a + 1;
if (a != b + 1)
return 1;
else
return 0;
}
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,该程序返回1。一些调试和预感表明,b + 1在条件a + 1语句中实际上返回了256,而在赋值操作中产生了预期值0。
C ++ 17草案的第8.10.6节(关于等式/不等号运算符)指出:
如果两个操作数均为算术或枚举类型,则对两个操作数执行常规的算术转换;如果指定的关系为真,则每个运算符都将产生true;如果指定的关系为false,则每个运算符应产生false。
什么是“通常的算术转换”,在标准中它们在哪里定义?我的猜测是,它们隐式地将较小的整数提升为某些运算符int或unsigned int为某些运算符提升(这也得到以下事实的支持:用产生的结果替换std::uint8_t为unsigned int0,而且赋值运算符缺少“常规算术转换”子句)。