diff --git a/README.md b/README.md index 625e53b..832de98 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,5 @@ #### day8: 静态库,动态库,指针 #### day9: 指针高级 + +#### day10: 数组指针,函数与指针,动态内存申请 diff --git a/day10/d1.c b/day10/d1.c new file mode 100644 index 0000000..ad8d9e7 --- /dev/null +++ b/day10/d1.c @@ -0,0 +1,19 @@ +#include + +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; +} \ No newline at end of file diff --git a/day10/d10.c b/day10/d10.c new file mode 100644 index 0000000..bcf9139 --- /dev/null +++ b/day10/d10.c @@ -0,0 +1,25 @@ +#include + +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; +} \ No newline at end of file diff --git a/day10/d11.c b/day10/d11.c new file mode 100644 index 0000000..d0c2c69 --- /dev/null +++ b/day10/d11.c @@ -0,0 +1,42 @@ +#include +#include +#include + +// 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; +} \ No newline at end of file diff --git a/day10/d12.c b/day10/d12.c new file mode 100644 index 0000000..8ebc3a0 --- /dev/null +++ b/day10/d12.c @@ -0,0 +1,46 @@ +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/day10/d13.c b/day10/d13.c new file mode 100644 index 0000000..1d3fcb3 --- /dev/null +++ b/day10/d13.c @@ -0,0 +1,9 @@ +#include +#include + +int main() +{ + char *p = "disen"; + free(p); // 释放常量区的内存,会报错; 因为常量区的内存是只读的 + return 0; +} \ No newline at end of file diff --git a/day10/d14.c b/day10/d14.c new file mode 100644 index 0000000..3516ddd --- /dev/null +++ b/day10/d14.c @@ -0,0 +1,18 @@ +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/day10/d15.c b/day10/d15.c new file mode 100644 index 0000000..ff37872 --- /dev/null +++ b/day10/d15.c @@ -0,0 +1,18 @@ +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/day10/d2.c b/day10/d2.c new file mode 100644 index 0000000..d434c43 --- /dev/null +++ b/day10/d2.c @@ -0,0 +1,35 @@ +#include +#include + +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"); + } +} \ No newline at end of file diff --git a/day10/d3.c b/day10/d3.c new file mode 100644 index 0000000..9ff7114 --- /dev/null +++ b/day10/d3.c @@ -0,0 +1,15 @@ +#include +#include + +int main() +{ + int a[5]; + int *p = a; + int(*q1)[5] = &a; + int **q2 = &p; + + // uintptr_t 是 C 语言标准库 中定义的一个无符号整数类型,它的大小足够存储指针值。因此, % 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; +} \ No newline at end of file diff --git a/day10/d4.c b/day10/d4.c new file mode 100644 index 0000000..087fb5f --- /dev/null +++ b/day10/d4.c @@ -0,0 +1,43 @@ +#include +#include + +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++; + // } +} \ No newline at end of file diff --git a/day10/d5.c b/day10/d5.c new file mode 100644 index 0000000..2210580 --- /dev/null +++ b/day10/d5.c @@ -0,0 +1,16 @@ +#include + +void change(int *p) +{ + *p += 10; +} + +int main() +{ + int x = 10; + change(&x); + + printf("x = %d\n", x); + + return 0; +} \ No newline at end of file diff --git a/day10/d6.c b/day10/d6.c new file mode 100644 index 0000000..e582c0d --- /dev/null +++ b/day10/d6.c @@ -0,0 +1,19 @@ +#include + +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; +} \ No newline at end of file diff --git a/day10/d7.c b/day10/d7.c new file mode 100644 index 0000000..4e01d19 --- /dev/null +++ b/day10/d7.c @@ -0,0 +1,19 @@ +#include + +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; +} \ No newline at end of file diff --git a/day10/d8.c b/day10/d8.c new file mode 100644 index 0000000..35b8eb3 --- /dev/null +++ b/day10/d8.c @@ -0,0 +1,21 @@ +#include + +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; +} \ No newline at end of file diff --git a/day10/d9.c b/day10/d9.c new file mode 100644 index 0000000..8d612f7 --- /dev/null +++ b/day10/d9.c @@ -0,0 +1,29 @@ +#include + +// 查找数组中的元素并替换为特定值 +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"); + } +} \ No newline at end of file