一、字符指针
字符指针可以定义为
char *p
,
并可以指向单个字符或字符串。通过 *p
可以访问指针 p
所指向的字符,而 p = &c
可以让指针 p
指向字符变量 c
的地址。
指向字符串时,如 char str[] = "Hello, world!"; char *p = str;
,指针 p
指向字符串的第一个字符,即存储第一个字符的地址。
字符指针可以用于遍历和修改字符串,通过指针运算(如 p++
或 p += 7
)可以移动指针访问数组中的其他元素。
在遍历字符串时,通常通过 while (*p != '\0')
进行,直到遇到字符串的终止符 '\0'
。修改字符串内容时,可以直接通过指针进行。
指向常量字符串的指针(如 const char *p = "Hello, world!";
)不允许通过指针修改字符串内容。
const修饰普通变量时,表示此变量不可以通过直接访问的形式进行修改,但是可以通过指针间接访问进行修改其内容。
const修饰指针时,作用的不是指针本身,而是指针指向的数据。
二、万能指针
万能指针是一种特殊类型的指针,可以指向任何数据类型。
万能指针被定义为
void *
它可以指向不同类型的数据,例如 `int`、`float` 或 `char` 等。
万能指针需要通过类型转换才能指向的数据,例如将 `void *ptr` 转换为 `int *` 类型后再进行指针运算。
在函数中,万能指针常用于处理不同类型的参数,通过额外的类型标志参数区分数据类型。
使用万能指针时需特别注意以下几点:万能指针不支持指针运算,因为它没有类型信息;类型转换时必须确保转换后的类型与实际数据类型匹配,否则可能导致未定义行为。
在实际编程中,万能指针可以提高代码的灵活性和通用性,但使用时需要谨慎,确保类型安全。
快速排序:其基本思想是通过一个“分区”过程,将待排序的数组分成两个子数组,其中一个子数组中的所有元素都比另一个子数组中的所有元素小。然后递归地对这两个子数组进行排序,从而达到整个数组有序的效果。
步骤:
-
选择基准: 选择数组中的一个元素作为基准。例如,如果选择第一个元素作为基准。
-
分区过程:
- 使用两个指针,一个从数组的开始位置向右移动(
i
),另一个从数组的结束位置向左移动(j
)。 - 移动指针找到左边比基准大的元素和右边比基准小的元素,然后交换它们。
- 当两个指针相遇时,基准元素与当前指针相遇的元素交换,使基准元素处于其最终位置。
- 使用两个指针,一个从数组的开始位置向右移动(
-
递归排序:
- 将分区后的左右两个子数组分别递归地进行快速排序。
示例代码:
void qSort(int *begin, int *end)
{
if(begin >= end)
{
return ;
}
int t = *begin;
int *p = begin,*q = end;
while(p < q)
{
while(p < q && *q >= t)
{
--q;
}
while(p < q && *p <= t)
{
++p;
}
swap(p,q);
}
swap(begin,p);
qSort(begin, p - 1);
qSort(p + 1,end);
}
三、动态分配内存
动态内存分配是指在程序运行时根据需要分配和释放内存,提供了更灵活的内存管理方式。
1.malloc函数:从堆区划分出指定大小的连续内存,并返回分配好的堆区空间 的首地址。,分配失败,则返回NULL;
void *malloc(size_t size);
2.calloc函数:分配指定数量的内存块,并将它们初始化为零
void *calloc(size_t num, size_t size);
3.realloc函数:调整先前分配的内存块的大小,可以扩大或缩小内存块。如果扩大内存块,新分配的内存内容不确定、
void *realloc(void *ptr, size_t size);
4.free函数 :释放先前分配的内存块
void free(void *ptr);
使用 `malloc` 和 `calloc` 需要检查返回的指针是否为 `NULL` 以确保内存分配成功。
`malloc` 用于分配指定大小的内存块,例如 `int *arr = (int *)malloc(5 * sizeof(int));`,
`calloc` 分配的内存初始化为零,例如 `int *arr = (int *)calloc(5, sizeof(int));`。
`realloc` 用于调整已经分配的内存大小,例如 `arr = (int *)realloc(arr, 10 * sizeof(int));`,
如果重新分配失败,原内存块仍然需要释放。
使用完动态分配的内存后,必须使用 `free` 函数释放内存以避免内存泄漏,例如 `free(arr);`。
动态内存分配的过程中要注意避免内存泄漏、检查空指针、防止使用已释放的指针。
通过动态分配内存 的方式 存储斐波那契数列的前十项:
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
int n = 10;
int *p = malloc(n * sizeof(int)); //申请内存
if(p == NULL)
{
return -1;
}
else
{
for(int i = 0 ; i < n ; ++i)
{
if( i == 0 || i == 1)
{
*(p + i ) = 1;
}
else
{
*(p + i) = *(p + i - 2) + *(p + i - 1);
}
}
}
for(int i = 0 ; i < n ; ++i)
{
printf("%d ", *( p + i));
}
puts("");
free(p); //释放内存
p = NULL;//检查指针
}