1.比特序

/ 位序 / bit numbering

/

我们知道一个字节有8位,也就是8个比特位。从第0位到第7位共8位。比特序就是用来描述比特位在字节中的存放顺序的。通过阅读网页的内容,关于比特序我们得到下面的结论:

(1)比特序分为两种:LSB

0位序和MSB

0位序。

LSB

0位序是指:字节的第0位存放数据的,即我们的数据的最低位存放在字节的第0位。

MSB

0位序是指:字节的第0位存放,即我们的数据的最高位存放在字节的第0位。

所以说对于代码:char *ch = 0x96;

//  0x96 = 1001 0110

指针ch到底指向哪里呢?不难知道,如果是LSB

0位序则显然指针ch指向最右边的也是最低位的0.

而如果是MSB

0位序则显然指针ch指向最左边的也是最高位的1.

LSB 0: A container for

8-bit binary number with the highlighted least significant bit assigned the

bit number 0

MSB 0:A container for 8-bit

binary number with the highlighted most significant bit assigned the bit

number 0

(2)小端CPU通常采用的是LSB

0位序,但是大端CPU却有可能采用LSB

0位序也有可能采用的是MSB

0位序

(Little-endian CPUs usually employ

"LSB 0" bit numbering, however both bit numbering conventions can

be seen in big-endianmachines. )

(3)推荐的标准是MSB

0位序。

(The

recommended style for Request for Comments documents is

"MSB 0" bit numbering.)

(4)Bit

numbering is usually transparent to the

In computing, the

term endian or endianness refers

to the ordering of individually addressable sub-components within

the representation of a larger data item as stored

in external memory (or,

sometimes, as sent on a serial connection). Each sub-component in

the representation has a unique degree of significance, like

the place

value of digits in a decimal number. These

sub-components are typically 16- or

32-bit words, 8-bit bytes, or

even bits.

Endianness is a difference in data representation at the hardware

level and may or may not be transparent at higher levels, depending

on factors such as the type of high level language used.

计算机中,术语“端”是指:在内存中的一个较大的数据,它是由各个可以被单独寻址的部分组成,这些组成部分在该数据中是以怎样的顺序存放的呢?而这个问题涉及到“端”的概念,CPU是大端还是小端决定了这些组成部分的存放顺序。

这些组成部分可能是16或32位的字、8位的字节、甚至是比特位。

The most common cases refer

to how bytes are ordered within a single。

我们通常碰到的情况是:字节是以怎样的顺序存放在一个16、32、64位的数据中。

(当我们要存取一个16、32、64位数据的某一组成部分,也就是某一个或几个字节时,就要特别注意机器的“大小端”)

A big-endian machine

stores the most significant byte

first, and

a little-endian machine stores

the least significant byte

first.

Quick Reference - Byte

Machine Example

Endian

First Byte

(lowest address)

Middle Bytes

Last Byte

(highest address)

Summary

big

most significant

...

least significant

Similar to a number written

on paper (in

little

least significant

...

most significant

Arithmetic calculation

order (see

Examples of storing the

value 0A0B0C0Dh in

memory

Big-endian

Atomic element size 8-bit,

address increment 1-byte (octet)

increasing

addresses→

...

0Ah

0Bh

0Ch

0Dh

...

The most significant byte (MSB) value,

which is 0Ah in our example, is

stored at the memory location with the lowest address, the next

byte value in significance, 0Bh, is stored at the

following memory location and so on. This is akin to Left-to-Right

reading in hexadecimal order.

Atomic element size

16-bit

increasing

addresses→

...

0A0Bh

0C0Dh

...

The most significant atomic

element stores now the value 0A0Bh, followed

by 0C0Dh.

Little-endian 

Atomic element size 8-bit,

address increment 1-byte (octet)

increasing

addresses→

...

0Dh

0Ch

0Bh

0Ah

...

The least significant byte (LSB)

value, 0Dh, is at the lowest address. The other

bytes follow in increasing order of significance.

Atomic element size

16-bit

increasing

addresses→

...

0C0Dh

0A0Bh

...

The least significant

16-bit unit stores the value 0C0Dh, immediately

followed by 0A0Bh. Note

that 0C0Dh and 0A0Bh represent

integers, not bit layouts (see

很显然“小端”机器符合“高高低低”的原则。及高位字节或字存放在高地址,低位字节或字存放在低地址。

另外“小端”机器中,数据在CPU的寄存器和内存中的存放顺序是一致的。

Byte addresses increasing

from right to left

在我们写: 0xFF86 时,很明显地址是从右向左递增的。也就是低位写在右边,高位写在左边。

但是当我们写字符串时:char *str = "Hello

world!",却是低位的字符写在左边,高位的字符写在了右边。

With 8-bit atomic

elements:

←increasing addresses

...

0Ah

0Bh

0Ch

0Dh

...

The least significant byte (LSB)

value, 0Dh, is at the lowest address. The other

bytes follow in increasing order of

significance.(这个明显符合我们的习惯)

With 16-bit atomic

elements:

←increasing addresses

...

0A0Bh

0C0Dh

...

The least significant

16-bit unit stores the value 0C0Dh, immediately

followed by 0A0Bh.

The display of text is

reversed from the normal display of languages such as English that

read from left to right. For example, the word "XRAY" displayed in

this manner, with each character stored in an 8-bit atomic

element:

←increasing addresses

...

"Y"

"A"

"R"

"X"

...

(可以看到和我们手写的顺序是相反的,这一点特别要注意!)

If pairs of characters are

stored in 16-bit atomic elements (using 8 bits per character), it

could look even stranger:

←increasing addresses

...

"AY"

"XR"

...

相关的一个C例子:

#include

#include

#include

int main()

{

char

a[] = {'a', 'b', 'c'};

char

b[] = {'d', 'e', 'f'};

a[3] = 0;

printf("strlen(a)=%d,

strlen(b)=%d\n", strlen(a), strlen(b));

printf("a=%s,

b=%s\n", a, b);

printf("sizeof(a)=%d,

sizeof(b)=%d\n", sizeof(a), sizeof(b));

return

0;

}

运行结果:

strlen(a)=3,

strlen(b)=6

a=abc, b=defabc

sizeof(a)=3, sizeof(b)=3

分析:

字符数组a和b都分配在栈上,先分配a,

而a中的字符是如何分配的呢?显然因为“写字符串时,低位的字符写在左边,高位的字符写在了右边”。'a'是最低位,'b'在中间,而'c'在最高位。而栈是从高地址从低地址扩展的。假如是小端CPU的话,按照“高高低低”的原则,高位的'c'应该最先分配,接着是'b',最后是'a'。

分配玩字符数组a之后,在分配字符数组b,同样的道理,高位的'f'应该最先分配,接着是'e',最后是'd'。

再执行a[3] = 0;显然a[3]的地址应该比'c'字符的地址要高。所以该语句执行玩之后的栈的情况如下:

高地址 <

\0 c b a f e d

所以:a字符串打印的结果是:abc,而b字符串打印的结果是:defabc.

strlen函数是计算字符串的长度,当然要找到最后的结束字符'\0',才停止计算。所以字符串a的长度是3,而字符串b的长度是6.

sizeof并不根据末尾的结束字符来计算大小。

例子2:

#include

int main()

{

unsigned

long array[] = {0x12345678, 0xabcdef01, 0x456789ab};

unsigned

short ret;

ret = *((unsigned

short *)((unsigned long)array+7));

printf("0x%x\n", ret);

return

0;

}

在“小端”CPU上结果为:0xabab。在“大端”CPU上应该为:0x0112.

例子3:

#include

#include

int main(void){

int a[5]={1,2,3,4,5};

int *ptr =(int *)(&a+1);

printf("%d,%d\n",*(a+1),*(ptr-1))

return

0;

}

结果为:2,5

(此题与“大小端”无关。)

判断CPU是大端还是小端的方法有有多种:

#include

#include

int main()

{

unsigned

short x = 0xff01;

assert(sizeof(x) >= 2);

if(*(char*)&x == 1) //if(char(x) == 1)

printf("little-endian\n");

else if((char)x > 1)

printf("big-endian\n");

else

printf("unknown\n");

return

0;

}

方法2:

#include

int main()

{

union{

char

c;

int i;

}u;

u.i = 0x0201;

if(u.c == 1)

printf("little-endian\n");

else if(u.c == 2)

printf("big-endian\n");

else

printf("unknown\n");

return

0;

}

3.C语言中的位域

先看几个例子:

#include

union u{

struct {

char

i:1;

char

j:2;

char

m:3;

} s;

char

c;

}r;

int main()

{

r.s.i = 1; // 1

r.s.j = 2; // 10

r.s.m = 3;

// 011

printf("0x%x\n", r.c);

return

0;

}

gcc -o union

union.c

./union

结果:0x1d (== 0001 1101

== 011 10 1)

#include

union {

struct

{

unsigned

char a1:2;

unsigned

char a2:3;

unsigned

char a3:3;

}x;

unsigned

char b;

}d;

int main(int argc, char* argv[])

{

d.b = 100;

//100 == 0110 0100

printf("0x%x\n0x%x\n0x%x\n", d.x.a1, d.x.a2, d.x.a3);

return

0;

}

gcc -o union2

union2.c

结果:

0x0 (== 00)

0x1 (== 001)

0x3 (== 011)

上面两个例子的运行结果,似乎都说明:小端机器中,位域的低位组成数据的低位,位域的高位组成了数据的高位。

似乎也符合:小端CPU通常采用的是LSB

0位序的惯例。

但是这里有意个疑问:在大端CPU中,上面两个例子的结果是什么呢?结果和小端CPU一样吗?结果唯一吗?

因为前面我们说过:“但是大端CPU却有可能采用LSB

0位序也有可能采用的是MSB

0位序”

位域 内存 字节序_C语言中的位域、字节序、比特序、大小端(转)相关推荐

  1. 大端字节序码流中取出2字节_graalvm字节码到位码

    大端字节序码流中取出2字节 GraalVM & Micronauts - frenzy way to MicroServices, Serverless: Part1 GraalVM和Micr ...

  2. 大端字节序码流中取出2字节_产生字节码

    大端字节序码流中取出2字节 在这篇文章中,我们将看到如何为我们的语言生成字节码. 到目前为止,我们已经看到了如何构建一种语言来表达我们想要的东西,如何验证该语言,如何为该语言构建编辑器,但实际上我们还 ...

  3. 大端字节序码流中取出2字节_字节码忍者的秘密

    大端字节序码流中取出2字节 Java语言由Java语言规范(JLS)定义. 但是,Java虚拟机的可执行字节码由单独的标准Java虚拟规范(通常称为VMSpec)定义. JVM字节码由javac从Ja ...

  4. c语言读取文件字节数,怎么在C语言中利用fstat函数获取文件的大小

    怎么在C语言中利用fstat函数获取文件的大小 发布时间:2021-01-22 17:03:17 来源:亿速云 阅读:110 作者:Leah 怎么在C语言中利用fstat函数获取文件的大小?针对这个问 ...

  5. 怎么把位域合成一个字节_C语言中字节对齐和位域

    1.1基本类型默认字节对齐和改变字节对齐方式 c语言在给不同类型变量分配地址空间时,并不是总是紧邻着上一个变量的地址空间分配的,而是它所在的地址空间,必须被它的默认对齐字节数整除.例如,int类型占4 ...

  6. c# 结构体 4字节对齐_C语言程序员们常说的“内存对齐”,究竟有什么目的?

    在C语言程序开发中,有时有经验的程序员会提起"内存对齐"一词,事实上,这也是C语言中结构体的 size 不等于它所有成员 size 之和的原因(C语言中的结构体的size,并不等于 ...

  7. c语言中非法使用void类型_C语言中的数据类型

    为什么需要介绍数据类型 学习语言编程,不用急着写代码,先搞懂基本概念.有了基本概念后,然后再考虑在不同的语言中是如何表达的.不同语言无非就是表达方式不一样而已,万变不离其宗. 每一门语言开始部分中总是 ...

  8. c语言字符串加减_C语言中指针的介绍

    C语言中指针的介绍 指针是C语言中广泛使用的一种数据类型. 运用指针编程是C语言最主要的风格之一.利用指针变量可以表示各种数据结构:能很方便地使用数组和字符串: 并能象汇编语言一样处理内存地址,从而编 ...

  9. c语言中申请内存并初始化,c语言中结构体的定义、初始化及内存分配

    #include struct person { char *name; int age; }; int main() { //结构体可以定义在函数内,也可以定义到函数外 //相当于全局变量与局部变量 ...

最新文章

  1. SpringBoot下文件上传与下载的实现
  2. php+方法返回多个参数,PHP中调用外部程序,及其参数与返回值
  3. 图像降噪算法——非局部均值降噪算法
  4. es创建索引库,无法使用InetSocketTransportAddress
  5. php网站xml链接,xml图像超链接的制作代码
  6. c#中实现图像图像卷积与滤波-高斯平滑
  7. 简单却实用的的例子:Jquery获取 radio 选中后的文字
  8. C++ 拷贝构造函数与赋值构造函数调用时机初步01
  9. 荣耀系统更新服务器不可用,荣耀确认系统更新方式 4月1日前发布的机型固件升级由华为负责...
  10. [转]关于Apple TV(take 2)及 iPhone 更新的相关内容
  11. SQLi LABS Less-39
  12. RPLIDAR最强参数详解
  13. 工具 | 2的次方对照表
  14. 加速度传感器和角度传感器
  15. QCOM chi-camera bring up
  16. 2019大数据未来七大发展方向
  17. r语言python0基础_万丈高楼平地起,从零开始学R语(生信分析向,R语言基础)...
  18. Python中不为人知的四个特性
  19. Arduino之读取温度传感器并串口显示
  20. 全球注意力缺陷多动障碍(ADHD)市场规模2021年大约为796亿元(人民币),预计2028年将达到1259亿元

热门文章

  1. 一步步把 SAP UI5 应用部署到 SAP BTP Kyma 运行环境中去
  2. SAP CRM Fiori Launchpad 登录之后,看不见任何 tile 的解决办法
  3. [1] JSP里的一个最简单的过滤器(filter)的例子
  4. SAP Cloud for Customer的Mashup位于CustomPane里
  5. 使用Fiddler监控使用RestTemplate发送网络请求的Java应用
  6. 使用ABAP绘制可伸缩矢量图
  7. CRM Fiori Application top N Opportunity
  8. Jerry带您了解Restful ABAP Programming模型系列之三:云端ABAP应用调试
  9. Time value help in webclient UI
  10. search by Belonging to my team测试 - with manager role