2

Windows用のmingw GCCコンパイラでコードブロックを使用して、Cでプログラムをコーディングしています。入力が type の配列である関数が定義されていますint。私は別のようにstruct定義しています

typedef struct {
float re;
float im;
}complex_float;

complex_float形式でデータを処理する必要があるため、int 型配列を型配列に変換したいと考えていcomplex_floatます。次のポインターメソッドを使用して変換を行っています

complex_float *comSig = (complex_float *) sigbuf;

ここsigbifint、整数配列の開始アドレスを指すポインターです。

しかし、私が行うと、のprintf("%f",comSig[0].re);ようなガベージ値が得られます-1.#QNAN0

LINUXで配列間のデータ変換にこの手法を何度も使用しましたが、うまくいきました。これは、mingw コンパイラが明確に動作しないことに関連する問題ですか、それとも int 配列を構造体配列に変換するために間違った方法を使用しているという事実に関連していますか。

4

4 に答える 4

4

これはあなたがしていることは絶対に間違っています。値の型をキャストしても、値は「変換」されませんが、コンパイラに別の型として扱うように指示するだけです。int と構造体のサイズはおそらく異なるため、それらから作成された配列も異なるため、整数配列の境界を超えて書き込み/読み取りを行うことさえできます。本当に整数を複素数に変換したい場合は、自分でコーディングする必要があります:

int number_of_items = 10; // e. g. there are 10 integers
int *int_arr = // however you obtain the integer array
complex_float *cpx_arr = malloc(sizeof(*cpx_arr) * number_of_items);
int i;
for (i = 0; i < number_of_items; i++)
{
    cpx_arr[i].re = (float)(int_arr[i]);
    cpx_arr[i].im = 0.0f;
}

もちろん、free(cpx_arr)使用後もお忘れなく。

于 2012-08-27T07:18:02.957 に答える
2

C には、そのような変換機能はありません。あなたがすることはただのpointer cast.

あなたがそれをするとどうなりますか:

sigbuf は整数の配列を指します。(complex_float*) にキャストして最初の構造体要素の実部にアクセスしようとすると、実際には配列の最初の整数値にアクセスしますが、暗黙的に float 値にキャストするため、ゴミのように見えます。

配列サイズ n の整数がある場合について説明します。実際には、次のような連続データがあります。

[int0][int1][int2][int3][int4][int5][int6][int7][int8]...[intN]

次のようにキャストすると:complex_float *comSig = (complex_float *) sigbuf; コンパイラはデータを次のように扱います (現在は float として扱われることに注意してください)。

[re0][im0][re1][im1][re2][im2][re3][im3][re4][im4]...[re(N/2)][im(N/2)]

したがって、キャストの結果は、整数データを float として扱うようにコンパイラに指示するだけであり、その結果、ガベージのように見える出力が得られます。問題を解決する正しい方法については、H2CO3 が提供する別の回答があります。

于 2012-08-27T07:12:25.940 に答える
1

構造体は、最適化のためにコンパイルされたときとは異なるサイズになることがあります。詳細については、 http://en.wikipedia.org/wiki/Data_structure_alignmentをご覧ください。ただし、gcc の拡張パック (http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html) を使用して無効にすることができます。それに加えて、アラインされていないアクセスの問題が発生する可能性があります。アーキテクチャによって処理される x86 では問題ありませんが、移植可能なコードのために、型キャストの代わりに memcpy を使用します。

于 2012-08-27T07:17:20.770 に答える
0

これまでの回答は、明示的な値のキャスト、構造のアラインメント、構造体の配列と int 配列など、アプローチに関する問題のほとんどを指摘しています。もう 1 点追加します。

int and float types are both of size 4 bytes, I have checked that...

Int と float は、メモリ内でまったく異なる方法で表現されます。

整数値は2 の補数と呼ばれるもので表されます。これにより、余分な演算を行わずに整数を加算することができ、数値の単一の表現が得られます0

  • 正の整数は、基数 2 に単純に変換されます。たとえば、=151として表されます。00000000 00000000 00000000 10010111(2)2^7 + 2^4 + 2^2 + 2^1 + 2^0
  • 負の整数は、絶対値のバイナリ表現として表され、すべてのビットが反転され、結果の数値に 1 が追加されます。たとえば、(正の数と比較) のように-151表されます。11111111 11111111 11111111 01101001(2)

一方、単精度浮動小数点は、IEEE 754-2008 標準で binary32と呼ばれるものとして表されます。

  • 最初のビットは符号ビットです。正の場合は 0、負の場合は 1 です。
  • 次の 8 ビットは指数で、2 の補数です。偏っています。実際の指数を得るには、この値から 127 を引きます。
  • 次の 23 ビットは、正規化された (小数点の前に 1 桁しかない) 分数の小数部分を表します。

Soはの指数(偏りがない) と仮数(整数部分が暗黙的であるため) を持つ151.0として表されます。01000011 00010111 00000000 0000000013470.17968751.1796875

float *これが、 aを anにキャストするとint *、これは実行したことと同等であり、後で逆参照するときにガベージ値を取得する理由です。H2CO3は、代入演算子による適切な変換方法を指摘しています。

于 2012-08-27T09:42:53.713 に答える