我正在进行简单的就地傅立叶变换。但我不知道原地是如何发生的。例如,以下代码段取自https://rosettacode.org/wiki/Fast_Fourier_transform#C
由于函数声明void fft(cplx buf[], int n)
,没有任何输出,子函数中buf
的变化如何转回主函数?
#include <stdio.h>
#include <math.h>
#include <complex.h>
double PI;
typedef double complex cplx;
void _fft(cplx buf[], cplx out[], int n, int step)
{
if (step < n) {
_fft(out, buf, n, step * 2);
_fft(out + step, buf + step, n, step * 2);
for (int i = 0; i < n; i += 2 * step) {
cplx t = cexp(-I * PI * i / n) * out[i + step];
buf[i / 2] = out[i] + t;
buf[(i + n)/2] = out[i] - t;
}
}
}
void fft(cplx buf[], int n)
{
cplx out[n];
for (int i = 0; i < n; i++) out[i] = buf[i];
_fft(buf, out, n, 1);
}
void show(const char * s, cplx buf[]) {
printf("%s", s);
for (int i = 0; i < 8; i++)
if (!cimag(buf[i]))
printf("%g ", creal(buf[i]));
else
printf("(%g, %g) ", creal(buf[i]), cimag(buf[i]));
}
int main()
{
PI = atan2(1, 1) * 4;
cplx buf[] = {1, 1, 1, 1, 0, 0, 0, 0};
show("Data: ", buf);
fft(buf, 8);
show("\nFFT : ", buf);
return 0;
}
我不确定我是否明确了这个问题。我在下面写了一个片段,与上面的片段结构相同。但是,它在就地模式下不起作用,我的意思是,子函数中变量的值变化没有转移到主函数中。
#include <stdio.h>
void _sumab(int a, int b, int c)
{
printf("2: %d, %d, %d\n", a, b, c );
a = 2*a + b+c;
b = 12;
// if(a<800) _sumab(a, b, c);
printf("3: %d, %d, %d\n", a, b, c );
}
void sumab(int a, int b, int c)
{
printf("1: %d, %d, %d\n", a, b, c );
_sumab(a, b, c);
a = a*4;
printf("4: %d, %d, %d\n", a, b, c);
}
int main()
{
int out1 = 0;
int out2 = 1;
int out3 = 2;
sumab(out1+100, out2, out3);
printf("5: %d, %d, %d\n", out1, out2, out3);
return 0;
}
在前一个代码中,在调用子函数之后,buf
中存储的值即使在main函数中也会发生变化。但是在后面的代码中,在调用子函数之后,a, b, c
的值保持不变,就像它们在主函数范围中一样。为什么呢?
我是否遗漏了一些重要问题?就地如何发生?
如果fft(buf, 8)
表示计算buf
的傅立叶变换并将其保存在buf
中,表达式fft(buf+2, 8)
怎么样,它将计算{的傅立叶变换{1}},但存储在哪里?
提前致谢。
答案 0 :(得分:4)
您的问题的关键是在C中,您无法将数组传递给函数。
当你这样写:
void fft(cplx buf[], int n)
根据C11标准§6.7.6.3p7中定义的规则,该声明中的类型为调整 * (引用最新的公共草案,n1570,在这里):
参数声明为'' type ''的数组应调整为''限定指针 type '',其中类型限定符(如果有)是在
[
和]
内指定的类型限定符。 数组类型推导。 [...]
这意味着,真正的声明如下:
void fft(cplx *buf, int n)
所以,你实际上是在传递一个指针,并且该函数可以通过该指针操作原始数组。
*)通常说数组衰减为指针。这不是该标准的官方措辞,但是被广泛理解。如果您有这样的数组:
char a[5];
并且您只需编写a
,这被评估为指向a
类型char *
的第一个元素的指针。因此,使用如下声明的函数:
void foo(char x[]);
你可以称之为
foo(a);
真正传递的是指向a
的第一个元素的指针,因此,a
“衰减”为指针。