cDreamer
cDreamer

Reputation: 415

Passing Variable To Function Changes Address Location in C

Having an odd issue here with passing an argument to a function.

The argument is a struct, defined as:

#pragma pack(push,1)
 typedef struct {
     struct {
         uint8_t opcode;
         uint8_t type;
         union {
             uint8_t attr;
             struct {
                 unsigned int reserved : 6;
                 unsigned int sequence : 2;
             };
         };
         uint8_t bytes;
     } header;
     uint8_t payload[15];
 } message_t;
 #pragma pack(pop)

I have a function that declares this struct as:

void func1(void) {
    message_t response;

Within this function I pass it as an argument to another function:

    func2(response);

Within func2 I have another struct declared and it is defined as:

 #pragma pack(push,1)
 typedef struct {
     struct {
         uint8_t op_code;
         avneraIDs_t IDs;
         uint8_t length;
     } header;
     uint8_t payload[30];
 } frame_t;
 #pragma pack(pop)

This struct is declared within func2 as:

frame_t frame;

frame will have some data copied into it, and the data within its payload element is what I want copied into the response struct.

So now in func2 i have a call to memcpy.

memcpy((uint8_t *)&response, frame.payload, (frame.header.length - 1));

I have verified that frame.header.length is equal to 20, and now minus 1 would copy over 19 bytes of data. response has a width of 19 bytes so it should be fine.

After performing the memcpy, I print out the contents of response and the contents look correct.

After returning to func1 I print the contents of response again. And now the contents are gone, it's empty again.

So what I did to debug this was I printed the address location of response within the context of func1 and I get the address 0x2000a470.

If I print the address location of response within the context of func2 I get the address 0x2000a484.

If I print the memory starting at address 0x2000a484, I see the data that should be in response.

Why did the address for response change as soon as I passed it to another function?

Also as some extra information, I am writing in C, using GCC, and an ST Arm Core MCU.

Upvotes: 1

Views: 80

Answers (1)

WhozCraig
WhozCraig

Reputation: 66234

You're propagating pass-by-value between func1 and func2. Your code has a function,

void func2(message_t response) // <<==== response gets value from caller
{
    memcpy(&response, ....) // <<==== modify local response; caller is unaffected.
}

void func1()
{
    message_t respnose;
    func2(response); // <<==== PASSED BY VALUE
}

C being pass-by-value, you need to craft the value to allow the modification you want:

void func2(message_t *response) // <<==== receiving address of caller's response
{
    memcpy(response, ...); // <<=== using address of caller's response.
}

void func1()
{
    message_t response;
    func2(&response); // <<==== passing address of our response
}

That should fix your issue.

Upvotes: 2

Related Questions