我知道C和C++标准留下了语言实现的许多方面 - 仅仅因为如果存在具有其他特征的体系结构,那么为它编写符合标准的编译器是非常困难或不可能的.
我知道40年前任何电脑都有自己独特的规格.但是,我不知道今天使用的任何架构:
CHAR_BIT != 8signed 不是两个补充(我听说Java有这个问题).我问的原因是我经常向人们解释C++不强制要求任何其他低级方面如固定大小的类型†.这很好,因为与其他语言不同,它使你的代码在正确使用时可以移植(编辑:因为它可以移植到更多架构而不需要模拟机器的低级方面,例如符号+幅度架构上的二进制补码算法) .但我感到很难过,我自己也无法指出任何特定的架构.
所以问题是:哪些架构具有上述属性?
† uint*_ts是可选的.
我知道整数值0和-0基本相同.但是,我想知道是否有可能区分它们.
例如,我如何知道是否分配了变量-0?
bool IsNegative(int num)
{
// How ?
}
int num = -0;
int additinon = 5;
num += (IsNegative(num)) ? -addition : addition;
Run Code Online (Sandbox Code Playgroud)
-0保存在内存中的值与完全相同0吗?
想象一下,我有两个无符号字节b和x.我需要计算bsubas b - x和baddas b + x.但是,我不希望在这些操作期间发生下溢/溢出.例如(伪代码):
b = 3; x = 5;
bsub = b - x; // bsub must be 0, not 254
Run Code Online (Sandbox Code Playgroud)
和
b = 250; x = 10;
badd = b + x; // badd must be 255, not 4
Run Code Online (Sandbox Code Playgroud)
显而易见的方法包括分支:
bsub = b - min(b, x);
badd = b + min(255 - b, x);
Run Code Online (Sandbox Code Playgroud)
我只是想知道是否有更好的方法来做到这一点,即通过一些hacky位操作?
是不是可以在整数数组上使用memset?我尝试了以下memset调用,并没有在int数组中获得正确的整数值.
int arr[5];
memset (arr, -1, sizeof(arr)/sizeof(int));
Run Code Online (Sandbox Code Playgroud)
我得到的Vaules是:
arr[0] = -1
arr[1] = 255
arr[2] = 0
arr[3] = 0
arr[4] = 0
Run Code Online (Sandbox Code Playgroud) 将来自外部源的两个字节数据转换为 16 位有符号整数的正确方法是使用如下辅助函数:
#include <stdint.h>
int16_t be16_to_cpu_signed(const uint8_t data[static 2]) {
uint32_t val = (((uint32_t)data[0]) << 8) |
(((uint32_t)data[1]) << 0);
return ((int32_t) val) - 0x10000u;
}
int16_t le16_to_cpu_signed(const uint8_t data[static 2]) {
uint32_t val = (((uint32_t)data[0]) << 0) |
(((uint32_t)data[1]) << 8);
return ((int32_t) val) - 0x10000u;
}
Run Code Online (Sandbox Code Playgroud)
上述哪个函数合适取决于数组是包含小端还是大端表示。字节序是不是问题的问题,在这里,我很奇怪,为什么zwol减去0x10000u从uint32_t值转换为int32_t。
为什么这是正确的方法?
转换为返回类型时如何避免实现定义的行为?
既然您可以假设 2 的补码表示,那么这个更简单的转换将如何失败: return (uint16_t)val;
这个幼稚的解决方案有什么问题:
int16_t le16_to_cpu_signed(const uint8_t data[static 2]) {
return …Run Code Online (Sandbox Code Playgroud) int v, sign;
// or, to avoid branching on CPUs with flag registers (IA32):
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1)); // if v < 0 then -1, else 0.
Run Code Online (Sandbox Code Playgroud)
此语句为变量符号指定变量v的符号(-1或0).我想知道为什么(int)((unsigned int)((int)v)用而不是普通的v?
有没有人知道C标准支持的任何平台,对于这些平台仍然有积极的开发工作,但它们是:
编辑:或者,如果1995年至1998年期间有平台影响了C99决定包括上述内容,但已停止使用,我也会对它们感兴趣.
编辑:C理由有关填充位的说法:
填充位是用户可访问的无符号整数类型.例如,假设一台机器使用一对16位短路(每个都有自己的符号位)来构成一个32位的int,并且当在这个32位int中使用时,忽略较低short的符号位.然后,作为32位有符号整数,在确定32位有符号int的值时会忽略一个填充位(在32位的中间).但是,如果将此32位项目视为32位无符号整数,则该填充位对用户程序可见.C委员会被告知有一台机器以这种方式工作,这就是填充位被添加到C99的一个原因.
脚注44和45提到奇偶校验位可能是填充位.委员会不知道任何具有用户可访问的奇偶校验位的机器在整数内.因此,委员会不知道任何将奇偶校验位视为填充位的机器.
所以另一个问题是,C99提到的那台机器是什么?
编辑:看来,C99正在考虑消除对1的补支持和符号的振幅:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n868.htm HTTP://www.open- std.org/jtc1/sc22/wg14/www/docs/n873.htm(搜索6.2.6.2)
C如何表示负整数?
它是通过二进制补码表示还是使用MSB(最重要的位)?
-1十六进制是ffffffff.
所以请为我澄清一下.
根据C/C++标准(参见此链接),C和C++中的>>运算符不一定是有符号数的算术移位.由于位向右移位,所以由编译器实现是0(逻辑)还是符号位(算术)移入.
对于为有符号整数实现逻辑右移的编译器,此代码是否会在编译时对ASSERT(fail)起作用?
#define COMPILE_TIME_ASSERT(EXP) \
typedef int CompileTimeAssertType##__LINE__[(EXP) ? 1 : -1]
#define RIGHT_SHIFT_IS_ARITHMETIC \
( (((signed int)-1)>>1) == ((signed int)-1) )
// SHR must be arithmetic to use this code
COMPILE_TIME_ASSERT( RIGHT_SHIFT_IS_ARITHMETIC );
Run Code Online (Sandbox Code Playgroud) 我正在尝试运用K&R的2.1.练习内容如下:
写一个程序,以确定的范围
char,short,int,和long变量,都signed和unsigned通过打印从标准头合适的值,并通过直接计算.如果计算它们会更难:确定各种浮点类型的范围.
打印标准标题中常量的值很简单,就像这样(例如只显示整数):
printf("Integral Ranges (from constants)\n");
printf("int max: %d\n", INT_MAX);
printf("int min: %d\n", INT_MIN);
printf("unsigned int max: %u\n", UINT_MAX);
Run Code Online (Sandbox Code Playgroud)
但是,我想以编程方式确定限制.
我尝试了这个代码似乎应该可以工作,但它实际上进入一个无限循环并被卡在那里:
printf("Integral Ranges (determined programmatically)\n");
int i_max = 0;
while ((i_max + 1) > i_max) {
++i_max;
}
printf("int max: %d\n", i_max);
Run Code Online (Sandbox Code Playgroud)
为什么这会陷入循环?似乎当整数溢出时,它会从2147483647跳转到-2147483648.递增的值显然小于先前的值,因此循环应该结束,但它不会.
c ×9
c++ ×4
casting ×2
architecture ×1
int ×1
math ×1
optimization ×1
signed ×1
standards ×1
zero ×1