将变量传递给函数会更改 C 中的地址位置
Passing Variable To Function Changes Address Location in C
在将参数传递给函数时遇到一个奇怪的问题。
参数是一个结构体,定义为:
#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
的内容。现在内容没了,又是空的
所以我调试它的方法是在 func1
的上下文中打印 response
的地址位置,然后我得到地址 0x2000a470
.
如果我在 func2
的上下文中打印 response
的地址位置,我会得到地址 0x2000a484
.
如果我打印从地址 0x2000a484
开始的内存,我会看到应该在 response
.
中的数据
为什么 response
的地址在我将它传递给另一个函数后立即发生变化?
还有一些额外的信息,我正在用 C 编写,使用 GCC 和一个 ST Arm Core MCU。
您正在 func1
和 func2
之间传播按值传递。你的代码有一个函数,
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
}
这应该可以解决您的问题。
在将参数传递给函数时遇到一个奇怪的问题。
参数是一个结构体,定义为:
#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
的内容。现在内容没了,又是空的
所以我调试它的方法是在 func1
的上下文中打印 response
的地址位置,然后我得到地址 0x2000a470
.
如果我在 func2
的上下文中打印 response
的地址位置,我会得到地址 0x2000a484
.
如果我打印从地址 0x2000a484
开始的内存,我会看到应该在 response
.
为什么 response
的地址在我将它传递给另一个函数后立即发生变化?
还有一些额外的信息,我正在用 C 编写,使用 GCC 和一个 ST Arm Core MCU。
您正在 func1
和 func2
之间传播按值传递。你的代码有一个函数,
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
}
这应该可以解决您的问题。