3

Here is the layout of my current code,

test.h

typedef struct{
        int aa;
        int bb;
        int cc;
} ABC;
extern ABC XYZ;  

void passValue(ABC DEF,int a, int b, int c);
void doSomething();

test.c

ABC XYZ;

void passValue(ABC DEF,int a, int b, int c){
  DEF.aa = a;
  DEF.bb = b;
  DEF.cc = c;
}

void doSomething(){
  ...
  ...
  passValue(XYZ,10,20,30);
}  

but when I call doSomething() on the main program, the value is still 0 (not changed). I've try to treat them just like @R Sahu answer on this question,

test.h

typedef struct{
        int aa;
        int bb;
        int cc;
} ABC;
extern ABC XYZ;  

void passValue(ABC * DEF,int a, int b, int c);
void doSomething();

test.c

ABC XYZ;

void passValue(ABC * DEF,int a, int b, int c){
  *DEF.aa = a;  //error
  *DEF.bb = b;  //error
  *DEF.cc = c;  //error
}

void doSomething(){
  ...
  ...
  passValue(&XYZ,10,20,30);
}


ERROR : expression must have struct or union type
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
duck
  • 369
  • 3
  • 17
  • Can you add the code that gives the `ERROR : expression must have struct or union type` error? – fvu Oct 24 '17 at 06:27
  • 1
    [This question and its answers](https://stackoverflow.com/questions/4316314/pass-struct-by-reference-in-c) should get you started. – fvu Oct 24 '17 at 06:32

3 Answers3

4

Unary operators have less priority then postfix operators. So an expression like this

 *DEF.aa = a;  //error

is equivalent to

*( DEF.aa ) = a;

So you need at first apply the unary operator * and only then the postfix operator

( *DEF ).aa = a;
( *DEF ).bb = b;
( *DEF ).cc = c;

Or you could use only the postfix operator ->

DEF->aa = a;
DEF->bb = b;
DEF->cc = c;

As for the first function definition then function parameters are its local variables. Parameters are initialized by copies of the values of arguments. So within the function it is the copies that are changed. The original arguments are unchanged. You need to pass arguments by reference if you are going to change them in the function that is by using pointers to them.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

*DEF.foo parses as *(DEF.foo), not as (*DEF).foo. That's why the DEF->foo form exists; the version of a->b->c->d using just * and . would be hideous.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
  • thanks for the answer, I just tried as you suggested, but it also produces compile error, "operand of "*" must be a pointer" – duck Oct 24 '17 at 06:34
2

The solution in how to change value of variable passed as argument? is only valid, because of a special property of string constants. They keep existing after a function exits, as detailed in "life-time" of string literal in C

Every time you pass an argument to a function, a copy of that argument is created. All your changes then get applied to that copy, which is discarded after your function ends.

You need to pass the address of the object you wish to change to your function instead, and then deference that address in order to apply your changes to the original instance of your structure:

test.h

typedef struct{
        int aa;
        int bb;
        int cc;
} ABC;
extern ABC XYZ;



void passValue(ABC *DEF,int a, int b, int c);
void doSomething();

test.c

ABC XYZ;

void passValue(ABC *DEF,int a, int b, int c){
  DEF->aa = a;
  DEF->bb = b;
  DEF->cc = c;
}

void doSomething(){
  ...
  ...
  passValue(&XYZ,10,20,30);
}  

You should read some more about pointers, if you'd like to understand this: How do pointer to pointers work in C?

Lanting
  • 3,060
  • 12
  • 28