【发布时间】:2021-10-18 05:45:02
【问题描述】:
我知道标题很混乱但我不知道如何更好地描述它,让代码自己解释一下:
我有一个第三方库将复杂的标量定义为
typedef struct {
float real;
float imag;
} cpx;
所以复杂的数组/向量就像
cpx array[10];
for (int i = 0; i < 10; i++)
{
/* array[i].real and array[i].imag is real/imag part of i-th member */
}
目前的情况是,在一个函数中我有两个浮点数组作为参数,我使用两个临时的局部复数数组,例如:
void my_func(float *x, float *y) /* x is input, y is output, length is fixed, say 10 */
{
cpx tmp_cpx_A[10]; /* two local cpx array */
cpx tmp_cpx_B[10];
for (int i = 0; i < 10; i++) /* tmp_cpx_A is based on input x */
{
tmp_cpx_A[i].real = do_some_calculation(x[i]);
tmp_cpx_A[i].imag = do_some_other_calculation(x[i]);
}
some_library_function(tmp_cpx_A, tmp_cpx_B); /* tmp_cpx_B is based on tmp_cpx_A, out-of-place */
for (int i = 0; i < 10; i++) /* output y is based on tmp_cpx_B */
{
y[i] = do_final_calculation(tmp_cpx_B[i].real, tmp_cpx_B[i].imag);
}
}
我注意到在第一个循环之后x 没用,第二个循环就位。如果我可以使用与x 和y 相同的内存来构建tmp_cpx_B,我可以节省一半的中间内存使用量。
如果复数数组定义为
typedef struct{
float *real;
float *imag;
} cpx_alt;
那我就可以了
cpx_alt tmp_cpx_B;
tmp_cpx_B.real = x;
tmp_cpx_B.imag = y;
然后做剩下的,但事实并非如此。
我无法更改第三个库复杂结构的定义,也无法将cpx 作为输入,因为我想对外部用户隐藏内部库,而不是破坏 API。
所以我想知道是否可以使用cpx 之类的标量成员和x 和y 之类的标量数组来初始化结构数组
编辑1:对于一些常见问题:
- 实际上数组长度最多为 960,这意味着一个
tmp_cpx数组将占用 7680 个字节。我的平台总共有 56k 内存,节省一个tmp_cpx将节省约 14% 的内存使用。 - 第三方库是kissFFt,对复数数组进行FFT,它定义了自己的
kiss_fft_cpx而不是标准的,因为它可以使用marco在浮点/定点计算之间切换
【问题讨论】:
-
你不能使用相同的内存。
x指向float的数组,而不是cpx的数组。 -
"我注意到在第一个循环之后 x 没用" 你的意思是
x不再使用了吗? -
如果没有看到 A Minimal, Complete, and Verifiable Example (MCVE) 显示数组是如何作为
x和y声明和初始化传递的,很难确定。 -
正如 Barmar 所说,答案是否定的。浮点数组不能用于保存另一种类型。你可以更改
my_func的参数(我假设),可以做一些技巧(例如使用联合类型),但值得吗?在这里,您只有 10 个数组元素,因此实际上我们正在谈论的内存很少。如果它是 10.000.000 个元素,那么做一些特殊的技巧可能是值得的,但不是像这样小的事情。最好保持简单。 -
请不要自行对现有术语进行定义。在 C 语言中,算术和指针类型是标量。与 聚合类型 的结构和数组相反(如果您愿意,可以选择“容器类型”)。因此
cpx是聚合类型,而不是标量类型。