相关疑难解决方法(0)

标准委员会关心的异域架构

我知道C和C++标准留下了语言实现的许多方面 - 仅仅因为如果存在具有其他特征的体系结构,那么为它编写符合标准的编译器是非常困难或不可能的.

我知道40年前任何电脑都有自己独特的规格.但是,我不知道今天使用的任何架构:

  • CHAR_BIT != 8
  • signed 不是两个补充(我听说Java有这个问题).
  • 浮点不符合IEEE 754(编辑:我的意思是"不是IEEE 754二进制编码").

我问的原因是我经常向人们解释C++不强制要求任何其他低级方面如固定大小的类型.这很好,因为与其他语言不同,它使你的代码在正确使用时可以移植(编辑:因为它可以移植到更多架构而不需要模拟机器的低级方面,例如符号+幅度架构上的二进制补码算法) .但我感到很难过,我自己也无法指出任何特定的架构.

所以问题是:哪些架构具有上述属性?

uint*_ts是可选的.

c c++ architecture

149
推荐指数
7
解决办法
1万
查看次数

是否有可能区分0和-0?

我知道整数值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吗?

c++ int zero negative-number

92
推荐指数
6
解决办法
7397
查看次数

减去/添加值而不会出现溢出或下溢

想象一下,我有两个无符号字节bx.我需要计算bsubas b - xbaddas 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位操作?

c c++ optimization bit-manipulation saturation-arithmetic

82
推荐指数
4
解决办法
1万
查看次数

为什么"memset(arr,-1,sizeof(arr)/ sizeof(int))"不能将整数数组清除为-1?

是不是可以在整数数组上使用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)

c

43
推荐指数
4
解决办法
6万
查看次数

将 2 个字节转换为有符号的 16 位整数的正确方法是什么?

这个回答中zwol提出了这个主张:

将来自外部源的两个字节数据转换为 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减去0x10000uuint32_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)

c casting language-lawyer

33
推荐指数
4
解决办法
4263
查看次数

为什么(int)((unsigned int)((int)v)?

我在其中找到此代码的网站

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 casting bitwise-operators

26
推荐指数
3
解决办法
1884
查看次数

C标准支持的平台列表

有没有人知道C标准支持的任何平台,对于这些平台仍然有积极的开发工作,但它们是:

  • 不是2的补充或
  • 整数宽度不是32位或64位或
  • 某些整数类型有填充位或
  • 如果您使用2的补码机器,符号位1和所有值位0的位模式不是有效的负数或
  • 从有符号到无符号的整数转换(反之亦然)不是通过逐字复制位模式或
  • 整数的右移不是算术移位或
  • 无符号类型中的值位数不是相应有符号类型+ 1或中的值位数
  • 从较宽的int类型转换为较小的类型不是通过截断不适合的最左边的位

编辑:或者,如果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 standards

24
推荐指数
5
解决办法
751
查看次数

在C中表示负数?

C如何表示负整数?

它是通过二进制补码表示还是使用MSB(最重要的位)?

-1十六进制是ffffffff.

所以请为我澄清一下.

c negative-number twos-complement language-lawyer

22
推荐指数
3
解决办法
2万
查看次数

验证C/C++签名的右移是特定编译器的算术运算?

根据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)

c c++ math signed

18
推荐指数
1
解决办法
3542
查看次数

如何以编程方式确定C中int数据的最大和最小限制?

我正在尝试运用K&R的2.1.练习内容如下:

写一个程序,以确定的范围char,short,int,和long变量,都signedunsigned通过打印从标准头合适的值,并通过直接计算.如果计算它们会更难:确定各种浮点类型的范围.

打印标准标题中常量的值很简单,就像这样(例如只显示整数):

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

7
推荐指数
1
解决办法
4649
查看次数