定义的变量的位域就是4是啥意思?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了定义的变量的位域就是4是啥意思?相关的知识,希望对你有一定的参考价值。

如果你定义的变量的位域就是4的话,那确实变小了,但是如果位域不是4的话,那就是另一回事了,比如说下面的;
unsigned char c = 0x80;
c <<= 1;
这个得到的结果c = 0;
但是对于
unsigned int c = 0x80;
c <<= 1;
得到的结果确实256,而不是0,就是这个原因

指的是变量分配的字节数,int变量占4个字节,char占1个字节

所以,位域 = 字节(byte)

unsigned char c = 0x80;
占1个字节,也就是8位(bit)
c的二进制1000 0000,左移一位,即0000 0000 ,c的二进制为0000 0000 即十进制0

unsigned int c = 0x80;
占4个字节,也就是32位(bit)
c的二进制为00000000 00000000 00000000 10000000,左移一位
即00000000 00000000 00000001 00000000,即十进制256,c = 256
参考技术A 很专业啊,不过楼上正解 就不复制啦 参考技术B 定义的是byte有什么问题? 不管是byte还是int都一样的啊, 当然unsigned是不一样的 这个叫做 位段 或者位域(可百度百科查看此解释) 资料:针对类

澄清 C 中的位域排序语义

【中文标题】澄清 C 中的位域排序语义【英文标题】:Clarification about Bit-field ordering semantics in C 【发布时间】:2013-09-10 05:19:23 【问题描述】:

我很难理解 C99 标准草案 (N1256) 中关于位域 (6.7.2.1:10) 的一段的确切含义:

6.7.2.1 结构和联合说明符

[...]

语义

[...]

实现可以分配任何大到足以容纳位字段的可寻址存储单元。如果有足够的空间剩余,紧跟在结构中另一个位域之后的位域将被打包到同一单元的相邻位中。如果剩余空间不足,则将不适合的位域放入下一个单元还是与相邻单元重叠是实现定义的。 一个单元内的位域分配顺序(高位到低位或低位到高位)是实现定义的。未指定可寻址存储单元。

强调的句子将我的英语技能发挥到了极限:我不明白它是指一个单元内的单个位域,还是指单个位域内的位排序或其他东西。

我会试着用一个例子来说明我的疑问。假设无符号整数是 16 位,实现选择无符号整数作为可寻址存储单元(并且字节为 8 位宽),并且不会出现其他对齐或填充问题:

struct Foo 
    unsigned int x : 8;
    unsigned int y : 8;
;

因此,假设xy 字段存储在同一个单元内,那么根据该语句定义的实现是什么?据我了解,这意味着在该 unsigned int 单元内,x 可以存储在低于y 的地址或反之亦然,但我不确定,因为直觉上我认为如果没有位域与两个底层存储单元重叠,声明顺序将对底层位域施加相同的顺序。

注意:我担心我在这里遗漏了一些微妙的术语(或者更糟糕的是,一些技术术语),但我不明白是哪一个。

任何指针表示赞赏。谢谢!

【问题讨论】:

您所说的等等... 无法保证unsigned x : 1 会修改哪个位,是最低位还是最高位。所以如果sizeof(unsigned int) == 4,x可以保存在第1位或第32位。 Representing individual bits in C 的可能重复项 【参考方案1】:

我的看法是,C99 规范正在讨论位字段的位字节序,以及它们如何在“单元”(字节字等)中排序。如果你开始转换结构,基本上你是靠自己的。

例子

bit  ex1    ex2   ex3
D7   x3     y0    x0
D6   x2     y1    x1
D5   x1     y2    x2
D4   x0     y3    x3
D3   y3     x0    y0
D2   y2     x1    y1
D1   y1     x2    y2
D0   y0     x3    y3

以上三种不同的方案用于对字节“单元”中的两个 4 位字段进行排序。就 C99 标准而言,它们都是合法的。

【讨论】:

【参考方案2】:

我真的看不出有什么不清楚的地方

一个单元内位域的分配顺序(高位到 低阶或低阶到高阶)是实现定义的。

它谈论的是位域的分配,而不是域内的位。因此,除了非位域成员之外,您无法确定可寻址单元内的位域是按什么顺序排序的。

否则,位域本身的表示保证与基础类型“相同”,分为值位和符号位(如果适用)。

本质上,它表示包含位域的存储单元的解剖结构是实现定义的,您不应尝试通过其他方式(union 左右)访问这些位,因为这会使您的代码非便携式。

【讨论】:

正如我在问题中所暗示的那样,我担心我会错过一些关于位域的东西(我希望这只是一些术语上的混淆,但从我得到的答案中我想我有以便更好地了解技术方面)。我从来没有不得不使用位域,但可能在不久的将来我会需要它们,因此我试图直接从标准中掌握细节。您的解释非常清楚 (+1),但我仍然需要花时间将其与标准文本联系起来。 @LorenzoDonati,是的,它的语义不是那么容易掌握,我同意。尽可能避免使用位域,因为它们通常不能实现太多目的。如果您对以压缩形式可移植地操作位感兴趣,那么在uint64_t 等无符号类型上使用位计算可能更可取。对于不同类型平台之间的二进制数据兼容性,位域也没有多大帮助。 我意识到我需要花更多时间在这个主题上,但在我看来,标准对位域的保证仍然相当少。一切似乎都是由实现定义的。我现在不确定,但我想我需要对一些外部专用 I/O 接口卡的硬件寄存器的访问进行编程。我认为位域可以减轻(但未知的)任务(所以我先发制人),但它似乎不能便携。不管怎样,谢谢!如果在接下来的几天内没有更详细的解释出现,我会接受你的回答。 所以除了非位域成员,你不能确定可寻址单元内的位域是按什么顺序排序的。:你不能确保一般。如果实现是已知的,那么您可以确定,因为顺序是实现定义的。【参考方案3】:

Gibbon1 的回答是正确的,但我认为示例代码对这类问题很有帮助。

#include <stdio.h>

int main(void)

    union 
        unsigned int x;
        struct 
            unsigned int a : 1;
            unsigned int b : 10;
            unsigned int c : 20;
            unsigned int d : 1;
         bits;
     u;
    
    u.x = 0x00000000;
    u.bits.a = 1;
    printf("After changing a: 0x%08x\n", u.x);
    u.x = 0x00000000;
    u.bits.b = 1;
    printf("After changing b: 0x%08x\n", u.x);
    u.x = 0x00000000;
    u.bits.c = 1;
    printf("After changing c: 0x%08x\n", u.x);
    u.x = 0x00000000;
    u.bits.d = 1;
    printf("After changing d: 0x%08x\n", u.x);
    
    return 0;

在使用 MinGW 的 GCC 的 little-endian x86-64 CPU 上,输出为:

更改a后:0x00000001

改变b后:0x00000002

改c后:0x00000800

改d后:0x80000000

由于这是一个联合,无符号整数(x)和位域结构(a/b/c/d)占用同一个存储单元。 [the] 位域的分配顺序决定了 u.bits.a 是指 x 的最低有效位还是 x 的最高有效位。通常,在 little-endian 机器上:

u.bits.a == (u.x & 0x00000001)
u.bits.b == (u.x & 0x000007fe) >> 1
u.bits.c == (u.x & 0xeffff800) >> 11
u.bits.d == (u.x & 0x80000000) >> 31

在大端机器上:

u.bits.a == (u.x & 0x80000000) >> 31
u.bits.b == (u.x & 0x7fe00000) >> 21
u.bits.c == (u.x & 0x001ffffe) >> 1
u.bits.d == (u.x & 0x00000001)

该标准的意思是,C 编程语言不需要任何特定的字节序——大字节序和小字节序机器可以按照最适合其寻址方案的顺序放置数据。

【讨论】:

以上是关于定义的变量的位域就是4是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

c里面冒号的意思,C语言中的冒号(:是啥意思

请问 C语言里的 结构体中定义变量 后面的:是啥意思

求大神指教C语言中的位域

C语言结构体在定义的时候,各成员后面加冒号是啥意思?

c语言中,函数定义中的冒号是啥意思?

通俗地说,位域是啥?