局部变量问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <stdio.h>

// 定义一个结构体
struct Point {
int x;
int y;
};

// 函数:返回一个 Point 结构体的拷贝
struct Point createPoint(int x, int y) {
struct Point p;
p.x = x;
p.y = y;
return p; // 返回结构体的拷贝
}

struct Point global_p; // 全局变量

struct Point func(void)
{
global_p = createPoint(10, 20);

return global_p; // 返回全局变量的拷贝
}

struct Point* global_ppinter; // 全局变量

struct Point* func2(void)
{
// 禁止返回局部变量的地址
struct Point p = createPoint(60, 80);

return &p; // 返回全局变量的拷贝
}

int main() {

struct Point* p4 = func2(); // 调用函数,返回全局变量的拷贝
// 输出 Point 结构体的成员
printf("Point p4: (%d, %d)\n", p4->x, p4->y);

struct Point p3 = func(); // 调用函数,返回全局变量的拷贝
// 输出 Point 结构体的成员
printf("Point p3: (%d, %d)\n", p3.x, p3.y);
p3.x = 30; // 修改 p3 的值
p3.y = 40; // 修改 p3 的值
printf("Point p3: (%d, %d)\n", p3.x, p3.y);

// 输出 Point 结构体的成员
printf("Point global_p: (%d, %d)\n", global_p.x, global_p.y);

// 创建一个 Point 结构体实例
struct Point p1 = createPoint(10, 20);

// 输出 Point 结构体的成员
printf("Point p1: (%d, %d)\n", p1.x, p1.y);

// 修改 p1 的值
p1.x = 30;
p1.y = 40;

// 再次输出 Point 结构体的成员
printf("After modifying p1: (%d, %d)\n", p1.x, p1.y);

// 使用 createPoint 函数创建一个新实例
struct Point p2 = createPoint(50, 60);
printf("Point p2: (%d, %d)\n", p2.x, p2.y);

return 0;
}

func2 是禁止返回局部变量的地址!局部变量 p 的生命周期仅限于 func2 函数执行时,一旦函数返回,这个局部变量将会被销毁,因此返回它的地址会导致未定义行为。

修改办法有两种。

方法 1:使用全局变量

如果你希望 func2 返回一个 Point 结构体的指针,可以将这个结构体定义为全局变量,如下所示:

1
2
3
4
5
6
7
struct Point global_point; // 全局变量

struct Point* func2(void) {
global_point = createPoint(60, 80);
return &global_point; // 返回全局变量的地址
}

方法 2:动态分配内存

你可以使用 malloc 动态分配内存:

1
2
3
4
5
6
7
8
9
#include <stdlib.h>  // 包含 malloc 和 free 的头文件

struct Point* func2(void) {
struct Point* p = (struct Point*)malloc(sizeof(struct Point)); // 动态分配内存
if (p != NULL) { // 检查内存分配是否成功
*p = createPoint(60, 80);
}
return p; // 返回分配的内存地址
}

使用动态分配的内存后,你需要记得在不需要这个结构体时使用 free(p) 来释放内存,防止内存泄漏。

如果选择使用全局变量,请确保在多线程或复杂逻辑情况下,代码的线程安全性。而如果使用动态内存分配,确保适当管理内存的生命周期,以防止内存泄漏。在实际应用中,根据需求选择合适的方法。


临时变量也不能取地址

1
2
3
4
5
6
7
struct Point* func2(void)
{
// 禁止返回局部变量的地址
global_ppinter = &(createPoint(60, 80));

return &global_ppinter; // 返回全局变量的拷贝
}

这种方法也会报错,函数的返回值依然是一个临时变量。

需要用下面这种方法:

1
2
3
4
5
6
7
8
9
struct Point global_ppinter; // 全局变量

struct Point* func2(void)
{
// 禁止返回局部变量的地址
global_ppinter = createPoint(60, 80);

return &global_ppinter; // 返回全局变量的拷贝
}

global_ppinter = createPoint(60, 80); 这一行代码是进行赋值操作。