- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
根据 C 标准,整数类型的值表示是实现定义的。所以5
可能不会表示为 00000000000000000000000000000101
或 -1
作为11111111111111111111111111111111
正如我们通常假设的 32 位 2 的补码。所以即使运营商~
, <<
和 >>
定义明确,他们将处理的位模式是实现定义的。我能找到的唯一定义的位模式是 "§5.2.1/3 所有位都设置为 0 的字节,称为空字符,应存在于基本执行字符集中;它用于终止字符串”。
所以我的问题是 - 是否有独立于实现的方法将整数类型转换为位模式?
我们总是可以从一个空字符开始,并对其进行足够的位操作以使其达到所需的值,但我觉得这太麻烦了。我还意识到实际上所有实现都将使用 2 的补码表示,但我想知道如何以纯 C 标准方式进行。就我个人而言,由于设备驱动程序编程的问题,我觉得这个主题非常有趣,到目前为止编写的所有代码都假设了一个特定的实现。
最佳答案
一般来说,在大多数情况下适应不寻常的平台并不(如果您不想简单地假设 8 位 char
,2 的补码,无填充、无陷阱和截断无符号到有符号的转换),该标准主要提供足够的保证(不过,一些宏来检查某些实现细节会有所帮助)。
就严格遵守程序可以观察到的(位域之外)而言,5 始终编码为 00...0101
。这不一定是物理表示(无论这应该意味着什么),而是可移植代码可以观察到的东西。例如,内部使用格雷码的机器必须为按位运算符和移位模拟“纯二进制表示法”。
对于有符号类型的负值,允许使用不同的编码,这会在重新解释为相应的无符号类型时导致不同(但对每种情况都有明确定义)的结果。例如,对于有符号整数 n
,严格遵守代码必须区分 (unsigned)n
和 *(unsigned *)&n
:它们相等对于没有填充位的二进制补码,但如果 n
为负数,则对于其他编码则不同。
此外,可能存在填充位,并且有符号整数类型可能比相应的无符号整数类型具有更多的填充位(但反之则不然,从有符号到无符号的类型双关总是有效的)。 sizeof
不能用于获取非填充位的数量,例如要获得一个无符号值,其中只设置了符号位(相应的有符号类型),必须使用类似这样的东西:
#define TYPE_PUN(to, from, x) ( *(to *)&(from){(x)} )
unsigned sign_bit = TYPE_PUN(unsigned, int, INT_MIN) &
TYPE_PUN(unsigned, int, -1) & ~1u;
(可能有更好的方法)而不是
unsigned sign_bit = 1u << sizeof sign_bit * CHAR_BIT - 1;
因为这可能会移动超过宽度。 (我不知道给出宽度的常量表达式,但是可以将上面的 sign_bit
右移直到它为 0 以确定它,Gcc 可以常量折叠它。)可以检查填充位通过 memcpy
ing 进入 unsigned char
数组,尽管它们可能看起来“摇摆不定”:两次读取相同的填充位可能会产生不同的结果。
如果你想要有符号整数(小端)的位模式(没有填充位):
int print_bits_u(unsigned n) {
for(; n; n>>=1) {
putchar(n&1 ? '1' : '0'); // n&1 never traps
}
return 0;
}
int print_bits(int n) {
return print_bits_u(*(unsigned *)&n & INT_MAX);
/* This masks padding bits if int has more of them than unsigned int.
* Note that INT_MAX is promoted to unsigned int here. */
}
int print_bits_2scomp(int n) {
return print_bits_u(n);
}
print_bits
根据使用的表示形式给出不同的负数结果(它给出原始位模式),print_bits_2scomp
给出二进制补码表示形式(可能具有更大的宽度如果 unsigned int
具有较少的填充位,则比 signed int
具有的多。
在使用按位运算符和从无符号到有符号的类型双关时,必须注意不要生成陷阱表示,请参阅下文如何生成这些表示(例如,*(int *)&sign_bit
可以用二进制补码捕获,-1 | 1
可以用一个补码捕获)。
无符号到有符号整数转换(如果转换后的值在目标类型中不可表示)始终是实现定义的,我希望非 2 的补码机更有可能不同于通用定义,尽管从技术上讲,它也可能成为 2 的补码实现的问题。
来自 C11 (n1570) 6.2.6.2:
(1) For unsigned integer types other than
unsigned char
, the bits of the object representation shall be divided into two groups: value bits and padding bits (there need not be any of the latter). If there are N value bits, each bit shall represent a different power of 2 between 1 and 2N-1, so that objects of that type shall be capable of representing values from 0 to 2N-1 using a pure binary representation; this shall be known as the value representation. The values of any padding bits are unspecified.(2) For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits;
signed char
shall not have any padding bits. There shall be exactly one sign bit. Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type (if there are M value bits in the signed type and N in the unsigned type, then M≤N ). If the sign bit is zero, it shall not affect the resulting value. If the sign bit is one, the value shall be modified in one of the following ways:
- the corresponding value with sign bit 0 is negated (sign and magnitude);
- the sign bit has the value -(2M) (two's complement);
- the sign bit has the value -(2M-1) (ones' complement).
Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for ones' complement), is a trap representation or a normal value. In the case of sign and magnitude and ones' complement, if this representation is a normal value it is called a negative zero.
关于c - 如何以 C 标准方式进行位表示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28937523/
我喜欢 smartcase,也喜欢 * 和 # 搜索命令。但我更希望 * 和 # 搜索命令区分大小写,而/和 ?搜索命令遵循 smartcase 启发式。 是否有隐藏在某个地方我还没有找到的设置?我宁
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 10年前关闭。 Improve this qu
从以下网站,我找到了执行java AD身份验证的代码。 http://java2db.com/jndi-ldap-programming/solution-to-sslhandshakeexcepti
似乎 melt 会使用 id 列和堆叠的测量变量 reshape 您的数据框,然后通过转换让您执行聚合。 ddply,从 plyr 包看起来非常相似..你给它一个数据框,几个用于分组的列变量和一个聚合
我的问题是关于 memcached。 Facebook 使用 memcached 作为其结构化数据的缓存,以减少用户的延迟。他们在 Linux 上使用 UDP 优化了 memcached 的性能。 h
在 Camel route ,我正在使用 exec 组件通过 grep 进行 curl ,但使用 ${HOSTNAME} 的 grep 无法正常工作,下面是我的 Camel 路线。请在这方面寻求帮助。
我正在尝试执行相当复杂的查询,在其中我可以排除与特定条件集匹配的项目。这是一个 super 简化的模型来解释我的困境: class Thing(models.Model) user = mod
我正在尝试执行相当复杂的查询,我可以在其中排除符合特定条件集的项目。这里有一个 super 简化的模型来解释我的困境: class Thing(models.Model) user = mod
我发现了很多嵌入/内容项目的旧方法,并且我遵循了在这里找到的最新方法(我假设):https://blog.angular-university.io/angular-ng-content/ 我正在尝试
我正在寻找如何使用 fastify-nextjs 启动 fastify-cli 的建议 我曾尝试将代码简单地添加到建议的位置,但它不起作用。 'use strict' const path = req
我正在尝试将振幅 js 与 React 和 Gatsby 集成。做 gatsby developer 时一切看起来都不错,因为它发生在浏览器中,但是当我尝试 gatsby build 时,我收到以下错
我试图避免过度执行空值检查,但同时我想在需要使代码健壮的时候进行空值检查。但有时我觉得它开始变得如此防御,因为我没有实现 API。然后我避免了一些空检查,但是当我开始单元测试时,它开始总是等待运行时异
尝试进行包含一些 NOT 的 Kibana 搜索,但获得包含 NOT 的结果,因此猜测我的语法不正确: "chocolate" AND "milk" AND NOT "cow" AND NOT "tr
我正在使用开源代码共享包在 iOS 中进行 facebook 集成,但收到错误“FT_Load_Glyph failed: glyph 65535: error 6”。我在另一台 mac 机器上尝试了
我正在尝试估计一个标准的 tobit 模型,该模型被审查为零。 变量是 因变量 : 幸福 自变量 : 城市(芝加哥,纽约), 性别(男,女), 就业(0=失业,1=就业), 工作类型(失业,蓝色,白色
我有一个像这样的项目布局 样本/ 一种/ 源/ 主要的/ java / java 资源/ .jpg 乙/ 源/ 主要的/ java / B.java 资源/ B.jpg 构建.gradle 设置.gr
如何循环遍历数组中的多个属性以及如何使用map函数将数组中的多个属性显示到网页 import React, { Component } from 'react'; import './App.css'
我有一个 JavaScript 函数,它进行 AJAX 调用以返回一些数据,该调用是在选择列表更改事件上触发的。 我尝试了多种方法来在等待时显示加载程序,因为它当前暂停了选择列表,从客户的 Angul
可能以前问过,但找不到。 我正在用以下形式写很多语句: if (bar.getFoo() != null) { this.foo = bar.getFoo(); } 我想到了三元运算符,但我认
我有一个表单,在将其发送到 PHP 之前我正在执行一些验证 JavaScript,验证后的 JavaScript 函数会发布用户在 中输入的文本。页面底部的标签;然而,此消息显示短暂,然后消失...
我是一名优秀的程序员,十分优秀!