Cにおけるstruct構造体の動的mallocとmemcpyのポインタ操作について
今日問題が発生しました.まずコードを貼ります.
出力結果:
では、これはなぜですか.まずアドレスを見てみましょう.構造体の最初のアドレスは0 x 28 f 1 ee 8で、0 x 28 f 1 eebで3バイト差があります.つまり、構造体の総サイズは6ですが、bySignatureのサイズは3バイトです.なぜ印刷されたのは[GIF 89 a]です.これは6バイトではありませんか.
元は1人で、memcpyは6バイトの空間の大きさのデータを構造体にコピーして、つまり構造体の6バイトのデータはすべてデータを充填して、1つの重要な標準があって私達は忘れることができなくて、配列を定義する時、私達は配列の最後の1つのオフセットの位置で1つの’0’を充填して配列の終わりを識別する必要があって、さもなくば配列のポインタを操作する時、オフセットして構造体に戻る可能性があります.構造体は3バイトサイズの2つの配列から構成されています.2つの配列の間に、構造体の最初のパラメータのアドレスが構造体の最初のアドレスであるため、最初の配列が印刷されると、'0'に遭遇したり、構造体の割り当てサイズの最後に終了したりします.それによって上記の状況を引き起こす
解決策:
1.構造体に配列が存在する場合、配列の特殊性を知らなければならないので、memcpyを使用して構造体ブロック全体のmemcpyを話すことはできません.cpyのソースがターゲットの構造とそっくりでない限り、このような状況は起こらないかもしれませんが、個人的には1つのcpyがより安全だと思っています.もちろん、*より良い方法があると思います.今のところ思いもよらなかった.構造体を作成するときは、できるだけ初期化構造体関数を確立し、配列が存在する場合は、配列の実際の大きさに基づいて+1を加え、'0',配列の終了を表す
次は正しいコードです.
結果:
typedef struct Gifheader {
char Signature[3];
char Version[3];
gifheader() {
Signature[2] = '\0';
Version[2] = '\0';
}
}GIFHEADER;
OpenGif()
{
QFile file(qApp->applicationDirPath()+"/gif.gif");
if(!file.open(QIODevice::ReadWrite | QIODevice::Text))
{
return;
}
QByteArray byte = file.readAll();
char* p = byte.data();
struct Gifheader* head = (struct Gifheader*)mallGGoc(sizeof(struct Gifheader));
memset(head,'\0',sizeof(GIFHEADER));
memcpy(head,p,sizeof(struct Gifheader));
qDebug("gif:[%s] version:[%s] phead = [%p] Signature:[%p] Version:[%p]"
,head->Signature,head->Version,head,head->Signature,head->Version);
free(head);
}
出力結果:
gif:[GIF89a] version:[89a] phead:[0x28f1ee8] Signature:[0x28f1ee8] Version:[0x28f1eeb]
では、これはなぜですか.まずアドレスを見てみましょう.構造体の最初のアドレスは0 x 28 f 1 ee 8で、0 x 28 f 1 eebで3バイト差があります.つまり、構造体の総サイズは6ですが、bySignatureのサイズは3バイトです.なぜ印刷されたのは[GIF 89 a]です.これは6バイトではありませんか.
元は1人で、memcpyは6バイトの空間の大きさのデータを構造体にコピーして、つまり構造体の6バイトのデータはすべてデータを充填して、1つの重要な標準があって私達は忘れることができなくて、配列を定義する時、私達は配列の最後の1つのオフセットの位置で1つの’0’を充填して配列の終わりを識別する必要があって、さもなくば配列のポインタを操作する時、オフセットして構造体に戻る可能性があります.構造体は3バイトサイズの2つの配列から構成されています.2つの配列の間に、構造体の最初のパラメータのアドレスが構造体の最初のアドレスであるため、最初の配列が印刷されると、'0'に遭遇したり、構造体の割り当てサイズの最後に終了したりします.それによって上記の状況を引き起こす
解決策:
1.構造体に配列が存在する場合、配列の特殊性を知らなければならないので、memcpyを使用して構造体ブロック全体のmemcpyを話すことはできません.cpyのソースがターゲットの構造とそっくりでない限り、このような状況は起こらないかもしれませんが、個人的には1つのcpyがより安全だと思っています.もちろん、*より良い方法があると思います.今のところ思いもよらなかった.構造体を作成するときは、できるだけ初期化構造体関数を確立し、配列が存在する場合は、配列の実際の大きさに基づいて+1を加え、'0',配列の終了を表す
次は正しいコードです.
typedef struct Gifheader {
char Signature[4];
char Version[4];
gifheader() {
Signature[3] = '\0';
Version[3] = '\0';
}
}GIFHEADER;
void HImageTool::OpenGif()
{
QFile file(qApp->applicationDirPath()+"/gif.gif");
if(!file.open(QIODevice::ReadWrite | QIODevice::Text))
{
return;
}
QByteArray byte = file.readAll();
char* p = byte.data();
GIFHEADER* head = (GIFHEADER*)malloc(sizeof(GIFHEADER));
memset(head,'\0',sizeof(GIFHEADER));
memcpy(head->Signature,p,sizeof(head->Signature)-1);
memcpy(head->Version,p+3,sizeof(head->Signature)-1);
// memcpy(head,p,sizeof(struct gifheader));
qDebug("gif:[%s] version:[%s] phead = [%p] Signature = [%p] Version = [%p]"
,head->Signature,head->Version,head,head->Signature,head->Version);
free(head);
}
結果:
gif:[GIF] version:[89a] phead = [0x2a71ac8] bySignature = [0x2a71ac8] byVersion = [0x2a71acc]