《斯坦福大学:编程范式》第三节:* 与&的技巧、大端与小端、最小寻址单位

---------------例1---------

double d = 3.1416;

char c = *(char*) &d;

&d 拿到指向d的内存地址,根据内存的起始点不同,值不同。

(char*)  把它当做  (char*)  类型,也就是指向char的指针。

*  解引用:根据指向的地址的起始点,向后 拿  8bits(也就是 char的内存大小,1字节 Byte)

结果是 会取 d的前八位。翻译为 char类型的值。

---------------例2-----------------------------

short s = 45;

double d = *(double*)& s;

跟上文一样,因为double 是 8字节,

所以 从 s第一个字节往后取 8字节。

但s本身是short,只有2字节,

所以,取完s的内存,还会往后取6字节。

如果后面有内存,则会拿到完整的8字节,翻译为double;

如果没有,则会导致程序崩溃。

---------------最小寻址单位----------大端编码和小端编码-----------------------------------------

也叫 大尾存储 和小尾存储。

正如之前所说,虽然计算机的存储最小单位是 bit/位。

但是 基本数据结构 都是以 byte 作为单位。

比如 bool, 虽然理论上 我们可以用 1 bit来表示,

但计算机里,我们至少要用 1 byte(8 bit)来表示它。

最小寻址单位是指特定的计算机硬件机构所支持的最小数据访问块大小。

内存的最小寻址单位为1个字节(1 Byte)即8个bit。也就是说,你无法单独访问1 bit的信息或者任意小于1字节的信息。 对应的:内存对齐会加快访问。

硬盘最小访问单位为4KB(依厂商不同而有所区别,较早的硬盘该单位比较小),这就是通常所讲的“硬盘按块寻址”,一块既指4KB的数据。对应的:4K对齐会加快访问。

在大尾存储 和小尾存储 中也是。

BigEndian(大端):低字节在高内存地址 
LittleEndian(小端):低字节在低内存地址

比如 一个short s =3 ,两个字节

在小端里:  0000,0011  从低位写起

在大端: 0011,0000    从内存地址高位写起。 (以字节为一个最小单位,而不是以bit)

大小端字节序与字符集编码之间的联系就是BOM,即 Byte Order Mark,字节顺序标记。例如可以以utf16编码将数据存储到文件中,在文件头部,会存入BOM,以表示在读取数据的时候是按照大端读取还是小端读取。FEFF表示大端,FFFE表示小端。而utf-8由于其特殊的变长编码规则,导致它是可以自解释的,所以以utf-8编码存储、传输数据时可以选择不加入BOM,同时这也是推荐的方式。

因为utf-8代码单元为1字节,每个字节高位都有标识,每当读到一个字节时,可以根据其高位进行判断。如上图,如果读到0开头的字节,则此字节单独编码;如果读到110、1110、11110开头的字节,则接着读取对应个数的字节;如果读到10开头的字节,则继续读取,读到110、1110、11110开头的字节为止。

由此看来,无需BOM并且可以无视字节序。只是utf-8解码程序稍稍麻烦一些。

而utf-16编码方式的代码单元为2字节,则一个代码单元内的两个字节的先后顺序对读取会产生影响,必须指定字节序,否则只能靠猜。

在网络传输中,tcp协议采用大端字节序,也就是先接收到的字节为数据的高位。

在不同的操作系统平台中,内存采用的字节序可能不同,x86和一般的OS(如windows,FreeBSD,Linux)使用的是小端模式。但比如Mac OS是大端模式。在不同平台之间进行网络传输时,需要进行特殊的转换。

在java中,通过 ByteOrder.nativeOrder() 方法可以判断当前平台采用的时大端字节序还是小端字节序。

public static ByteOrder nativeOrder() {
    return Bits.byteOrder();
}
static ByteOrder byteOrder() {
    if (byteOrder == null)
        throw new Error("Unknown byte order");
    return byteOrder;
}

static {
    long a = unsafe.allocateMemory(8);
    try {
        unsafe.putLong(a, 0x0102030405060708L);
        byte b = unsafe.getByte(a);
        switch (b) {
        case 0x01: byteOrder = ByteOrder.BIG_ENDIAN;     break;
        case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN;  break;
        default:
            assert false;
            byteOrder = null;
        }
    } finally {
        unsafe.freeMemory(a);
    }
}

主要实现为static静态方法,首先为long分配了8个字节内存,然后为long分配了值,之后拿出long的第一个字节,如果为数据的高位,那么平台采用的是大端字节序,如果为数据的低位,那么平台采用的时小端字节序。

原文地址:https://www.cnblogs.com/sundayofit/p/9206710.html

时间: 2024-11-29 02:05:18

《斯坦福大学:编程范式》第三节:* 与&的技巧、大端与小端、最小寻址单位的相关文章

【网络编程系列】一:字节顺序的大端与小端表示法

一.字节序 字节序,也就是字节的顺序,指的是多字节的数据在内存中的存放顺序. 在几乎所有的机器上,多字节对象都被存储为连续的字节序列.例如:如果C/C++中的一个int型变量 a 的起始地址是&a = 0x100,那么 a 的四个字节将被存储在存储器的0x100, 0x101,0x102, 0x103位置. 根据整数 a 在连续的 4 byte 内存中的存储顺序,字节序被分为大端序(Big Endian) 与 小端序(Little Endian)两类. 然后就牵涉出两大CPU派系: Motoro

网络编程中的大端和小端

将低序字节存储在内存的起始地址,这称为小端字节序. 将高序字节存储在内存的起始地址,这称为大端字节序. 检查大小端字节序的简单代码如下: intmain(int argc, char **argv){     union {        short s;         char c[sizeof(short)];     } un; un.s = 0x0102;    printf("%s: ", CPU_VENDOR_OS);    if (sizeof(short) == 2)

《斯坦福大学公开课:编程方法学》随笔

这是观看网易公开课 Mehran Sahami教授的<斯坦福大学公开课:编程方法学>后的随笔. 目前只看到第三次课,<Karel与Java>,我的收获有以下要点: 1.软件工程跟普通的写代码是不同的.软件应该考虑很多东西,比如:可移植性.便于升级维护等等,而不仅仅是写出代码实现功能那么简单. 2.代码是写给机器执行的,但更重要的是人要让人能看懂.(代码后期维护等等的工作量或者时间是写代码的10倍及更多,所以让代码更规范更易被人读懂很重要) 3.准确定义一个函数.一个类.一个包的功能

Deep Learning 12_深度学习UFLDL教程:Sparse Coding_exercise(斯坦福大学深度学习教程)

前言 理论知识:UFLDL教程.Deep learning:二十六(Sparse coding简单理解).Deep learning:二十七(Sparse coding中关于矩阵的范数求导).Deep learning:二十九(Sparse coding练习) 实验环境:win7, matlab2015b,16G内存,2T机械硬盘 本节实验比较不好理解也不好做,我看很多人最后也没得出好的结果,所以得花时间仔细理解才行. 实验内容:Exercise:Sparse Coding.从10张512*51

【编程范式】C语言1

最近在网易公开课上看斯坦福大学的<编程范式>,外国人讲课思路就是清晰,上了几节课,感觉难度确实比我们普通大学大很多,但是却很有趣,让人能边学边想. 范式编程,交换两个数,利用 void * void Swap (void * lhs,void * rhs,int size) { void * temp = malloc(sizeof(size)); memmove(temp,lhs,sizeof(size)); memmove(lhs,rhs,sizeof(size));  memmove(r

斯坦福大学 iOS 开发公开课总结

 斯坦福大学 iOS 开发公开课总结 前言 iPhone 开发相关的教程中最有名的,当数斯坦福大学发布的 “iPhone 开发公开课 “ 了.此公开课在以前叫做<iPhone 开发教程>,今年由于平板电脑的流行,所以也加入了 ipad 开发相关的课程.在 网易公开课 上,有 该教程 的 2010 年录象,并且前面 15 集带中文字幕文件,非常适合初学者学习. 在这里顺便说一下,网易公开课上的 28 集其实并不需要全部看完.真正的课程只有前面 12 集.后面的课程都是请一些业界的名人讲他们成功的

Deep Learning 十_深度学习UFLDL教程:Convolution and Pooling_exercise(斯坦福大学深度学习教程)

前言 理论知识:UFLDL教程和http://www.cnblogs.com/tornadomeet/archive/2013/04/09/3009830.html 实验环境:win7, matlab2015b,16G内存,2T机械硬盘 实验内容:Exercise:Convolution and Pooling.从2000张64*64的RGB图片(它是the STL10 Dataset的一个子集)中提取特征作为训练数据集,训练softmax分类器,然后从3200张64*64的RGB图片(它是th

Deep Learning九之深度学习UFLDL教程:linear decoder_exercise(斯坦福大学深度学习教程)

前言 实验内容:Exercise:Learning color features with Sparse Autoencoders.即:利用线性解码器,从100000张8*8的RGB图像块中提取彩色特征,这些特征会被用于下一节的练习 理论知识:线性解码器和http://www.cnblogs.com/tornadomeet/archive/2013/04/08/3007435.html 实验基础说明: 1.为什么要用线性解码器,而不用前面用过的栈式自编码器等?即:线性解码器的作用? 这一点,Ng

函数式编程(一) 认识“编程范式”和“函数”

编程范式(Programming paradigm) 编程范式指我们在编写程序解决问题的思路和视角.它提供了同时也决定了程序员对程序运行的看法.计算机编程中存在许多编程范式,如命令式编程.声明式编程.面向对象编程以及结构化编程等等.其中面向对象编程范式认为程序是由一系列相互作用的对象组成,而结构化编程范式认为程序采用子程序.代码区块.for循环以及while循环等结构组成.下面主要说明本篇文章将要讲到的命令式编程范式和声明式编程范式. 1)命令式编程(Imperative): 强调程序代码模拟电