I am trying to run a function, int testfn
below, which should assign a complex number to the pointer (to a complex number), double _Complex *foo
below, that it is fed. The minimal (non-working) example .c file is test.c
below.
When I call testfn
through main
, instead of returning the assigned value 1.0 0.5*I
, it returns 0.0 0.0*I
. I do not understand why, or how to fix it.
test.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
int testfn(double _Complex *foo) {
double _Complex foobar = 1.0 0.5*I;
foo = &foobar;
printf("foobar = %.8f I %.8f \n",creal(foobar),cimag(foobar));
printf("*foo = %.8f I %.8f \n",creal(*foo),cimag(*foo));
return 0;
}
int main() {
double _Complex toot;
testfn(&toot);
printf("toot = %.8f I %.8f \n",creal(toot),cimag(toot));
return 0;
}
compile and run with
cc -o test test.c -L. -lm -Wall
./test
terminal output gives wrong answer
foobar = 1.00000000 I 0.50000000
*foo = 1.00000000 I 0.50000000
toot = 0.00000000 I 0.00000000
Notice that the actual answer for toot
should be toot = 1.00000000 I 0.50000000
.
On the other hand, this array case works
Here, in test2.c
, I am feeding double _Complex (*foo)[3]
, i.e. a three-dimensional array of pointers to complex numbers (is that right?) to int testarrayfn
, and then assigning foo
to be a specific 2x3 matrix of complex numbers inside testarrayfn
.
When I call testarrayfn
from main
using double _Complex toot[2][3];
and testarrayfn(toot);
, I do get the right answer. I am not sure why this is done right (I just googled and played around a lot with arrays, and passing array arguments).
test2.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
int testarrayfn(double _Complex (*foo)[3]) {
double _Complex foobar;
int i,j;
for (i=0;i<2;i ) {
for (j=0;j<3;j ) {
foobar = 1.*(i 1) 0.5*(j 1)*I ;
foo[i][j] = foobar;
printf("[%d][%d]: foobar = %.8f I %.8f \n",i,j,creal(foobar),cimag(foobar));
printf("foo[%d][%d] = %.8f I %.8f \n",i,j,creal(foo[i][j]),cimag(foo[i][j]));
}
}
return 0;
}
int main() {
double _Complex toot[2][3];
testarrayfn(toot);
int i,j;
for (i=0;i<2;i ) {
for (j=0;j<3;j ) {
printf("toot[%d][%d] = %.8f I %.8f \n",i,j,creal(toot[i][j]),cimag(toot[i][j]));
}
}
return 0;
}
compile and run with
cc -o test2 test2.c -L. -lm -Wall
./test2
terminal output gives expected answer
[0][0]: foobar = 1.00000000 I 0.50000000
foo[0][0] = 1.00000000 I 0.50000000
[0][1]: foobar = 1.00000000 I 1.00000000
foo[0][1] = 1.00000000 I 1.00000000
[0][2]: foobar = 1.00000000 I 1.50000000
foo[0][2] = 1.00000000 I 1.50000000
[1][0]: foobar = 2.00000000 I 0.50000000
foo[1][0] = 2.00000000 I 0.50000000
[1][1]: foobar = 2.00000000 I 1.00000000
foo[1][1] = 2.00000000 I 1.00000000
[1][2]: foobar = 2.00000000 I 1.50000000
foo[1][2] = 2.00000000 I 1.50000000
toot[0][0] = 1.00000000 I 0.50000000
toot[0][1] = 1.00000000 I 1.00000000
toot[0][2] = 1.00000000 I 1.50000000
toot[1][0] = 2.00000000 I 0.50000000
toot[1][1] = 2.00000000 I 1.00000000
toot[1][2] = 2.00000000 I 1.50000000
Additional questions about complex.h
I could not find the answers to the following questions anywhere:
- Can one use
double complex foo
anddouble _Complex foo
interchangeably, both inside a function, and an argument? - Can one use
double complex *foo
anddouble _Complex *foo
interchangeably, both inside a function, and an argument? - Can one use
double complex (*foo)[3]
anddouble _Complex (*foo)[3]
interchangeably, both inside a function, and an argument? - More generally, is there any difference between
double complex
,double _Complex
, andcomplex double
?
CodePudding user response:
Test1
Two problems.
foo
is a local variable. When you assign it it only will be valid in the function scope.foobar
is a local variable and it cannot be accessed after the function return (as it stops to exist)
You need to make foobar
exist after the function return and pass the reference to the pointer.
int testfn(double _Complex **foo) {
static double _Complex foobar = 1.0 0.5*I;
*foo = &foobar;
printf("foobar = %.8f I %.8f \n",creal(foobar),cimag(foobar));
printf("*foo = %.8f I %.8f \n",creal(**foo),cimag(**foo));
return 0;
}
int main() {
double _Complex *toot;
testfn(&toot);
printf("toot = %.8f I %.8f \n",creal(*toot),cimag(*toot));
return 0;
}
or assign the underlying object with the value of the foobar
(not reference)
int testfn(double _Complex *foo) {
double _Complex foobar = 1.0 0.5*I;
*foo = foobar;
printf("foobar = %.8f I %.8f \n",creal(foobar),cimag(foobar));
printf("*foo = %.8f I %.8f \n",creal(*foo),cimag(*foo));
return 0;
}
int main() {
double _Complex toot;
testfn(&toot);
printf("toot = %.8f I %.8f \n",creal(toot),cimag(toot));
return 0;
}
Test2 works because you assign the values to the referenced object, not trying to change the pointer to the array.
you can write the foo[i][j] = foobar;
as *(*(foo i) j) = foobar;
and it is identical as my second example (you can treat toot
as single element array)
_Complex
is an actual C keyword from C99 (or GCC extension before C99). complex
is a simple definition expanding to _Complex
. It is done this way as many old programs use its own complex
type