2

我正在使用带有 mingw GCC 编译器的 Code-Blocks 来用 C 编写我的程序。我定义了一个函数,其中输入是一个 type 的数组int。我有另一个struct定义为

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

我想将 int 类型数组转换为complex_float类型数组,因为我需要处理complex_float格式中的数据。我正在使用以下指针方法进行转换

complex_float *comSig = (complex_float *) sigbuf;

其中sigbifint指向整数数组起始地址的指针。

但是当我这样做时,我会printf("%f",comSig[0].re);得到一些垃圾值,例如-1.#QNAN0.

我已经在 LINUX 上多次使用这种技术在数组之间进行数据转换,并且它可以工作。这是与 mingw 编译器无法正常工作有关的问题,还是与我使用不正确的方法将 int 数组转换为 struct 数组的事实有关。

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*) 并尝试访问第一个结构元素的实部时,您实际上访问了数组的第一个整数值,但它对您来说似乎是垃圾,因为您隐式地将其转换为浮点值。

当你有一个数组大小为 n 的整数时,让我为你说明一下。实际上你有一个这样的顺序数据:

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

当您像这样进行转换时:complex_float *comSig = (complex_float *) sigbuf; 编译器将像这样处理您的数据(请注意,现在它们被视为浮点数):

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

所以强制转换的结果只是告诉编译器将整数数据视为浮点数,这将导致看似垃圾的输出。对于解决问题的正确方法,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 数组。我再补充一点:

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

Int 和 float 在内存中以完全不同的方式表示。

整数值用所谓的二进制补码表示,它允许在没有额外操作的情况下添加整数并给出数字的单一表示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 位)分数的小数部分。

所以151.0表示为01000011 00010111 00000000 00000000,指数为1347无偏),尾数为0.17968751.1796875因为积分部分是隐式的)。

这就是为什么,如果你将 afloat *转换为 an int *,这与你所做的相同,当你稍后取消引用它时,你会得到垃圾值。H2CO3通过赋值运算符指出了正确的转换方法。

于 2012-08-27T09:42:53.713 回答