遭遇位元組對齊的問題。

來源:互聯網
上載者:User

#include <vcl.h>
#pragma hdrstop
#include<stdio.h>
#include "Unit1.h"
#include"File1.h"

struct BITMAPFILEHEADER_
{

short type;
int bfSize;
short re1,re2;
int Offbits;
};

struct BITMAPINFO_
{
long size;
long width,height;
short planes,bitCount;
long comp,sizeImg;
long xpels,ypels;
long used,important;
};

struct COLORTABLE_
{
char blue,green,red,res;
};

void xxx()
{
FILE *f=fopen("F://projects//bmp//1.bmp","rb");
if(f==NULL) /*判斷檔案是否開啟成功*/
{
ShowMessage("File open error");
return;
}
fseek(f,0,0);
BITMAPFILEHEADER_ *bmph=new BITMAPFILEHEADER_();
if(fgets((char*)bmph,sizeof(BITMAPFILEHEADER_),f)==NULL)
{
ShowMessage("File read error");
return;
}

BITMAPINFO_ *bmpi=new BITMAPINFO_();
if(fgets((char*)bmpi,sizeof(BITMAPINFO_),f)==NULL)
{
ShowMessage("File read error2");
return;
}

Form1->Edit1->Text=IntToStr(bmph->bfSize);
Form1->Edit2->Text=IntToStr(bmpi->width);
Form1->Edit3->Text=IntToStr(bmpi->height);

fclose(f);
};

 

這是一個用BCB寫的普通的讀取BMP檔案頭資訊的簡單程式,但工作不正常。

顯示結果

Edit1:0

Edit2:1073741824

Edit3:16777216

苦思冥想解釋不了,用Ultra edit開啟BMP檔案發現檔案開頭是

42 4D 38 14 00 00 00 00 00 00 36 04 00 00 28 00

檔案是沒錯的,42 4D是BMP檔案標誌“BM”,接下來38 14 00 00 是檔案大小,INT值是0X1438=5176位元組,和WINDOWS顯示的一樣,沒錯。

後來寫了個程式讀出第一個自己‘B’和第2個位元組‘M’卻時正確的,就時到讀size時會變成0,只能懷疑是BITMAPFILEHEADER_結構匹配資料時出了問題,為了進一步驗證,寫了另一個程式自己填充BMP檔案頭,寫入磁碟,再用Ultra edit查看,程式碼是這樣的。

#pragma argsused

#include<stdio.h>

#include<stdlib.h>

struct BITMAPFILEHEADER_
{

short type;
int bfSize;
short re1,re2;
int Offbits;
};

int main(int argc, char* argv[])
{
FILE *f=fopen( "f://abc.txt","wb");
BITMAPFILEHEADER_ *b=new BITMAPFILEHEADER_();
b->type=1;
b->bfSize=1;
b->re1=b->re2=1;
b->Offbits=1;

if(f==NULL)
{
printf("xxx");
system("pause");
return 0;
}

fwrite( b,sizeof(BITMAPFILEHEADER_),1,f);
system("pause");
return 0;
}

 

用Ultra Edit 查看發現居然寫了 16 個位元組,如下

01 00 67 32 01 00 00 00 01 00 01 00 01 00 00 00

寫了 type 後無緣無故多了個 67 32,後面的又沒問題,突然想起論壇上有討論過C語言的位元組對齊問題,就懷疑是位元組對齊的問題,到網上找BCB位元組對齊的指令,原來BCB預設是4位元組對齊,用#pragma pack(1)可以把位元組對齊設定到1位元組。

加上#pragma pack(1),讀出的資料就正確了。

奔騰機器是32位系統,資料匯流排寬度32位,CPU一次從記憶體傳送4位元組的資料,為了取一個資料時能把訪問儲存空間的減到最少,編譯器預設結構類型的資料以4位元組對齊,這樣讀取上面那個BITMAPFILEHEADER_結構需要4次訪問記憶體(16位元組每次讀4位元組),跟在這個結構後面的資料也在記憶體中對齊了,如果後面再跟著一個BITMAPFILEHEADER_結構,那麼讀取後面那個BITMAPFILEHEADER_也只需要4次訪問記憶體,如果用#pragma pack(1)強制1位元組對齊後,訪問第一個BITMAPFILEHEADER_時仍然時4次訪問記憶體,但訪問後面緊接著的那個BITMAPFILEHEADER_時就需要5次訪問記憶體,而且再後面接著的資料也對不齊了。

雖然出於效能的考慮編譯器預設4位元組對齊,但有時使用者使用者有有自己的需要不對齊,就像上面那種情況,這時就要用IDE指令#pragma pack(1)強制不對齊了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.