2016-05-30 49 views
1

char配列にuint8_t配列をコピーします。 私はさまざまなソリューションを試しました:キャスト、memcopy、strcpy ... しかし、それは動作しません!私の小さな例は次のとおりです。uint8_t配列をCの文字配列にコピーする

uint32_t num = 123456789; 
printf("\n num: %"PRIu32 "\n", num); 
uint32_t x; 
uint8_t a[4]; 
char b[4]; 

num=htonl(num); 

a[0]=num; 
a[1]=num>>8; 
a[2]=num>>16; 
a[3]=num>>24; 

b[0] = a[0]; 
b[1] = a[1]; 
b[2] = a[2]; 
b[3] = a[3]; 



printf("\nA: %x %x %x %x", a[0],a[1],a[2],a[3]); 
printf("\nB: %x %x %x %x", b[0],b[1],b[2],b[3]); 


x= b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24; 

x=ntohl(x); 
printf("\n x vale: %"PRIu32 "\n", x); 
} 

プリントは、次のとおりです。

num: 123456789 
A: 7 5b cd 15 
B: 7 5b ffffffcd 15 
x: 123457023 

私はXにdifferente番号を取得するのはなぜ?

+0

['CHAR_BIT'](http://en.cppreference.com/w/c/types/limits#Limits_of_integer_types)が8(' char'が8ビットであることを意味する)であれば、 'memcpy'呼び出し? –

+0

文字が署名されています。気にかけておいて。 @EugeneSh。 –

+1

'char'に署名することができます。または署名されていない。それは実装までです。 –

答えて

0

signed int値オーバーフローのような未定義の動作を確実に処理するには、コードを少し修正する必要があります。

#include <stdio.h> 
#include <stdint.h> 
#include <inttypes.h> 
#include <arpa/inet.h> 

int main() 
{ 
    uint32_t num = 123456789; 
    printf("\n num: %" PRIu32 "\n", num); 
    uint32_t x; 
    uint8_t a[4]; 
    unsigned char b[4]; 

    num=htonl(num); 

    a[0] = num & 0x000000FFu; 
    a[1] = (num & 0x0000FF00u) >> 8; 
    a[2] = (num & 0x00FF0000u) >>16; 
    a[3] = (num & 0xFF000000u) >>24; 

    b[0] = a[0]; 
    b[1] = a[1]; 
    b[2] = a[2]; 
    b[3] = a[3]; 


    printf("\nA: %x %x %x %x", a[0],a[1],a[2],a[3]); 
    printf("\nB: %x %x %x %x", b[0], b[1], b[2], b[3]); 


    x = b[0] | (b[1] & 0x000000FFu)<<8 | (b[2] & 0x000000FFu)<<16 | (b[3] & 0x000000FFu)<<24; 

    x = ntohl(x); 

    printf("\n x vale: %" PRIu32 "\n", x); 

    return 0; 
} 

あなたが見ることができるように:

  1. b配列は、undefined behaviorを避けるためにunsigned charとして宣言されています。また、コード内の第3のprintfによって印刷された値も修正されます。
  2. aアレイに値を挿入すると、正しい位置にシフトする前に移動したいビットをマスクすると、より明確になります。
  3. xの値を計算すると、8 bitの変数に左シフトが実行されます。あなたは8シフト後にすべてのビットを失っています。 &あなたが2501 @指摘したように、あなたはUBを避けるようにしてくださいするリテラルのためのuを使用する必要があり、ポイント3についてビットシフト用とor

の正しいサイズを使用することを確認することができます32 bit HEX literalでそれらをINGのintのサイズが32 btsより小さいか、signed intにトラップ値があるプラットフォームで実行します。 6.4.4.1を参照してください。標準のp5。

+1

intの幅が32ビット未満の場合、または符号付き整数表現にトラップ値がある場合、このコードは整数昇格のために左シフトが行われたときにubを持ちます。 – 2501

+0

@ 2501さて、そうですが、私はそれがあまりにも複雑でOPのレベルでは分かりやすいと書いています。私のコメントで十分でした。私は私の不正確な答えを取り消します。 – LPs

+0

解決策は本当にシンプルです。「0x000000FFu」 – 2501

0

memcpyへの呼び出しがうまくいかない理由がわかりません。 CHAR_BIT == 8を確認して、charが8ビットタイプ(一部の実装ではcharを16ビットビッグと定義しています)として定義されていることを確認してから、memcpy(b, a, sizeof(b)/sizeof(b[0]))を呼び出します。これはトリックする必要があります。 memcpystring.hCHAR_BITlimits.hを含めるのを忘れないでください。他の人が指摘したようにcharの署名ネスが実装同様に定義されているので


は、あなたはまだ、これでトラブルを得ることができます。したがって、定義されていない動作を防ぐにはをunsigned charと宣言する必要があります。

abのサイズが同じであることを確認して、ランタイムエラーが発生しないようにする必要があります。

関連する問題