0x12 | 0x34 | 0x56 | 0x78
低地址------------->高地址
0x78 | 0x56 | 0x34 | 0x12
高地址
-----------
buf[3] (0x78) ->低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) ->高位
-----------
低地址
高地址
-----------
buf[3] (0x12) ->低位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) ->高位
-----------
低地址
先看下面的代码,然后我在简短的解释一下。
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <string>#define nmemb 7/****************************************************Date types(Compiler specific) 数据类型(和编译器相关)
*****************************************************/typedef unsigned char uint8 /* Unsigned 8 bit quantity */typedef signed char int8 /* Signed 8 bit quantity */typedef unsigned short uint16 /* Unsigned 16 bit quantity */typedef signed short int16 /* Signed 16 bit quantity */typedef unsigned int uint32 /* Unsigned 32 bit quantity */typedef signed int int32 /* Signed 32 bit quantity */typedef float fp32 /* Single precision */
/* floating point */typedef double fp64 /* Double precision */
/* floating point *///int32#define BigtoLittle32(A) ((( (uint32)(A) &0xff000000 ) >>24) | \
(( (uint32)(A) &0x00ff0000 ) >>8) | \
(( (uint32)(A) &0x0000ff00 ) <<8) | \
(( (uint32)(A) &0x000000ff ) <<24))//int16#define BigtoLittle16(A) (( ((uint16)(A) &0xff00) >>8 ) | \
(( (uint16)(A) &0x00ff ) <<8))/************************************************************
* Conversion little endian float data to big endian
* *************************************************************/float ReverseFloat(const float inFloat)
{ float retVal char *floatToConvert = (char*) &inFloat char *returnFloat = (char*) &retVal // swap the bytes into a temporary buffer
returnFloat[0] = floatToConvert[3]
returnFloat[1] = floatToConvert[2]
returnFloat[2] = floatToConvert[1]
returnFloat[3] = floatToConvert[0] return retVal
}struct matrix
{ int row int column
}s[nmemb]void set_s(int j, int x, int y)
{
s[j].row = x
s[j].column = y
}bool is_bigendian()
{ int a = 0x1234 char b = *(char *)&a //b == the Low address part of a
//printf("%c\n", b)
if (b == 0x34) { return false
} return true
}int main()
{ if (is_bigendian()) { printf("BigEndian\n")
} else { printf("LittleEndian\n")
}
FILE *fp
set_s(0, 1, 50)
set_s(1, 1, 80)
set_s(2, 4, 20)
set_s(3, 50, 1)
set_s(4, 80, 2)
set_s(5, 100, 3)
set_s(6, 100, 4) int ans = sizeof(struct matrix) printf("size: %d\n", ans) printf("size: %d\n", sizeof(s)) if ((fp = fopen("test", "wb")) == NULL) { printf("EROOR\n") return 1
} for (int j = 0j <nmemb++j) { printf("row: %d column: %d\n", s[j].row, s[j].column)
}
fwrite(s, sizeof(struct matrix), nmemb, fp) for (int i = 0i <nmemb++i) { float *m = (float*) malloc(sizeof(float) * s[i].row * s[i].column)
bzero(m, sizeof(float) * s[i].row * s[i].column) for (int j = 0j <s[i].row++j) { for (int k = 0k <s[i].column++k) {
m[k + j*s[i].column] = k
}
}
fwrite(m, sizeof(float), s[i].row * s[i].column, fp) free(m)
}
fclose(fp) printf("11\n") /*
printf("%d\n", sizeof(float))
FILE *fp
if ((fp = fopen("test", "rb")) == NULL) {
printf("EROOR\n")
return 1
}
fread(s, sizeof(struct matrix), nmemb, fp)
for (int i = 0i <nmemb++i) {
printf("row: %d column: %d\n", s[i].row, s[i].column)
}
for (int i = 0i <nmemb++i) {
float *m = (float*) malloc(sizeof(float) * s[i].row * s[i].column)
bzero(m, sizeof(float) * s[i].row * s[i].column)
fread(m, sizeof(float), s[i].row * s[i].column, fp)
for (int j = 0j <s[i].row++j) {
for (int k = 0k <s[i].column++k) {
printf("%lf ", m[k + j*s[i].column])
}
printf("\n")
}
printf("\n\n")
free(m)
}
fclose(fp)
*/
return 0
}
fopen和fclose是很常见的,在这里就不做解释了。我们来看看fwrite和fread,本来以为这个很麻烦,但是用过之后发现这个二进制文件读写才是最简单的。
size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream)
fwrite()用来将数据写入文件流中。
stream为已打开的文件指针
ptr 指向欲写入的数据地址
写入的字符数以参数size*nmemb来决定。
size表示写入一个nmemb的内存大小。
fwrite()会返回实际写入的nmemb数目。
size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)
fread()用来从文件流中读取数据。
stream为已打开的文件指针
ptr 指向欲存放读取进来的数据空间
读取的字符数以参数size*nmemb来决定
size表示读取一个nmemb的内存大小。
fread()会返回实际读取到的nmemb数目,如果此值比参数nmemb 小,则代表可能读到了文件尾或有错误发生,这时必须用feof()或ferror()来决定发生什么情况。
返回实际读取到的nmemb数目。
详情参见上面的代码。
另外就是大小端的问题了。关于大小端的具体解释网上有很多,在此不作解释。参考上面写的代码,我判断了自己机器是大端还是小端,并且实现了int16,int32已经float数据类型的大小端转换,大端转小端,在使用相同的代码一次小端又变成了大端。
PS:float的大小端转化我之前一直以为写的是错的,因为好多数据转化之后输出都是0。后来发现可能是与float类型在内存中的存放有关,我们的程序是对的。
在计算机系统中,存储是以字节为单位的,每个地址单元都对应着一个字节,一个字节=8bit。在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器)。对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,如何安排多个字节的存储,这就有了大端存储模式和小端存储模式。
小端:较高的有效字节存放在较高的的存储器地址,较低的有效字节存放在较低的存储器地址。
大端:较高的有效字节存放在较低的存储器地址,较低的有效字节存放在较高的存储器地址。
如果将一个16位的整数0x1234存放到一个短整型变量(short)中。这个短整型变量在内存中的存储在大小端模式由下表所示。
C语言判断大小端模式
方法一:
voidIsBigEndian()
{
shortinta=0x1122//十六进制,一个数值占4位charb = *(char*)&a//通过将short(2字节)强制类型转换成char单字节,b指向a的起始字节(低字节)
if( b ==0x11) //低字节存的是数据的高字节数据
{
//是大端模式
}
else
{
//是小端模式
}
}
方法二:
voidIsBigEndian() //原理:联合体union的存放顺序是所有成员都从低地址开始存放,而且所有成员共享存储空间
{
uniontemp
{
shortint a
char b
}temp
temp.a=0x1234
if(temp.b==0x12) //低字节存的是数据的高字节数据
{
//是大端模式
}
else
{
//是小端模式
}
}
参考:https://www.jianshu.com/p/152268b0ea19