c語言判斷大小端
『壹』 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;}//設置'