2017-01-25 2 views
2

Cで定数浮動小数点から生データバイトを取得しようとしています。これは読取り可能な定数バイト配列を作成するために行われています。これは以下で見ることができます。Cで#defineを使用して定数浮動小数点値の生データバイトを取得

#define FLOAT_TO_BYTES(value) \ 
     (uint8_t)(value),  (uint8_t)(value << 8), \ 
     (uint8_t)(value << 16), (uint8_t)(value << 24) 

    const uint8_t byteArray[] = { 
     FLOAT_TO_BYTES(11.4) 
    }; 

問題は、ポインタや任意の種類のコードブロックを使用できないことです。浮動小数点値をシフトすることができないので、上記は機能しません。私は組合を使用しようとしましたが、どちらかを働かせることはできません。どんな助けでも大歓迎です!

+2

あなたが本当にあなたのためにそれらのバイトを計算するためのプリプロセッサをしたい、またはそれはあなたが '符号なしchar'sの配列としてあなたのフロートへのアクセスを得ることは十分ありますか?後者の場合、 'const double x = 11.4;あなたは 'sizeof(bytearray)'も 'sizeof(double) 'にしたいですか? –

+0

C言語とC++は異なる言語です。答えは実際にどのようにコーディングしているかによって異なる場合があります。 – kaylum

+0

実際の実装では、byteArrayのサイズがKBなのでconstのuint8_t配列でなければならないので、バイトを計算するにはプリプロセッサが必要です – Drew

答えて

0

標準化されていないため、floatでバイト操作を使用することはできません。

はどのようにそれを行うことができますか? 注:以下のすべての方法は、floatが32ビット幅であることを前提としています。

ポインタ

#define FLOAT_TO_BYTES(value) (*((unsigned char *) value)), (*(((unsigned char *) value) + 1)), (*(((unsigned char *) value) + 2)), (*(((unsigned char *) value) + 3)) 

連合

typedef union 
{ 
    float f; 
    unsigned char chars[4]; 
} __attribute__ ((packed)) floatunion; 

// I am lazy: 
#define FLOAT_TO_BYTES(value) FLOAT_TO_BYTES0 ((floatunion *) &value) 
#define fLOAT_TO_BYTES0(value) value->chars[0], value->chars[1], value->chars[2], value->chars[3] 
+1

私はポインタのバリエーションが未定義の動作を呼び出すかどうかはわかりません。しかし、 'union'の変種は、型打ちと明示的に許可された方法です。あなたがなぜ 'packed'属性を追加したのかは分かりません。それは標準ではなく、不要です。 – Olaf

+1

'packed'属性は、私のOS開発経験に基づいています。それは不要かもしれません。 –

+0

'浮動小数点の参照のメモリは私の意見では定義されていないはずです。 –

2
ここ

あなたは労働組合とのバイトを取得することができます方法は次のとおりです。

#include <stdio.h> 

union float_bytes{ 
    float f; 
    char b[sizeof(float)]; 
}; 

int main() 
{ 
    union float_bytes fb = { 1.1 }; 
    for(int i=0; i<sizeof(float);i++) 
     printf("%hhx\n", fb.b[i]); 

} 

また、単純に行うことができます。

#include <stdio.h> 
int main() 
{ 
    float f = 1.1; 
    for(int i=0; i<sizeof(float);i++) 
     printf("%hhx\n", ((char*)&f)[i]); 

} 

文字ポインタで何かを検査することは常に許可されています。

あなたは本当に、あなたがマクロ に(のchar *)にキャストを入れて、フロートポインタを渡すか、明示的にfloat型の変数を避けるために、マクロでリテラルの一時的な化合物を作成することができますすることができますしたい場合は

#include <stdio.h> 

#define FLOAT_BYTES(Float) ((char*)(&(float){Float})) 
int main() 
{ 
    for(int i=0; i<sizeof(float);i++) 
     printf("%hhx\n", FLOAT_BYTES(1.1)[i]); 
} 

(化合物の寿命リテラルは、その最も近い外側のブロックのそれである。)

0

はC99から利用可能unionのリテラル化合物を、使用します。

ポインタまたはシフトを使用しません。コードは、floatのバイトと順序を指定する必要があります。

#define FLOAT_TO_BYTE(float_value, index) \ 
    ((\ 
    (union { float f; uint8_t u8[sizeof (float)]; }) {(float_value)} \ 
    ).u8[(index)]) 

// size sensitive code - assume sizeof (float) == 4 
#define FLOAT_TO_BYTES(float_value) \ 
    FLOAT_TO_BYTE((float_value), 0), FLOAT_TO_BYTE((float_value), 1), \ 
    FLOAT_TO_BYTE((float_value), 2), FLOAT_TO_BYTE((float_value), 3) 

int main(void) { 
    const uint8_t byteArray[] = { 
     42, 
     FLOAT_TO_BYTE(11.4, 0), 
     FLOAT_TO_BYTE(11.4, 1), 
     FLOAT_TO_BYTE(11.4, 2), 
     FLOAT_TO_BYTE(11.4, 3), 
     42, 
     FLOAT_TO_BYTES(11.4) 
    }; 
    for (unsigned i=0; i<sizeof byteArray; i++) { 
    printf("%u %u\n", i, 1u*byteArray[i]); 
    } 
} 

出力

0 42 
1 102 
2 102 
3 54 
4 65 
5 42 
6 102 
7 102 
8 54 
9 65 
関連する問題