⑴ 电脑开机自检顺序是什么
自检测过程大致为:加电-CPU-ROM-BIOS-System Clock-DMA-64KB RAM-IRQ-显卡-VGA接口-键盘-硬盘-并行口(打印机)和串行口(RS232)。所以电脑自检首先自检cpu,到串行口(RS232)检查结束。
自检中如发现有错误,将按两种情况处理:对于严重故障(致命性故障)则停机,此时由于各种初始化操作还没完成,不能给出任何提示或信号;对于非严重故障则给出提示或声音报警信号,等待用户处理。
当自检完成后,系统进行下一步骤:从硬盘、光盘或网络服务器上寻找操作系统进行启动,电脑的控制权将由操作系统完成。
(1)电脑网络字节顺序图扩展阅读
开机自检音所代表的含义:
1短:系统正常启动。恭喜,你的机器没有任何问题。
2短:常规错误,请进入CMOS Setup,重新设置不正确的选项。
1长1短:内存或主板出错。换一条内存试试,若还是不行,只好更换 主板。
1长2短:显示器或显示卡错误。
1长3短:键盘控制器错误。检查主板。
2短1短1短 前64K基本内存错误。
3短1短1短 DMA寄存器错误。
3短1短2短 主DMA寄存器错误。
4短3短4短 时钟错误。
4短4短1短 串行口错误。
4短4短2短 并行口错误。
⑵ 求计算机的基本知识跟基础大全
程序员不能任意命名,而是有规则的,因为如果遇到系统变量等,自己乱定义会冲突的。
⑶ 什么是数据包序例号
“包”(Packet)是TCP/IP协议通信传输中的数据单位,一般也称“数据包”。有人说,局域网中传输的不是“帧”(Frame)吗?没错,但是TCP/IP协议是工作在OSI模型第三层(网络层)、第四层(传输层)上的,而帧是工作在第二层(数据链路层)。上一层的内容由下一层的内容来传输,所以在局域网中,“包”是包含在“帧”里的。 名词解释:OSI(Open System Interconnection,开放系统互联)模型是由国际标准化组织(ISO)定义的标准,它定义了一种分层体系结构,在其中的每一层定义了针对不同通信级别的协议。OSI模型有7层,1�7层分别是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。OSI模型在逻辑上可分为两个部分:低层的1�4层关注的是原始数据的传输;高层的5�7层关注的是网络下的应用程序。 我们可以用一个形象一些的例子对数据包的概念加以说明:我们在邮局邮寄产品时,虽然产品本身带有自己的包装盒,但是在邮寄的时候只用产品原包装盒来包装显然是不行的。必须把内装产品的包装盒放到一个邮局指定的专用纸箱里,这样才能够邮寄。这里,产品包装盒相当于数据包,里面放着的产品相当于可用的数据,而专用纸箱就相当于帧,且一个帧中只有一个数据包。 “包”听起来非常抽象,那么是不是不可见的呢?通过一定技术手段,是可以感知到数据包的存在的。比如在Windows 2000 Server中,把鼠标移动到任务栏右下角的网卡图标上(网卡需要接好双绞线、连入网络),就可以看到“发送:××包,收到:××包”的提示。通过数据包捕获软件,也可以将数据包捕获并加以分析。 就是用数据包捕获软件Iris捕获到的数据包的界面图,在此,大家可以很清楚地看到捕获到的数据包的MAC地址、IP地址、协议类型端口号等细节。通过分析这些数据,网管员就可以知道网络中到底有什么样的数据包在活动了。 附: 数据包的结构 数据包的结构非常复杂,不是三言两语能够说清的,在这里主要了解一下它的关键构成就可以了,这对于理解TCP/IP协议的通信原理是非常重要的。数据包主要由“目的IP地址”、“源IP地址”、“净载数据”等部分构成。 数据包的结构与我们平常写信非常类似,目的IP地址是说明这个数据包是要发给谁的,相当于收信人地址;源IP地址是说明这个数据包是发自哪里的,相当于发信人地址;而净载数据相当于信件的内容。 正是因为数据包具有这样的结构,安装了TCP/IP协议的计算机之间才能相互通信。我们在使用基于TCP/IP协议的网络时,网络中其实传递的就是数据包。理解数据包,对于网络管理的网络安全具有至关重要的意义。
参考资料:http://ke..com/view/25880.htm
⑷ 计算机网络原理问题 请解答第二问
2017年12月07日星期四,
问题:
请注意看上图,1分组中的第二行(tcp报头)中第二个4字节的值就是Sequence number(顺序号码),它明确的告诉目标主机(d3444750)需要接收Sequence number(顺序号码)为846b741c5的数据包,然后2分组中的源主机(d3444750)对Sequence number(顺序号码)846b741c5的数据包进行确认,并按照tcp规则将Sequence number(顺序号码)加一后写入第二行的第三个4字节中即Acknowledge number(确认号码),同时,向自己的目标主机(c0a80008)发送Sequence number(顺序号码)为(e0599fef)的数据包,最后,3分组中的第二行中的第三个4字节对刚才从主机(d3444750)接收的(e0599fef)的数据包进行了确认【也是Acknowledge number(确认号码)+1】,又因为接到了主机(d3444750)对846b741c5的数据包的确认,因此将同时发送Sequence number(顺序号码)为846b741c6的数据包给目标主机(d3444750)。
参考书内容:TCP(Transmission Control Protocol)传输控制协议
TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:
位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)Sequence number(顺序号码) Acknowledge number(确认号码)
第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到主机B,主机B由SYN=1知道,A要求建立联机;
第二次握手:主机B收到请求后,要确认联机信息,向A发送ack number=1234568(主机A的seq number+1),syn=1,ack=1,随机产生seq number=7654321的包;
第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及ack(对A的发送来的请求,B的确认,)是否为1,若正确,主机A会再发送ack number=7654322(主机B的seq number+1),ack=1,主机B收到后确认seq number值(7654322)并且ack=1则连接建立成功。
扩展阅读材料:
TCP传输连接中的SYN、ACK、SEQ、AN分别是什么意思?他们所带的数字又是代表什么?
SYn=1.ACK=0,SEQ=200
SYN=1,ACK=1.SEQ=4800,AN=201
SYN=1,ACK=1.SEQ=201,AN=4801
SYN,ACK是标志位
SEQ,AN是数据包序号
SYN=1, ACK=0, SEQ=200 的意思是:发送端发出一个SYN请求(SYn=1),同时发送端发送了一个序号为SEQ=200的数据包,
SYN=1, ACK=1, SEQ=4800, AN=201 的意思是:接收端的确认信息,收到了序号为SEQ=200的数据包,同时接收端也发送了一个初始数据包序号为SEQ=4800的数据包,并等待发送端确认,
SYN=1,ACK=1.SEQ=201,AN=4801的意思是:首先,发送端通过接收端送回的AN=201,知道接收端已成功的接收了序号为SEQ=200的数据包,接下来发送端要发送序号为SEQ=201的数据包,并且同时告知接收端刚才送来的序号为SEQ=4800的包已收到,
⑸ 什么是字节序
小头 (LSB):
Least Significant Bit (or Byte)
大头 (MSB):
Most Significant Bit (or Byte)
字节序,即字节在电脑中存放时的序列与输入(输出)时的序列是先到的在前还是后到的在前。
输入(输出)流字节序:
B1,B2,B3,B4,B5,B6.....
电脑中
short int a,b,c;
可能是:
a = B2 << 8 + B1;
b = B4 << 8 + B3;
c = B6 << 8 + B5;
也可能是:
a = B1 << 8 + B2;
b = B3 << 8 + B3;
c = B5 << 8 + B6;
这取决于字节序的约定。例如GIF图像文件中的许多定义块中的short int 是 a = B2 << 8 + B1; ...
即B2左移8位加B1等于一个十六位的整数。
⑹ 字节序的字节数据
1.BIG-ENDIAN、LITTLE-ENDIAN跟多字节类型的数据有关的比如int,short,long型,而对单字节数据byte却没有影响。
比如 int a = 0x08070605
在BIG-ENDIAN的情况下存放为:
字节号 0 1 2 3
数据 08 07 06 05
在LITTLE-ENDIAN的情况下存放为:
字节号 0 1 2 3
数据 05 06 07 08
又比如数字0x87654321,在两种不同字节序CPU中,其存储顺序如下所示:
Little Endian
低地址 高地址
----------------------------------------->
| 21 |43 | 65 | 87 |
Big Endian
低地址 高地址
----------------------------------------->
| 87 |65 | 43 |21 |
从上面两图可以看出:
采用LITTLE-ENDIAN方式存储数据,地位地址存放低位数据,可以用“低对低”来方便记忆与理解。
采用BIG-ENDIAN方式存储数据,从书写习惯上看,高位数据排列在前面(低址在前面),可以用“高位在前”来简化理解。
2.BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有关的,每一种CPU不是BIG-ENDIAN就是LITTLE-ENDIAN、。IA架构(Intel、AMD)的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola处理器是Big-Endian。这其实就是所谓的主机字节序。而网络字节序是指数据在网络上传输时是大头还是小头的,在Internet的网络字节序是BIG-ENDIAN。所谓的JAVA字节序指的是在JAVA虚拟机中多字节类型数据的存放顺序,JAVA字节序也是BIG-ENDIAN。
3.所以在用C/C++写通信程序时,在发送数据前务必用htonl和htons去把整型和短整型的数据进行从主机字节序到网络字节序的转换,而接收数据后对于整型和短整型数据则必须调用ntohl和ntohs实现从网络字节序到主机字节序的转换,在Visual C++中,这四个函数被包含在头文件Winsock2.h里面,链接时需要链入Ws2_32.lib。如果通信的一方是JAVA程序、一方是C/C++程序时,则需要在C/C++一侧使用以上几个方法进行字节序的转换,而JAVA一侧,则不需要做任何处理,因为JAVA字节序与网络字节序都是BIG-ENDIAN,只要C/C++一侧能正确进行转换即可(发送前从主机序到网络序,接收时反变换)。如果通信的双方都是JAVA,则根本不用考虑字节序的问题了。
4.如果网络上全部是相同字节序的计算机那么不会出现任何问题,但由于实际有大量不同字节序的计算机,所以如果不对数据进行转换,就会出现大量的错误。
5.文章开头所提出的问题,就是因为程序运行在X86架构的PC SERVER上,发送数据的一端用C实现的,接收一端是用JAVA实现的,而发送端在发送数据前未进行从主机字节序到网络字节序的转换,这样接收端接收到的是LITTLE-ENDIAN的数据,数据解释自然出错。
具体数据如下,实际发送的数据为23578
发送端发送数据: 1A 5C
接收端接收到数据后,按BIG-ENDIAN进行解释得到的则是6748,显然不是正确的数据。
⑺ 字节、KB、MB、GB 之间的换算关系
数据存储以10进制表示:
1B(byte,字节)= 8 bit(见下文);
1KB(Kilobyte,千字节)=1000B= 10^3 B;
1MB(Megabyte,兆字节,百万字节,简称“兆”)=1000KB= 10^6 B;
1GB(Gigabyte,吉字节,十亿字节,又称“千兆”)=1000MB= 10^9 B。
数据传输以2进制表示:
1B(byte,字节)= 8 bit(见下文);
1KiB(Kibibyte,千字节)=1024B= 2^10 B;
1MiB(Mebibyte,兆字节,百万字节,简称“兆”)=1024KB= 2^20 B;
1GiB(Gibibyte,吉字节,十亿字节,又称“千兆”)=1024MB= 2^30 B。
(7)电脑网络字节顺序图扩展阅读:
字节相关单位:
B与bit
数据存储是以“字节”(Byte)为单位,数据传输大多是以“位”(bit,又名“比特”)为单位,一个位就代表一个0或1(即二进制),每8个位(bit,简写为b)组成一个字节(Byte,简写为B),是最小一级的信息单位。
B与iB
1KiB(Kibibyte)=1024byte
1KB(Kilobyte)=1000byte
1MiB(Mebibyte)=1048576byte
1MB(Megabyte)=1000000byte
硬盘生产商是以GB(十进制,即10的3次方=1000,如1MB=1000KB)计算的,而电脑(操作系统)是以GiB(2进制,即2的10次方, 如1MiB=1024KiB)计算的,但是国内用户一般理解为1MiB=1M=1024 KB, 所以为了便于中文化的理解,翻译MiB为MB也是可以的。
⑻ 网络字节顺序和机器顺序什么区别
存在两种字节顺序:NBO与HBO
网络字节顺序NBO(Network Byte Order):
按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
主机字节顺序(HBO,Host Byte Order):
不同的机器HBO不相同,与CPU设计有关
计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先。Internet上数据以高位字节优先顺序在网络上传输,所以对于在内部是以低位字节优先方式存储数据的机器,在Internet上传输数据时就需要进行转换。
我们要讨论的第一个结构类型是:struct sockaddr,该类型是用来保存socket信息的:
struct sockaddr {
unsigned short sa_family; /* 地址族, AF_xxx */
char sa_data[14]; /* 14 字节的协议地址 */ };
sa_family一般为AF_INET;sa_data则包含该socket的IP地址和端口号。
另外还有一种结构类型:
struct sockaddr_in {
short int sin_family; /* 地址族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* IP地址 */
unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小 */
};
这个结构使用更为方便。sin_zero(它用来将sockaddr_in结构填充到与struct sockaddr同样的长度)应该用bzero()或memset()函数将其置为零。指向sockaddr_in 的指针和指向sockaddr的指针可以相互转换,这意味着如果一个函数所需参数类型是sockaddr时,你可以在函数调用的时候将一个指向 sockaddr_in的指针转换为指向sockaddr的指针;或者相反。sin_family通常被赋AF_INET;sin_port和 sin_addr应该转换成为网络字节优先顺序;而sin_addr则不需要转换。
我们下面讨论几个字节顺序转换函数:
htons()--"Host to Network Short" ; htonl()--"Host to Network Long"
ntohs()--"Network to Host Short" ; ntohl()--"Network to Host Long"
在这里, h表示"host" ,n表示"network",s 表示"short",l表示 "long"。
打开socket 描述符、建立绑定并建立连接
socket函数原型为:
int socket(int domain, int type, int protocol);
domain参数指定socket的类型:SOCK_STREAM 或SOCK_DGRAM;protocol通常赋值“0”。Socket()调用返回一个整型socket描述符,你可以在后面的调用使用它。
一旦通过socket调用返回一个socket描述符,你应该将该socket与你本机上的一个端口相关联(往往当你在设计服务器端程序时需要调用该函数。随后你就可以在该端口监听服务请求;而客户端一般无须调用该函数)。 Bind函数原型为:
int bind(int sockfd,struct sockaddr *my_addr, int addrlen);
Sockfd是一个socket描述符,my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针;addrlen常被设置为sizeof(struct sockaddr)。
最后,对于bind 函数要说明的一点是,你可以用下面的赋值实现自动获得本机IP地址和随机获取一个没有被占用的端口号:
my_addr.sin_port = 0; /* 系统随机选择一个未被使用的端口号 */
my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本机IP地址 */
通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。同样,通过将 my_addr.sin_addr.s_addr置为INADDR_ANY,系统会自动填入本机IP地址。Bind()函数在成功被调用时返回0;遇到错误时返回“-1”并将errno置为相应的错误号。另外要注意的是,当调用函数时,一般不要将端口号置为小于1024的值,因为1~1024是保留端口号,你可以使用大于1024中任何一个没有被占用的端口号。
Connect()函数用来与远端服务器建立一个TCP连接,其函数原型为:
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
Sockfd是目的服务器的sockt描述符;serv_addr是包含目的机IP地址和端口号的指针。遇到错误时返回-1,并且errno中包含相应的错误码。进行客户端程序设计无须调用bind(),因为这种情况下只需知道目的机器的IP地址,而客户通过哪个端口与服务器建立连接并不需要关心,内核会自动选择一个未被占用的端口供客户端来使用。
Listen()——监听是否有服务请求
在服务器端程序中,当socket与某一端口捆绑以后,就需要监听该端口,以便对到达的服务请求加以处理。
int listen(int sockfd, int backlog);
Sockfd是Socket系统调用返回的socket 描述符;backlog指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待accept()它们(参考下文)。Backlog对队列中等待服务的请求的数目进行了限制,大多数系统缺省值为20。当listen遇到错误时返回-1,errno被置为相应的错误码。
故服务器端程序通常按下列顺序进行函数调用:
socket(); bind(); listen(); /* accept() goes here */
accept()——连接端口的服务请求。
当某个客户端试图与服务器监听的端口连接时,该连接请求将排队等待服务器accept()它。通过调用accept()函数为其建立一个连接,accept()函数将返回一个新的socket描述符,来供这个新连接来使用。而服务器可以继续在以前的那个 socket上监听,同时可以在新的socket描述符上进行数据send()(发送)和recv()(接收)操作:
int accept(int sockfd, void *addr, int *addrlen);
sockfd是被监听的socket描述符,addr通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息(某台主机从某个端口发出该请求);addrten通常为一个指向值为sizeof(struct sockaddr_in)的整型指针变量。错误发生时返回一个-1并且设置相应的errno值。
Send()和recv()——数据传输
这两个函数是用于面向连接的socket上进行数据传输。
Send()函数原型为:
int send(int sockfd, const void *msg, int len, int flags);
Sockfd是你想用来传输数据的socket描述符,msg是一个指向要发送数据的指针。
Len是以字节为单位的数据的长度。flags一般情况下置为0(关于该参数的用法可参照man手册)。
char *msg = "Beej was here!"; int len, bytes_sent; ... ...
len = strlen(msg); bytes_sent = send(sockfd, msg,len,0); ... ...
Send()函数返回实际上发送出的字节数,可能会少于你希望发送的数据。所以需要对send()的返回值进行测量。当send()返回值与len不匹配时,应该对这种情况进行处理。
recv()函数原型为:
int recv(int sockfd,void *buf,int len,unsigned int flags);
Sockfd是接受数据的socket描述符;buf 是存放接收数据的缓冲区;len是缓冲的长度。Flags也被置为0。Recv()返回实际上接收的字节数,或当出现错误时,返回-1并置相应的errno值。
Sendto()和recvfrom()——利用数据报方式进行数据传输
在无连接的数据报socket方式下,由于本地socket并没有与远端机器建立连接,所以在发送数据时应指明目的地址,sendto()函数原型为:
int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen);
该函数比send()函数多了两个参数,to表示目地机的IP地址和端口号信息,而tolen常常被赋值为sizeof (struct sockaddr)。Sendto 函数也返回实际发送的数据字节长度或在出现发送错误时返回-1。
Recvfrom()函数原型为:
int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);
from是一个struct sockaddr类型的变量,该变量保存源机的IP地址及端口号。fromlen常置为sizeof (struct sockaddr)。当recvfrom()返回时,fromlen包含实际存入from中的数据字节数。Recvfrom()函数返回接收到的字节数或当出现错误时返回-1,并置相应的errno。
应注意的一点是,当你对于数据报socket调用了connect()函数时,你也可以利用send()和recv()进行数据传输,但该socket仍然是数据报socket,并且利用传输层的UDP服务。但在发送或接收数据报时,内核会自动为之加上目地和源地址信息。
Close()和shutdown()——结束数据传输
当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作:close(sockfd);
你也可以调用shutdown()函数来关闭该socket。该函数允许你只停止在某个方向上的数据传输,而一个方向上的数据传输继续进行。如你可以关闭某socket的写操作而允许继续在该socket上接受数据,直至读入所有数据。
int shutdown(int sockfd,int how);
Sockfd的含义是显而易见的,而参数 how可以设为下列值:
·0-------不允许继续接收数据
·1-------不允许继续发送数据
·2-------不允许继续发送和接收数据,均为允许则调用close ()
shutdown在操作成功时返回0,在出现错误时返回-1(并置相应errno)。
DNS——域名服务相关函数
由于IP地址难以记忆和读写,所以为了读写记忆方便,人们常常用域名来表示主机,这就需要进行域名和IP地址的转换。函数gethostbyname()就是完成这种转换的,函数原型为:
struct hostent *gethostbyname(const char *name);
函数返回一种名为hosten的结构类型,它的定义如下:
struct hostent {
char *h_name; /* 主机的官方域名 */
char **h_aliases; /* 一个以NULL结尾的主机别名数组 */
int h_addrtype; /* 返回的地址类型,在Internet环境下为AF-INET */
int h_length; /*地址的字节长度 */
char **h_addr_list; /* 一个以0结尾的数组,包含该主机的所有地址*/
};
#define h_addr h_addr_list[0] /*在h-addr-list中的第一个地址*/
2、将主机的unsigned long值转换为网络字节顺序(32位):为什么要这样做呢?因为不同的计算机使用不同的字节顺序存储数据。因此任何从Winsock函数对IP地址和端口号的引用和传给Winsock函数的IP地址和端口号均时按照网络顺序组织的。
&<60;&<60;&<60;&<60;&<60; u_long&<60; htonl(u_long hostlong);
&<60;&<60;&<60;&<60;&<60; 举例:htonl(0)=0
&<60;&<60;&<60;&<60;&<60; htonl(80)= 1342177280
3、将unsigned long数从网络字节顺序转换位主机字节顺序,是上面函数的逆函数。&<60;&<60;&<60;&<60;&<60;&<60; u_long&<60; ntohl(u_long netlong);
&<60;&<60;&<60;&<60;&<60; 举例:ntohl(0)=0
&<60;&<60;&<60;&<60;&<60; ntohl(1342177280)= 80
1342177280 = 80*256*256*256
4、将主机的unsigned short值转换为网络字节顺序(16位):原因同2:&<60;&<60;&<60;&<60;&<60;&<60; u_short&<60; htons(u_short hostshort);
&<60;&<60;&<60;&<60;&<60; 举例:htonl(0)=0
&<60;&<60;&<60;&<60;&<60; htonl(80)= 20480
5、将unsigned short数从网络字节顺序转换位主机字节顺序,是上面函数的逆函数。&<60;&<60;&<60;&<60;&<60;&<60; u_short&<60; ntohs(u_short netshort);
&<60;&<60;&<60;&<60;&<60; 举例:ntohs(0)=0
&<60;&<60;&<60;&<60;&<60; ntohsl(20480)= 80
20480 = 8-*256 (大小端地址转换)
****
不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机序
最常见的有两种
1. Little endian:将低序字节存储在起始地址
2. Big endian:将高序字节存储在起始地址
LE little-endian
最符合人的思维的字节序
地址低位存储值的低位
地址高位存储值的高位
怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说
低位值小,就应该放在内存地址小的地方,也即内存地址低位
反之,高位值就应该放在内存地址大的地方,也即内存地址高位
BE big-endian
最直观的字节序
地址低位存储值的高位
地址高位存储值的低位
为什么说直观,不要考虑对应关系
只需要把内存地址从左到右按照由低到高的顺序写出
把值按照通常的高位到低位的顺序写出
两者对照,一个字节一个字节的填充进去
⑼ 用photoshop储存tif图片格式里面的,图像压缩,像素顺序,字节顺序,图层压缩他们都是什么意思
另存的时候,把所有图层都合并了。然后在保存。
⑽ 计算机硬件为什么要区分字节序
一、字节序定义
字节序,顾名思义字节的顺序,再多说两句就是大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。
其实大部分人在实际的开发中都很少会直接和字节序打交道。唯有在跨平台以及网络程序中字节序才是一个应该被考虑的问题。
在所有的介绍字节序的文章中都会提到字节序分为两类:Big-Endian和Little-Endian。引用标准的Big-Endian和Little-Endian的定义如下:
a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
c) 网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。比如,以太网头部中2字节的“以太网帧类型”,表示后面数据的类型。对于ARP请求或应答的以太网帧类型来说,在网络传输时,发送的顺序是0x08,0x06。在内存中的映象如下图所示:
栈底 (高地址)
---------------
0x06 -- 低位
0x08 -- 高位
---------------
栈顶 (低地址)
该字段的值为0x0806。按照大端方式存放在内存中。
二、高/低地址与高低字节
首先我们要知道我们C程序映像中内存的空间布局情况:在《C专家编程》中或者《Unix环境高级编程》中有关于内存空间布局情况的说明,大致如下图:
----------------------- 最高内存地址 0xffffffff
| 栈底
.
. 栈
.
栈顶
-----------------------
|
|
|/
NULL (空洞)
/|
|
|
-----------------------
堆
-----------------------
未初始化的数据
----------------(统称数据段)
初始化的数据
-----------------------
正文段(代码段)
----------------------- 最低内存地址 0x00000000
以上图为例如果我们在栈上分配一个unsigned char buf[4],那么这个数组变量在栈上是如何布局的呢[注1]?看下图:
栈底 (高地址)
----------
buf[3]
buf[2]
buf[1]
buf[0]
----------
栈顶 (低地址)
现在我们弄清了高低地址,接着来弄清高/低字节,如果我们有一个32位无符号整型0x12345678(呵呵,恰好是把上面的那4个字节buf看成一个整型),那么高位是什么,低位又是什么呢?其实很简单。在十进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。就拿0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78。
高低地址和高低字节都弄清了。我们再来回顾一下Big-Endian和Little-Endian的定义,并用图示说明两种字节序:
以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
Big-Endian: 低地址存放高位,如下图:
栈底 (高地址)
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
栈顶 (低地址)
Little-Endian: 低地址存放低位,如下图:
栈底 (高地址)
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
---------------
栈顶 (低地址)
在现有的平台上Intel的X86采用的是Little-Endian,而像Sun的SPARC采用的就是Big-Endian。