当前位置:首页 » 编程语言 » c语言判断大小端

c语言判断大小端

发布时间: 2022-06-06 08:23:33

‘壹’ C语言读写二进制文件读取 大小端,该怎么解决

1、二进制文本使用fopen函数的二进制模式“rb”就可以打开。对于程序来说,不管后缀名如何,文件分为两种类型:文本文件和二进制文件。 C语言里有一系列文件操作函数。区分文本和二进制文件,需要在打开文件时设置不同的控制符mode的变量即可。

‘贰’ C语言读写二进制文件读取 大小端,该怎么解

先看下面的代码,然后我在简短的解释一下。

#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 ", b);
if (b == 0x34) { return false;
} return true;
}int main()
{ if (is_bigendian()) { printf("BigEndian ");
} else { printf("LittleEndian ");
}

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 ", ans); printf("size: %d ", sizeof(s)); if ((fp = fopen("test", "wb")) == NULL) { printf("EROOR "); return 1;
} for (int j = 0; j < nmemb; ++j) { printf("row: %d column: %d ", s[j].row, s[j].column);
}
fwrite(s, sizeof(struct matrix), nmemb, fp); for (int i = 0; i < 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 = 0; j < s[i].row; ++j) { for (int k = 0; k < 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 "); /*
printf("%d ", sizeof(float));
FILE *fp;
if ((fp = fopen("test", "rb")) == NULL) {
printf("EROOR ");
return 1;
}
fread(s, sizeof(struct matrix), nmemb, fp);
for (int i = 0; i < nmemb; ++i) {
printf("row: %d column: %d ", s[i].row, s[i].column);
}

for (int i = 0; i < 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 = 0; j < s[i].row; ++j) {
for (int k = 0; k < s[i].column; ++k) {
printf("%lf ", m[k + j*s[i].column]);
}
printf(" ");
}
printf(" ");
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类型在内存中的存放有关,我们的程序是对的。

‘叁’ 大小端模式的判断处理器

通过下列的程序可以确认在某个硬件平台上的某个操作系统是大端还是小端:
VB6: '注意这个CopyMemory的声明与一般的不一样,'一般的都是(pDstAsAny,pSrcAsAny,ByValByteLenAsLong)'为了能够逐字节访问u,所以前面两个参数改成了按值传递,配合VarPtr函数获取变量地址_RtlMoveMemory(ByValpDstAsLong,ByValpSrcAsLong,ByValByteLenAsLong)PrivateSubForm_Load()'VB的Integer占用2个字节!Long才是4个字节'32位应用程序的指针是4个字节sLong'储存u从低地址到高地址的4个字节=367328153'十六进制数:15E4FB99uptr=VarPtr(u)'VarPtr函数是内置函数,但是msdn不说,作用是获取变量的地址aptr=VarPtr(a)bptr=VarPtr(b)cptr=VarPtr(c)dptr=VarPtr(d)CopyMemoryaptr,uptr+0,1'将u逐字节按顺序写入a,b,c,dCopyMemorybptr,uptr+1,1CopyMemorycptr,uptr+2,1CopyMemorydptr,uptr+3,1'Windows系统,英特尔处理器:最后输出的是99FBE415MsgBoxHex(a)&&Hex(b)&&Hex(c)&&Hex(d)EndSub在英特尔处理器,Windows10操作系统上,对话框显示的结果是99 FB E4 15,与直接求出来的16进制值15 E4 FB 99正好相反,所以是小端的。
C++语言(VS2013下,控制台项目): #include<iostream>usingnamespacestd;typedefunsignedcharbyte;//转换char(视为整数类型)为16进制字符串voidChtoHex(byteVal,char*dest){//辗转相除法,倒序看得到结果bytetmp=Val%16;if(tmp>=0&&tmp<=9){dest[1]='0'+tmp;}elseif(tmp>=10&&tmp<=15){dest[1]='A'+tmp-10;}tmp=(Val/16)%16;if(tmp>=0&&tmp<=9){dest[0]='0'+tmp;}elseif(tmp>=10&&tmp<=15){dest[0]='A'+tmp-10;}//设置''dest[2]='';}//主函数intmain(){intu=367328153;//原始数据,8位16进制为15E4FB99bytea,b,c,d;//u从低地址到高地址的四个字节//a~d对应的16进制字符串,预留3个字符charSa[3],Sb[3],Sc[3],Sd[3];byte*k=(byte*)&u;a=k[0];b=k[1];c=k[2];d=k[3];//转成16进制字符串ChtoHex(a,Sa);ChtoHex(b,Sb);ChtoHex(c,Sc);ChtoHex(d,Sd);cout<<Sa<<<<Sb<<<<Sc<<<<Sd<<endl;system(pause);return0;}在英特尔处理器,Windows10操作系统上,控制台显示的结果是99 FB E4 15,与直接求出来的16进制值15 E4 FB 99正好相反,所以也证明是小端的。
C语言(VC++6.0,控制台工程): #include<stdio.h>typedefunsignedcharbyte;//转换char(视为整数类型)为16进制字符串voidChtoHex(byteVal,char*dest){//辗转相除法,倒序看得到结果bytetmp=Val%16;if(tmp>=0&&tmp<=9){dest[1]='0'+tmp;}elseif(tmp>=10&&tmp<=15){dest[1]='A'+tmp-10;}tmp=(Val/16)%16;if(tmp>=0&&tmp<=9){dest[0]='0'+tmp;}elseif(tmp>=10&&tmp<=15){dest[0]='A'+tmp-10;}//设置dest[2]='';}//主函数voidmain(){intu=367328153;//原始数据,8位16进制为15E4FB99bytea,b,c,d;//u从低地址到高地址的四个字节//a~d对应的16进制字符串,预留3个字符charSa[3],Sb[3],Sc[3],Sd[3];byte*k=(byte*)&u;a=k[0];b=k[1];c=k[2];d=k[3];//转成16进制字符串ChtoHex(a,Sa);ChtoHex(b,Sb);ChtoHex(c,Sc);ChtoHex(d,Sd);printf(%s%s%s%s ,Sa,Sb,Sc,Sd);scanf_s(%d,&a);}在英特尔处理器,Windows10操作系统上,结果跟上面是一样的,输出的16进制数是反序的,证明是小端系统。
C#(VS2013下,控制台项目): usingSystem;namespaceConsoleApplication1{classProgram{staticvoidMain(string[]args){intu=367328153;//原始数据,8位16进制为15E4FB99byte[]bytes;//u从低地址到高地址的四个字节//获取bytes=System.BitConverter.GetBytes(u);Console.WriteLine(bytes[0].ToString(X)++bytes[1].ToString(X)++bytes[2].ToString(X)++bytes[3].ToString(X));Console.ReadLine();}}}在英特尔处理器,Windows10操作系统上,结果跟上面还还是一样的,输出的16进制数是反序的,证明是小端系统。
MDK(Keil5,STM32F407)C语言: #includestm32f4xx.hintmain(void){intu=367328153;//原始数据15E4FB99int*k=&u;return0;}编译连接然后下载到开发板上,然后启动调试,通过监视窗口可以看到u的地址,然后在内存窗口可以看到字节序是反序的,所以说明STM32F407是小端的。据某些资料说ARM内核是可以设置大小端的,但是STM32是外设自动进入了小端,似乎是无法调整的。

89C52(Keil5)C语言:
最后来一个大端的例子。手头上没有51的开发板,所以用的是软件仿真。 #include<reg52.h>intmain(){intlongbit=sizeof(long);longu=367328153;//原始数据15E4FB99long*k=&u;return0;}注意看了,C52是8位的处理器,long才是4个字节的,看监视窗口longbit的值就知道了(紫色框)。然后再看内存窗口,就会发现u的存储是跟原始数据给的顺序是一样的,所以C51和C52是大端的!!

‘肆’ C语言中使用union是怎么判断处理器大小端的

union Charge

{
char arr[2];
short num;
};
int main()
{

union Charge charge;
charge.arr[0] = 1;
charge.arr[1] = 2;

if (charge.num == 0x0201)
{
printf("小端\n");

}
else
{
printf("大端\n");

}

return 0;
}

‘伍’ 如何确定大小端

什么大小端啊?是一根木杆的大小端吗?放到水中,沉下去多的就是根部(大端)

热点内容
sql2012导入数据 发布:2025-02-08 19:09:07 浏览:286
java位与运算 发布:2025-02-08 18:48:22 浏览:217
sift算法详解 发布:2025-02-08 18:35:23 浏览:580
linux标准错误的是 发布:2025-02-08 18:32:07 浏览:916
蛮多小说怎么缓存书架的小说 发布:2025-02-08 18:30:16 浏览:889
光遇花开脚本封号吗 发布:2025-02-08 18:23:15 浏览:535
怎么弄ld帐号和密码 发布:2025-02-08 18:11:42 浏览:629
新逍客20发动机压缩比 发布:2025-02-08 17:58:10 浏览:116
qq号和密码我都知道为什么登不上 发布:2025-02-08 17:52:21 浏览:873
宝塔服务器ip进不去 发布:2025-02-08 17:52:18 浏览:383