[英]Copying structure in C with assignment instead of memcpy()
直到最近,我才看到用memcpy()
復制結構字段。 在類和在線指令中,將一個結構的內容復制到另一個結構中通常看起來像
struct block *b0 = malloc(sizeof(struct block));
struct block *b1 = malloc(sizeof(struct block));
/* populate fields in *b0 */
memcpy(b1, b0, sizeof *b1); /* copy contents of b0 into b1 */
/* free b0, b1 */
但是,也可以通過替換memcpy()
的簡單賦值來完成此任務。
*b1 = *b0; /* dereferenced struct assignment */
有沒有充分的理由說明為什么它沒有被廣泛使用(至少在我有限的經驗中)? 這兩個方法 - 賦值和memcpy()
等價,還是有一些令人信服的理由一般使用memcpy()
?
兩種方法都是等效的,並執行淺拷貝 。 這意味着復制了結構本身,但不復制結構引用的任何內容。
至於為什么memcpy
更受歡迎,我不確定。 較舊版本的C不支持結構分配( 雖然它早在1978年就是常見的擴展 ),因此memcpy樣式可能會成為制作更多可移植代碼的方式嗎? 在任何情況下,PC編譯器都廣泛支持結構分配,並且使用memcpy
更容易出錯(如果大小錯誤,可能會發生壞事),因此最好盡可能使用結構分配。
但是,只有memcpy
有效。 例如:
memcpy
,因為結構分配需要正確對齊源和目標。 memcpy
,並將此附加信息計入大小字段。 memcpy
可能更有效,而不是單獨循環和復制結構。 然后,它可能不會。 很難說, memcpy
實現的性能特征不同。 還要注意,雖然在C memcpy
和結構賦值中通常是等價的,但在C ++中memcpy
和結構賦值並不等價。 在一般的C ++中,最好避免使用memcpy
結構,因為結構賦值可以並且經常被重載以執行其他操作,例如深層復制或引用計數管理。
這可能不是您尋找的確切答案。
我解釋了我遇到的情景。
當我們使用memcpy()
,它會逐字節地復制到目標。 所以不用擔心ARM架構中的數據對齊。 如果使用=
運算符,並且任何一個地址未與4字節對齊,則會出現對齊錯誤。
來自Arm站點:
指向目標位置的指針,該指針位於寫入的最后一個字節之外一個字節。 這使得寫入過程的繼續with perfect alignment of bytes
用於字符串串聯內存塊with perfect alignment of bytes
。
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0175k/Cihbbjge.html
我正在復活這個老問題,因為答案並沒有解釋為什么 memcpy
實際上是首選。
memcpy
是首選,因為它清楚地表明程序員想要復制內容而不是簡單的指針。
在下面的示例中,兩個賦值有兩個非常不同的東西:
struct Type *s1,*s2;
*s1=*s2;
s1=s2;
無意中使用一個而不是另一個可能會產生災難性的后果。 編譯器不會抱怨。 除非在使用未初始化指針時程序崩潰,否則錯誤很長時間都會被忽視並產生奇怪的副作用。
將其寫成以下之一:
memcpy(s1,s2,sizeof(*s1));
memcpy(s1,s2,sizeof(*s2));
memcpy(s1,s2,sizeof(struct Type));
讓讀者知道目的是復制內容(以類型安全和邊界檢查為代價)。
有些編譯器(例如gcc)甚至會在遇到類似以下內容時發出有關sizeof的警告:
memcpy(s1,s2,sizeof(s1));
有些人更喜歡memcpy,因為這是他們學到的東西,他們從來沒有想過他們可以做一個任務(在古代,不允許任務,但很久以前)。 沒有對齊問題需要擔心,因為malloc()分配的內存總是正確對齊。 而且由於編譯器可以將這個賦值簡單地轉換為memcpy調用,因此它永遠不會比memcpy更慢或更多代碼。 當然,嵌入式系統中存在嚴重過時的編譯器。
在嵌入式平台上工作的人更願意使用memcopy而不是直接分配結構。 主要是當您處理嵌入式平台時,某些編譯器不支持直接結構分配,因為您需要使用memcopy。 如果您正在使用PC,那么在任何一種情況下都沒有問題,兩者都是有效的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.