将变量传递给函数将更改C中的地址位置

时间:2018-06-27 21:03:30

标签: c arguments parameter-passing memory-address memcpy

在这里有一个奇怪的问题,即将参数传递给函数。

该参数是一个结构,定义为:

#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)

我有一个函数将此结构声明为:

void func1(void) {
    message_t response;

在此函数中,我将其作为参数传递给另一个函数:

    func2(response);

func2中,我声明了另一个结构,并将其定义为:

 #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)

此结构在func2中声明为:

frame_t frame;

frame中将复制一些数据,而其payload元素中的数据正是我想要复制到response结构中的数据。

所以现在在func2中,我打电话给memcpy

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

我已验证frame.header.length等于20,现在减1将复制19字节的数据。 response的宽度为19个字节,所以应该没问题。

执行memcpy后,我打印出response的内容,并且看起来正确。

返回func1后,我将再次打印response的内容。现在内容不见了,又是空的。

所以我要调试的是在response的上下文中打印了func1的地址位置,并得到了地址0x2000a470

如果我在response的上下文中打印func2的地址位置,则会得到地址0x2000a484

如果我从地址0x2000a484开始打印内存,则会看到应该在response中的数据。

当我将response的地址传递给另一个函数后,为什么会更改它?

还有一些其他信息,我正在使用GCC和ST Arm Core MCU用C编写。

1 个答案:

答案 0 :(得分:2)

您正在传播func1func2之间的传递值。您的代码具有功能,

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是按值传递的,因此您需要调整值以允许进行所需的修改:

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
}

那应该可以解决您的问题。