我在Quora帖子中看到了以下代码:
#include <stdio.h>
struct mystruct { int enabled:1; };
int main()
{
struct mystruct s;
s.enabled = 1;
if(s.enabled == 1)
printf("Is enabled\n"); // --> we think this to be printed
else
printf("Is disabled !!\n");
}
Run Code Online (Sandbox Code Playgroud)
在C&C++中,代码的输出都是意外的,
被禁用 !!
虽然在那篇文章中给出了"符号位"相关的解释,但是我无法理解,我们如何设置某些内容然后它没有反映出来.
有人可以给出更详细的解释吗?
c c++ bit-fields signed-integer implementation-defined-behavior
signed和unsigned int有什么区别?
考虑这些定义:
int x=5;
int y=-5;
unsigned int z=5;
Run Code Online (Sandbox Code Playgroud)
它们如何存储在内存中?任何人都能解释这些在内存中的位表示吗?
能int x=5和int y=-5有相同的内存位表示?
考虑以下†:
size_t r = 0;
r--;
const bool result = (r == -1);
Run Code Online (Sandbox Code Playgroud)
结果初始化的比较是否result具有明确定义的行为?正如我所期待的那样,
结果true如何?
这个Q&A的写作是因为我不确定有两个因素.
在我的回答中,它们都可以通过使用术语"关键[ly]"来识别.
†此示例的灵感来自于计数器未签名时的循环条件方法:
for (size_t r = m.size() - 1; r != -1; r--)
我有一个简单的程序.请注意,我使用的是无符号的固定宽度整数1字节.
#include <cstdint>
#include <iostream>
#include <limits>
int main()
{
uint8_t x = 12;
std::cout << (x << 1) << '\n';
std::cout << ~x;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.get();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的输出如下.
24
-13
Run Code Online (Sandbox Code Playgroud)
我测试了更大的数字,操作员<<总是给我正数,而操作员~总是给我负数.我然后使用sizeof()并发现......
当我使用左移位运算符(
<<)时,我收到一个无符号的4字节整数.当我使用bitwise not运算符(
~)时,我收到一个带符号的4字节整数.
似乎bitwise not运算符(~)像算术运算符一样执行有符号整数提升.但是,左移运算符(<<)似乎提升为无符号整数.
我觉得有必要知道编译器什么时候改变我背后的东西.如果我在分析中是正确的,那么所有按位运算符都会提升为4字节整数吗?为什么一些签名和一些未签名?我很困惑!
编辑:我总是得到肯定或总是得到负值的假设是错误的.但是由于错误,我理解真正发生的事情,这要归功于下面的重要答案.
c++ bitwise-operators integer-promotion unsigned-integer signed-integer
在信号处理许多无损算法需要的形式⌊的表达的评估 一个 / 2 b ⌋,其中一个,b是签名(一个可能为负,b非负)的整数和⌊·⌋是地板函数.这通常会导致以下实施.
int floor_div_pow2(int numerator, int log2_denominator)
{
return numerator >> log2_denominator;
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,C标准规定>>如果左操作数具有有符号类型和负值,则运算符的结果是实现定义的.
为了确保所有平台上的正确行为,可以用多个if-else条件替换这个简单的函数,从而导致程序性能不佳.(必须有人来治疗的整数溢出和考虑的情况下,当numerator为INT_MIN.)
因此,我想问一下,在C中实现算术右移的最佳实践是什么?理想情况下,我正在寻找与上面的代码片段编译成相同代码1的构造,同时避免实现定义的行为.
1考虑例如gcc和x86-64平台
更新:
经过一番思考,我意识到我在上面的问题中做了不正确的暗示.如果平台不使用二进制补码,则使用算术移位计算负数的基函数是没有意义的.我们的目标是实现表达⌊ 一个 / 2 b ⌋在便携式方式.
c bit-manipulation bit-shift integer-arithmetic signed-integer
在 intel 指令中,idiv(integer divsion) 表示有符号除法。
我得到了 的结果idiv,但我不太明白结果。
- 例子
0xffff0000 idiv 0xffff1100
Run Code Online (Sandbox Code Playgroud)
- 我的错误预测
据我所知,quotient应该是 0,并且remainder应该是 0xffff0000 并且因为...
0xffff0000 / 0xffff1100 = 0
0xffff0000 % 0xffff1100 = 0xffff0000
Run Code Online (Sandbox Code Playgroud)
——然而,结果却是……
之前idiv
eax 0xffff0000 # dividend
esi 0xffff1100 # divisor
edx 0x0
Run Code Online (Sandbox Code Playgroud)
后 idiv
eax 0xfffeedcc # quotient
edx 0x7400 29696 # remainder
Run Code Online (Sandbox Code Playgroud)
- 问题。
结果是我无法预料的价值。
有人可以解释一下签名除法(idiv)吗?
- 附加。
这是有关idiv.
idiv使用 eax 寄存器作为源寄存器。
作为执行的结果,商存于eax,余数存于edx。
我的任务是编写一个显示程序PSP线性地址的程序.我写了以下内容:
ORG 256
mov dx,Msg
mov ah,09h ;DOS.WriteStringToStandardOutput
int 21h
mov ax,ds
mov dx,16
mul dx ; -> Linear address is now in DX:AX
???
mov ax,4C00h ;DOS.TerminateWithExitCode
int 21h
; ------------------------------
Msg: db 'PSP is at linear address $'
Run Code Online (Sandbox Code Playgroud)
我搜索了DOS api(使用Ralph Brown的中断列表)并没有找到输出数字的单个函数!我错过了吗,我该怎么办?
我想以DX:AX十进制显示数字.
我在编写一个程序试图打印 UTF-8 字符的组成字节值时遇到了这个问题。
这是我为测试各种操作而编写的程序~0:
#include <stdio.h>
int main()
{
printf("%x\n", (char)~0); // ffffffff
printf("%x\n", (unsigned char)~0); // ff
printf("%d\n", sizeof(char) == sizeof(unsigned char)); // 1
printf("%d\n", sizeof(char) == sizeof(unsigned int)); // 0
printf("%d\n", (char)~0 == (unsigned int)~0); // 1
}
Run Code Online (Sandbox Code Playgroud)
我正在努力理解为什么当char产生int- 大小的值时会unsigned char产生 -char大小的值。
是否有类似于C中的Java的Integer.MIN_VALUE,它给出了有符号整数的最小可能值,或者我只需要自己对该值进行硬编码?
signed-integer ×10
c ×6
c++ ×3
assembly ×2
bit-fields ×1
bit-shift ×1
c++11 ×1
char ×1
const ×1
division ×1
dos ×1
implementation-defined-behavior ×1
types ×1
x86 ×1
x86-16 ×1