C中结构体之指针与数组杂谈

First Post:

Last Update:

Page View: loading...

C中结构体之指针与数组

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
using namespace std;
// 今天描述结构体中的指针和数组
typedef struct _Player
{
int level;
char name[20];

} Player, *PPplayer;
// 上面这个第一个结构体里面成员在内存中是连续的

void fun1()
{
PPplayer p1 = (PPplayer)malloc(sizeof(Player)); // 为p1申请内存
memset(p1, 0, sizeof(Player)); // 初始化
p1->level = 1;
strcpy(p1->name, "张三");
cout << "p1->level:" << p1->level << endl;
cout << "p1->name:" << p1->name << endl;
free(p1);
p1 = NULL;
}

typedef struct _Player2
{
int level;
char *name; // name是一个指针

} Player2, *PPplayer2;
// 上面这个结构体里面成员在内存中是不连续的
void fun2()
{
PPplayer2 p2 = (PPplayer2)malloc(sizeof(Player2)); // 为p2申请内存
memset(p2, 0, sizeof(Player2)); // 初始化
p2->level = 1;
p2->name = (char *)malloc(strlen("1angx") + 1); // 为name申请内存,这里用了strlen()函数,最后的\x00的大小没有加上去,所以要加个1
memset(p2->name, 0, 20); // 初始化
strcpy(p2->name, "1angx");
cout << "p2->level:" << p2->level << endl;
cout << "p2->name:" << p2->name << endl;
// free(p2->name);
free(p2);
p2 = NULL;
}

typedef struct _Player3
{
int level;
char name[1]; // 这里给name的大小为1个字节,我们等会会在fun3函数中说明为何

} Player3, *PPplayer3;

void fun3()
{
PPplayer3 p3 = (PPplayer3)malloc(sizeof(Player3) + strlen("1angx")); // 为p3申请内存,同时加上我们的name的大小,这里因为我们数组的大小是1所以不需要再加上1了
memset(p3, 0, sizeof(Player3) + strlen("1angx")); // 初始化
p3->level = 1;
strcpy(p3->name, "1angx"); // 这里我们直接给name赋值是不是越界访问了,确实是,但是由于在结构体中内存是连续的,name在结构体中,我们的结构体的大小足够大,且level name的内存是连续的
cout << "p3->level:" << p3->level << endl;
cout << "p3->name:" << p3->name << endl;
free(p3);
p3 = NULL;
puts("fun3中,我们就实现了内存连续,且大小为动态的name");
puts("我们通过‘越界访问’实现了这一要求");
}

int main()
{
fun1(); // fun1中确实是利用数组实现了角色名称的创建,但是大小是固定的,不能动态改变
putchar('\n');

fun2(); // fun2中利用指针实现了角色名称的创建,大小是动态的,但是内存是不连续的
putchar('\n');
puts("那我们怎么实现大小是动态的,其在内存空间中的大小也是动态的?\n");
puts("答案:fun3\n");

fun3();

return 0;
}