day10 coding: 指针, 函数与指针,动态内存申请

This commit is contained in:
flykhan 2023-07-15 10:00:28 +08:00
parent 74ddf49c45
commit 07358e7842
16 changed files with 376 additions and 0 deletions

View File

@ -11,3 +11,5 @@
#### day8: 静态库,动态库,指针
#### day9: 指针高级
#### day10: 数组指针,函数与指针,动态内存申请

19
day10/d1.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdio.h>
int main()
{
int arr[3][4] = {1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 11, 12};
// arr 表示第 0 行的地址, arr[0] 表示第 0 行的地址
int *p = arr[0]; // p 表示第 1 行的地址
for (int j = 0; j < 3; j++)
{
for (int i = 0; i < 4; i++)
{
printf("%d ", *(p + i));
}
printf("\n");
p += sizeof(arr[0]) / sizeof(arr[0][0]);
}
return 0;
}

25
day10/d10.c Normal file
View File

@ -0,0 +1,25 @@
#include <stdio.h>
void show(char *q[], int n)
// void show(char **q, int n) // char **q == char *q[]
{
for (int i = 0; i < n; i++)
{
while (*(*(q + i))) // 当本行字符串没有结束时
{
printf("%c", *(*(q + i))++); // q[i] == *(q + i)
}
printf("\n");
}
}
int main()
{
// names 内容存在栈区names[0] 存放的是字符串的首地址
// "disen" 是常量,存在常量区,"disen" 的首地址存在栈区
// 常量区的内容不能修改
char *names[3] = {"disen", "rose", "jack"};
show(names, 3);
return 0;
}

42
day10/d11.c Normal file
View File

@ -0,0 +1,42 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// int rands[10]; // 全局变量处理方式
void *rand_arr(int size, int min, int max)
{
srand(time(NULL));
// 使用 malloc 分配内存,因为函数返回的指针是局部变量,会被释放
// 而当使用 malloc 分配内存时,内存会一直存在,直到程序结束
// malloc 存放在内存的堆区,而局部变量存放在内存的栈区
// 堆区的内存需要手动释放,栈区的内存会自动释放
int *rands = (int *)malloc(sizeof(int) * size);
// int rands[size]; // 对照上面的处理方式
// static int rands[size]; // 静态变量处理方式,但是变长数组不能使用静态变量
for (int i = 0; i < size; i++)
{
rands[i] = (rand() % (max - min + 1)) + min;
}
return rands;
}
int main()
{
int *nums = (int *)rand_arr(10, 3, 12);
for (int i = 0; i < 10; i++)
{
printf("%d ", *(nums + i));
}
printf("\n");
printf("free nums\n");
free(nums);
for (int i = 0; i < 10; i++)
{
printf("%d ", *(nums + i));
}
printf("\n");
return 0;
}

46
day10/d12.c Normal file
View File

@ -0,0 +1,46 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *input_score(int size)
{
int *arr = (int *)malloc(sizeof(int) * size);
memset(arr, 0, sizeof(int) * 5); // 将 scores 指向的内存清零0
for (int i = 0; i < size; i++)
{
printf("请输入第 %d 个学生的成绩: ", i + 1);
scanf("%d", arr + i);
}
return arr;
}
int main()
{
int *scores = input_score(5);
// scores = NULL 的判断是必须的,因为 malloc 分配内存失败时,会返回 NULL
if (scores == NULL)
{
printf("内存分配失败\n");
return 1;
}
for (int i = 0; i < 5; i++)
{
printf("%d ", *(scores + i));
}
printf("\n");
printf("R%p\n", scores);
free(scores); // 释放后,打印的前两个值是随机的,因为内存已经被释放了,但是后面的值还在,所以还能打印出来
// free(scores); // 重复释放内存,会报错;一个指针只能释放一次内存
printf("R%p\n", scores);
for (int i = 0; i < 10000000; i++)
;
for (int i = 0; i < 5; i++)
{
// 会报错,因为 scores 指向的内存已经被释放了
// free(scores + i); // 释放指针数组中的每一个元素 malloc 分配的内存
printf("%d ", *(scores + i));
}
printf("\n");
return 0;
}

9
day10/d13.c Normal file
View File

@ -0,0 +1,9 @@
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p = "disen";
free(p); // 释放常量区的内存,会报错; 因为常量区的内存是只读的
return 0;
}

18
day10/d14.c Normal file
View File

@ -0,0 +1,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// malloc(30) 申请大小为 30 字节的内存空间,返回的是这块内存空间的首地址
char *p = (char *)malloc(30);
strcpy(p, "hi, disen");
printf("%s, p->%p, last p->%p\n", p, p, p + 8);
free(p); // free 后,变为野指针,指向的内存空间已经被释放了
// free 之后p 指针指向的内存空间已经被释放了,但是 p 指针本身的地址没有变
p = (char *)malloc(10);
memset(p, 'A', 10);
printf("%s, p->%p\n", p, p);
return 0;
}

18
day10/d15.c Normal file
View File

@ -0,0 +1,18 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// malloc(30) 申请大小为 30 字节的内存空间,返回的是这块内存空间的首地址
char *p = (char *)malloc(30);
strcpy(p, "hi, disen");
printf("%s, p->%p, last p->%p\n", p, p, p + 8);
free(p); // free 后,变为野指针,指向的内存空间已经被释放了
// free 之后p 指针指向的内存空间已经被释放了,但是 p 指针本身的地址没有变
p = (char *)ralloc(p, 10);
memset(p, 'A', 10);
printf("%s, p->%p\n", p, p);
return 0;
}

35
day10/d2.c Normal file
View File

@ -0,0 +1,35 @@
#include <stdio.h>
#include <stdint.h>
int main()
{
int m[3][5] = {{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15}};
// 数组指针
int(*p)[5] = m; // 5 表示每行有 5 个元素,*p 表示第 0 行的地址
int(*p2)[5] = m + 2;
printf("%p\n", p2);
printf("%p\n", p);
uintptr_t ret2 = (uintptr_t)p2 - (uintptr_t)p; // uintptr_t 无符号整型 // 除以每个元素的大小
int ret = p2 - p; // 原理: (m + 2) - m = 2
printf("%d\n", ret2); // 2
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
printf("第 %d 行第 %d 列的地址: %p\n", i, j, *(p + i) + j);
scanf("%d", *(p + i) + j); // *(p + i) + j 表示第 i 行第 j 列的地址
}
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
printf("%d ", *(*(p + i) + j));
printf("\n");
}
}

15
day10/d3.c Normal file
View File

@ -0,0 +1,15 @@
#include <stdio.h>
#include <stdint.h>
int main()
{
int a[5];
int *p = a;
int(*q1)[5] = &a;
int **q2 = &p;
// uintptr_t 是 C 语言标准库<stdint.h> 中定义的一个无符号整数类型,它的大小足够存储指针值。因此, % lu 格式说明符用于打印 uintptr_t 类型的变量。 printf("q1=%p, &q1+1=%p, len = %lu\n", q1, q1 + 1, (uintptr_t)(q1 + 1) - (uintptr_t)q1);
printf("q2=%p, &q2+1=%p, len = %lu\n", q2, q2 + 1, (uintptr_t)(q2 + 1) - (uintptr_t)q2);
return 0;
}

43
day10/d4.c Normal file
View File

@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdint.h>
int main()
{
int a[2][3] = {1, 2, 3, 4, 5, 6};
int(*p)[3] = a;
int **q = &p;
int i = 0;
// while (i < 2)
// {
// int j = 0;
// while (j < 3)
// {
// // printf("%d ", *(p[i] + j));
// printf("%d ", *(*(p + i) + j));
// j++;
// }
// printf("\n");
// i++;
// }
printf("q = %lu\n", q);
printf("*q = %lu\n", *q);
printf("(*q + 1) = %lu\n", (*q + 1));
printf("(*q + 1) - *q = %lu\n", (uintptr_t)(*q + 1) - (uintptr_t)*q);
printf("*(*q + 1) = %lu\n", *(*q + 5));
printf("--------------------");
printf("\n");
printf("**q = %lu\n", **q);
printf("*(*q + 1) = %lu\n", *(*q + 1));
printf("p = %lu\n", p);
printf("&p = %lu\n", &p);
printf("&p + 1 = %lu\n", &p + 1);
// while (i < 6)
// {
// printf("%d ", *(*q + i));
// i++;
// }
}

16
day10/d5.c Normal file
View File

@ -0,0 +1,16 @@
#include <stdio.h>
void change(int *p)
{
*p += 10;
}
int main()
{
int x = 10;
change(&x);
printf("x = %d\n", x);
return 0;
}

19
day10/d6.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdio.h>
void change(char *p)
{
printf("change %s, p = %p\n", p, p);
p = "jack"; // p 的 char * 指针可以理解为是一个字符串的常量
printf("change %s, p = %p\n", p, p);
p = "D";
printf("change %s, p = %p\n", p, p);
}
int main()
{
char *name = "disen";
change(&name); // 属于地址传递
printf("name = %s, name 地址 = %p\n", name, name);
return 0;
}

19
day10/d7.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdio.h>
void change(char **p)
{
printf("change %s, p = %p\n", *p, p);
*p = "jack"; // p 的 char * 指针可以理解为是一个字符串的常量
printf("change %s, p = %p\n", *p, p);
*p = "D";
printf("change %s, p = %p\n", *p, p);
}
int main()
{
char *name = "disen";
change(&name);
printf("name = %s, name 地址 = %p\n", name, &name);
return 0;
}

21
day10/d8.c Normal file
View File

@ -0,0 +1,21 @@
#include <stdio.h>
int max(int *p, int size)
{
int m = *p; // 默认为第一个元素是最大
for (int i = 1; i < size; i++)
{
if (m < *(p + i))
m = *(p + i);
}
return m;
}
int main()
{
int a[3] = {1, 5, 2};
int m = max(a, 3); // a 表示第一个元素的地址
printf("m max %d\n", m);
return 0;
}

29
day10/d9.c Normal file
View File

@ -0,0 +1,29 @@
#include <stdio.h>
// 查找数组中的元素并替换为特定值
void findReplace(int rows, int cols, int (*p)[cols], int oval, int nval)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (*(*(p + i) + j) == oval)
*(*(p + i) + j) = nval;
}
}
}
int main()
{
int a[3][3] = {1, 2, 3, 4, 1, 6, 1, 8, 9};
int(*q)[3] = a;
findReplace(3, 3, q, 1, 9);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
}