2010-07-06 41 views
1

在C中的字節數組和整數之間複製數據的最佳方式是什麼?目前我正在使用memcpy,這對我來說並不合適。下面是我正在做的事情的一個例子。在字節數組和無符號長整數之間複製

struct alpha { 
     unsigned char byte_array[20]; 
} 

void function(struct alpha *st) { 
     unsigned long num; 

     /* Do some stuff */ 

     memcpy(st->byte_array, &num, sizeof(unsigned long)); 

     /* Do more stuff */ 

     memcpy(&num, st->byte_array, sizeof(unsigned long)); 
} 

我想我想用蒙上莫名其妙,但我不確信如何鑄造和指針(DE)引用進行交互,尤其是當陣列涉足的。

回答

6

memcpy是這種效果的標準和便攜式工具。現代優化的編譯器將內聯這個調用以適應您的情況,例如數據類型,整型,大小(如果在編譯時已知),處理器......所以我認爲你應該明確地堅持這一點,而不是亂搞一些手工優化。

+0

這是100%正確的。 – caf 2010-07-07 09:56:01

+0

但是爲什麼'char [20]'?爲什麼不'char [8]'?即您不復制數字,您正在複製這些位。 – Mazyod 2013-05-22 04:51:41

+1

@Mazyod,問題中的原始代碼只是示例代碼,如果您要正確執行此操作,則可能會使用'unsigned char [sizeof(long)]'。 – 2013-05-22 06:15:28

1

它看起來完全正確的方式給我。也就是說,當我不得不這樣做時,這是我做到的。

+0

+1您的「正確方式」的定義。 – JeremyP 2010-07-06 16:14:25

0

memcpy是做這種事最安全的方法。如果速度雖然重要,你可以做一些施展魔法,讓編譯器在本地處理的副本你:


*((unsigned long *)&st->byte_array[0]) = num; 

num = *((unsigned long *)&st->byte_array[0]); 

兩者均會使用內置的寄存器類型的副本,而不是4個字節的函數調用。如果你想進一步閱讀byte_array,你必須小心字節對齊問題。

+0

這就像我所期望的那樣,但不是'st-> byte_array [0]'與*(st-> byte_array)'相同,這是一個字節,而不是一個指針? '(unsigned long *)'強制轉換似乎正在爲一個字節(指向一個無符號長整型)指向一個字節,而我以爲我想將一個指向一個字節的指針指向一個無符號長)... – 2010-07-06 14:39:46

+0

當它 - 忘記&符。希望這個地方有一個快速的語法編譯器:) – 2010-07-06 15:58:41

+1

[0]下標不正確。正確的轉換將是將字節數組轉換爲無符號長指針;如果你需要索引k個字節,*((unsigned long *)(st-> byte_array + k))= num; ((unsigned long *)st-> byte_array)[0] = num;如果您需要將k個長字索引到它中, – supercat 2010-07-06 16:26:14

0

這是沒有錯的,除非你知道「誰」將數據寫入數組,寫入的數據與系統中使用的數據不同。比如說,如果這些數據來自「某人」通過網絡發送的「流」。然後,如果協議使用所謂的「網絡字節順序」(即big endian),並且您的機器不是大端,那麼您將獲得錯誤的值。

0

是否有任何特殊原因需要複製而不是僅僅混淆兩者?例如:

聯合XXX {char_byte_array [20]; unsigned long num; };

從理論上講,當您寫入工會的一個成員然後從另一個成員讀取時,您不會得到定義的結果。在現實中,基本上沒有可能獲得與你現在得到的東西不同的東西 - 除了(當然),你不必複製數據從一個視圖到另一個視圖 - 你只需使用x.num來看看在它作爲一個無符號long,並x.byte_array將其視爲一個字節數組。

0

我更喜歡一些默認功能爲這個要求,

字符串到整數

int atoi (const char * str); 

和 整數串

char * itoa (int value, char * str, int base); 


#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
unsigned long int number; 
unsigned char string[256]; 

printf ("Enter a number: "); 
fgets (string, 256, stdin); 
number = atoi (string); 
printf("number = %d\n",number); 

//converting int to string 
itoa (number,string,10); //10 is base here for decimal, 16 is used for Hex and 2 for Binary 
printf ("string = %s\n",string); 

return 0; 
} 

按照我的atoi()函數是罰款。但如果你不想使用itoa(),或者是不提供給你,然後你可以用sprintf()

sprintf (string,"%ld",number); 

我希望它能幫助

感謝 Alok.kr.

+0

atoi和itoa用於將數字轉換爲ASCII表示形式,反之亦然。這與無需轉換複製字節的問題無關。 – JeremyP 2010-07-06 16:16:36

1

下面介紹如何用石膏做:

/* Do some stuff */ 

    *(unsigned long *)st = num; 

    /* Do more stuff */ 

    num = *(unsigned long *)st; 

你鑄造你的結構指針的指針到一個unsigned long,然後解引用在賦值語句的指針。

+0

這似乎假定數組始終是結構中的第一個元素。它在這裏,但這只是一個簡單的例子... – 2010-07-06 16:09:58

+0

@me_and:true。用'st-> byte_array'替換'st'來引用字節數組。 – tomlogic 2010-07-06 16:49:42

+0

糟糕得多,它假定'st-> byte_array'正確對齊作爲'unsigned long'訪問。 – caf 2010-07-07 01:44:34

相關問題