[英]memcpy for copying a fixed length buffer into a structure
我有這個示例代碼:
struct
{
char a[2];
char b[2];
} buff;
char buffer1[5] = "ABCD";
要將buffer1
復制到結構成員,我這樣做:
char c[3],d[3];
memcpy(&buff,buffer1,4);
sprintf(c,"%2.2s",buff.a);
sprintf(d,"%2.2s",buff.b);
printf("c=%s,d=%s",c,d);
當我打印變量c和d時,我正確地將c和d變量中的值變為: c="AB"
和c="CD"
。
好吧,我的問題是,即使我正確地得到輸出, memcpy
會影響與空字符終止相關的任何事情,還是會產生其他與記憶相關的意外后果?
這里有兩個問題:
1)如評論中所述,您可能忘記在結尾'\\0'
(即ASCII中的NUL
)終結符字符中包含空格。 printf
函數的%s
格式說明符期望字符串%s
格式有效。 然而,沒有什么能阻止你打印成字符序列,就像這里:
#include <stdio.h>
#include <string.h>
struct {
char a[2];
char b[2];
} buff;
char buffer1[5] = "ABCD";
int main(void)
{
memcpy(&buff, buffer1, 4);
printf("First member: %c%c\n", buff.a[0], buff.a[1]);
printf("Second member: %c%c\n", buff.b[0], buff.b[1]);
return 0;
}
2)一個更嚴重的問題是編譯器可能在struct成員之間(以及在最后一個成員之后)包含任意填充 ,因此memcpy
可能無法按預期工作。 而不是像那樣復制(因為它可能將數組中的字節放入未使用的“整體”)。 我建議每個成員的個人副本或使用offsetof()
宏。
來自N1570 6.7.2.1/15
結構和聯合說明符 :
結構對象中可能存在未命名的填充,但不是在其開頭。
和6.7.2.1/17
:
結構或聯合的末尾可能有未命名的填充。
因此,您應該將memcpy
分成兩個調用,例如:
memcpy(&buff.a, buffer1, 2); /* or replace 2 with sizeof buff.a */
memcpy(&buff.b, buffer1+2, 2);
buffer1
以null結尾。 但是, buff
的數據成員不是,因為您沒有在它們上附加空終止符。 而且,null終結器沒有空間!
所以,不,它不會影響它,因為它不存在。 當您嘗試使用stdio.h
的函數時,您會得到意外的結果,這些函數期望以null結尾的字符串。
另外,你可能想在這里查看我的例子,關於在一個結構中循環,它有點相關。 我建議你一次復制到一個數據成員,而不是一次復制。
這可能無法按預期工作。 結構中的字段之間可能存在填充字節。 它們插入字段之間,以使下一個字段以某個地址偏移量開始。 這主要是CPU的字大小或總線大小,或者是高速緩存對齊的倍數。
即使對於char []
也是如此,因為這將允許使用單詞傳輸有效地移動/復制這樣的數組。
對於其他類型,填充很可能,另外你必須關心endianess。
還要記住, memcpy
和朋友完全按照他們的名字所暗示的做法:他們在一塊內存上運行。 他們不關心字符串,他們對“字符串”沒有任何想法。 插入任何NUL字節會使它們無用,所以它們不會。
請注意,此方法類似於轉換不兼容的指針類型。 你很安全的地方很少,但大多數時候這是通往地獄的道路(又名未定義的行為 )。
#include<stdio.h>
#include<string.h>
struct
{
char a[2];
char b[2];
}buff;
int main ( void )
{
char buffer1[4] = "ABCD";
memcpy ( &buff , buffer1 , 4 );
printf ( "\n%s\n ", buff.a );
printf ( "\n%s\n ", buff.b );
return ( 0 );
}
o/p-->
rabi@rabi-VirtualBox:~/rabi/c$ gcc 16.c
rabi@rabi-VirtualBox:~/rabi/c$ ./a.out
ABCD
CD
rabi@rabi-VirtualBox:~/rabi/c$
#include<stdio.h>
#include<string.h>
struct
{
char a[3];
char b[3];
}buff;
int main ( void )
{
char buffer1[4] = "ABCD";
memcpy ( &buff.a , &buffer1[0], 2 );
buff.a[2]='\0';
memcpy ( &buff.b , &buffer1[2], 2 );
buff.b[2]='\0';
printf ( "\n%s\n ", buff.a );
printf ( "\n%s\n ", buff.b );
return ( 0 );
}
o/p--->
rabi@rabi-VirtualBox:~/rabi/c$ gcc 15.c
rabi@rabi-VirtualBox:~/rabi/c$ ./a.out
AB
CD
rabi@rabi-VirtualBox:~/rabi/c$
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.