1. <>和“”引用区别

  • #include <> 主要用于对标准库的引用
  • #include “” 主要用于对自定义本地库的引用

2. 指针函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

void add(int i, int j) {
printf("result : %d \n", i + j);
}

void test(void(*p)(int, int)) {
p(1, 2); // p被明确声明为函数指针,可以省略*
(p)(1, 2); // p被明确声明为函数指针,可以省略*
(*p)(1, 2);
}

int main() {
test(add);
return 0;
}

3.文档查看

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
// 查看文档方法中有 &xxxx 可以尝试传NULL试试
srand((unsigned) time(NULL));
for (int i = 0; i < 10; i++) {
printf("rand num: %d \n", + rand() / 100);
}
return 0;
}

4. 静态内存和动态内存

静态内存(栈内开辟内存)和动态内存开僻(使用malloc开辟内存)。

4.1 栈上分配内存
1
2
3
4
5
// 调用执行会入栈
void staticMem() {
int arr[5]; //在栈空间分配20字节内存
} // 执行完毕会出栈
// 每次开辟/释放20字节
4.2 堆上分配内存
  • 野指针:没有指向的指针。指针不使用了需要指向NULL。
  • 悬空指针:当堆内存释放之后,指针指向的地址还在,这就形成了悬空指针。当堆内存空间被释放之后,需要将指针指向NULL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>

void dynamicMem() {
// int *p; // 野指针
int *p = NULL; // 规范写法

int *arr = malloc(1 * 1024 * 1024); // 1M
// &arr取栈上地址, arr堆上的地址
printf("stack addr: %p , deap addr: %p \n", &arr, arr);

free(arr); //如果不释放,内存地址会一直添加
arr = NULL; // 如果不指向NULL,会出现 “悬空指针”

printf("stack addr: %p , deap addr: %p \n", &arr, arr);
}

int main() {
for (int i = 0; i < 5; ++i) {
dynamicMem();
}

return 0;
}

5.堆上空间分配使用场景

5.1 开辟可变空间(malloc)
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
#include <stdio.h>
#include <stdlib.h>

int main() {
int num;
printf("please insert the count of the number: \n");

scanf("%d", &num);

int *arr = (int *) malloc(sizeof(int) * num);

for (int i = 0; i < num; ++i) {
int insert_num;
printf("please insert No.%d :", (i + 1));
scanf("%d", &insert_num);
arr[i] = insert_num;
// *(arr + i) == arr[i]
printf("your number is: %d , the addr: %p\n", *(arr + i), arr + i);
}

if (arr) {
free(arr);
arr = NULL;
}
return 0;
}
5.2 在原来分配的基础上继续再分配
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
#include <stdio.h>
#include <stdlib.h>

int main() {
int num;
printf("please insert the count of the number: \n");

scanf("%d", &num);

int *arr = (int *) malloc(sizeof(int) * num);

for (int i = 0; i < num; ++i) {
int insert_num;
printf("please insert No.%d :", (i + 1));
scanf("%d", &insert_num);
arr[i] = insert_num;
// *(arr + i) == arr[i]
}
for (int i = 0; i < num; ++i) {
printf("your number is: %d , the addr: %p\n", *(arr + i), arr + i);
}

// 在原基础上新增加空间
printf("please insert the count of the new memory: \n");
int newMem;
scanf("%d", &newMem);

// realloc第一个参数传入指针是为了防止分配内存不够时,系统会重新开辟一个连续的空间,然后把以前地址(arr)的数据拷贝过来。
int *newArr = (int *) realloc(arr, sizeof(int) * (num + newMem));
if (newArr) {
for (int i = num; i < num + newMem; ++i) {
int insert_num;
printf("please insert No.%d :", (i + 1));
scanf("%d", &insert_num);
newArr[i] = insert_num;
}
for (int i = 0; i < num + newMem; ++i) {
printf("your number is: %d , the addr: %p\n", *(newArr + i), newArr + i);
}
}

if (newArr) {
// 开辟成功了释放新内存空间,包含了旧地址空间
free(newArr);
newArr = NULL;
arr = NULL;
} else {
// 没成功释放旧内存即可
free(arr);
arr = NULL;
}

return 0;
}