In theory, even in old K&R C compilers you can pass a struct to a function by value and by reference. In the first case the struct, when changed inside the function, is changed only there. In the latter case, when passing the struct as a pointer to a struct, the struct is changed on a global basis.
Imagine the following simple code:
#include <stdio.h>
struct Plot {
double x;
double y;
};
/* handing over struct by value */
int test_s1(p)
struct Plot p;
{
p.x = 11.1;
p.y = 12.2;
printf("In test_s1: ");
printf("x: %lf, y: %lf\n", p.x, p.y);
return(0);
}
/* handing over struct by reference */
int test_s2(p)
struct Plot *p;
{
p->x = 12.2;
p->y = 13.3;
printf("In test_s2: ");
printf("x: %lf, y: %lf\n", p->x, p->y);
return(0);
}
int main(void) {
struct Plot p;
p.x = 10.0;
p.y = 11.0;
printf("In main: ");
printf("x: %lf, y: %lf\n", p.x, p.y);
test_s1(p);
printf("After test_s1: ");
printf("x: %lf, y: %lf\n", p.x, p.y);
test_s2(&p);
printf("After test_s2: ");
printf("x: %lf, y: %lf\n", p.x, p.y);
return(0);
}
This code compiles fine with GCC in a modern x86 environment and produces no runtime error, even when compiled with
gcc -std=c89 -Wall -o struct-test struct-test.c
The output is as expected:
In main: x: 10.000000, y: 11.000000
In test_s1: x: 11.100000, y: 12.200000
After test_s1: x: 10.000000, y: 11.000000
In test_s2: x: 12.200000, y: 13.300000
After test_s2: x: 12.200000, y: 13.300000
In POWER C, after test_s1(), p.x and p.y contain random double values, and the code produces a runtime error: „stack overflow“. This seems to be a problem with long floats in combination with the struct object in POWER C.
Unfortunately, and in contrast to old K&R compilers, POWER C does not allow a function to return a struct, which might have solved the issue. Declaring the struct before the function prototype, as in above code, is recommended practice but also did not change the outcome.
Issues only with struct and long values? No!
But now it gets wild: When above code is changed from long floats to using unsigned int in the struct, p.x and p.y contain random values after returning from test_s2()!
Changing the function test_s2() to accept x and y as parameters did not fix the issue:
...
/* handing over struct by reference */
int test_s2(p, x, y)
struct Plot *p;
int x,y;
{
p->x = x;
p->y = y;
printf("In test_s2: ");
printf("x: %d, y: %d\n", p->x, p->y);
return(0);
}
...
test_s2(&p, 14, 15);
printf("After test_s2: ");
printf("x: %d, y: %d\n", p.x, p.y);
...
This is expected, as the problem is not in calling the function but in returning from the function.
Replacing the struct with a union will not solve the issue, as in a union all members have the same value:
...
union Plot {
unsigned int x;
unsigned int y;
};
...
/* handing over union by reference */
int test_s2(p)
union Plot *p;
{
p->x = 13;
p->y = 14;
printf("In test_s2: ");
printf("x: %d, y: %d\n", p->x, p->y);
return(0);
}
int main(void) {
union Plot p;
p.x = 10;
p.y = 11;
...
test_s2(&p);
printf("After test_s2: ");
printf("x: %d, y: %d\n", p.x, p.y);
...
Running this code means that p.x and p.y are both „14“ after test_s2()!
Resume
So, what is my resume? I believe POWER C has some serious memory bugs in dealing with the struct object in relations to functions. For most cases, you might consider a different compiler, maybe even a cross compiler.
In the program I wrote and troubleshooted for days, a Mandelbrot software for the Commodore 64, I removed all functions that needed to deal with the struct and moved the code into the main () function, and now everything is fine.