对指针进行加法运算,及p+n,其结果依旧是一个指针,新的指针是在原来的地址值基础上加上n(sizeof(基类型))个字节。
当(*p)++,表达的是首先*p指的是啊a[0]的值然后进行++运算,此时数组变为22345.....当为*p++时先进行++运算表达式没有加但是值加了,再进行指针运算,最后指针会指向a[1]。
返回值为指针的函数也叫指针函数,可以返指针但不能返数组,空的话返回null。
在C++中,迭代器是一种泛化的指针,用于访问容器中的元素。在C语言中,指针可以模拟迭代器的功能,实现数组的遍历和操作。通过begin和end指针可以定义一个范围,遍历该范围内的所有元素。
int *p; p = a;在此代码中,指针变量可以++运算,a不是指针变量不可以++运算。
指针与指针不能求和,但可以做减法运算,最终代表两个地址之间差了几个基类型 ,但必须相互运算的类型一致。
如果数组指针为int型,则指针变量的基类型也为int型, p = &a[0], 把a[0]元素的地址赋给指针变量p,也就是使p指向a数组的第0号元素。(p = &a[0]; p = a;两句等价。)
如果指针变量p指向数组中的一个元素,则p+1指向同一数组下的一个元素,而不是将值简单的加一。
字符串函数的指针实现实现字符串函数(如puts、strlen)时,可以使用字符指针代替数组下标。puts函数通过循环打印字符指针指向的字符,直到遇到'\0'。strlen函数通过指针逐个递增,统计字符个数直到遇到'\0'。字符串常量可以作为函数参数传递,其本质是传递首字符的地址。
指针与数组的sizeof和strlen区别sizeof(s)返回数组s的总字节数,而strlen(s)返回字符串有效字符个数(不包括'\0')。对于字符指针p,sizeof(p)返回指针大小(通常为8字节),而strlen(p)返回字符串有效字符个数。比如char s[100] = "hello"; sizeof(p); p = s;则sizeof(p) = 8,sizeof(s)= 100;strlen(s) = 5; 如果是strlen(p),传的是&s[0],所以还是5.
指针与数组的遍历
- 可以通过定义两个指针(如begin和end)来实现数组的遍历。
- 遍历时使用循环,条件为begin小于等于end,循环体内访问当前元素并移动指针。
- 这种方式不需要下标变量,仅通过指针操作即可完成数组的遍历。
void printfarray(int *begin, int *end)
{
//while(begin <= end)
//{
//printf("%d\n",*begin);
//++begin;
//}
if(begin > end)
{
return ;
}
else
{
printf("%d\n", *begin);
printfarray(begin + 1, end);
}
}
这个函数 qSort
是实现快速排序,快速排序基于递归和指针操作,时间复杂度为O(N log N)。核心思想是选择一个基准数,将数组分为两部分,一部分比基准数小,另一部分比基准数大。通过左右指针从数组两端向中间扫描并交换元素,最终将基准数放到正确位置。递归处理左右两部分,直到整个数组有序。
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
void qSort(int *begin, int *end)
{
if(begin >=end)
{
return ;
}
int t = *begin;
int *p = begin;
int *q = end;
while(p < q)
{
while(p < q && *p >= t)
{
--q;
}
while(p < q && *q <= t)
{
++p;
}
swap(p, q);
}
swap(begin, p);
qSort(begin ,p - 1);
qSort(p + 1, end);
}
函数 server
实现了一个递归的两端扫描的交换操作,移动 begin
指针向后,end
指针向前,然后重复交换进行逆序操作。注释的是迭代操作,下面的是递归。第三个是常规逆序。
void server(int *begin, int *end)
{
//while(begin < end)
//{
//swap(begin, end);
//++begin;
//--end;
//}
if(begin >= end)
{
return ;
}
else
{
swap(begin,end);
server(begin + 1, end - 1);
}
}
第一段代码是一个递归两数大小进行交换的代码,选择排序。在每轮循环找到范围最小的元素放在前面,swap(begin, p)
在找到比*begin
更小的元素时,交换它们。冒泡将未排序部分中的最大元素移动到末端。
void choicesort(int *begin,int *end)
{
int *p;
for(; begin < end; ++begin)
{
for(p = begin + 1; p <= end; ++p)
{
if(*begin > *p)
{
swap(begin,p);
}
}
}
}
void maopasort(int *begin, int *end)
{
int *p;
int *q;
for(p = end; p > begin; --p)
{
for(q = begin; q < p; ++q)
{
if(*q > *(q + 1))
{
swap(q, q + 1);
}
}
}
}
两段实现 二分查找(Binary Search)的代码:binarfind
和 binary
。它们的功能都是在有序数组中查找某个元素 n
,但实现方式不同:一段是迭代版本,一段是递归版本。
int *binarfind(int *begin, int *end, int n)
{
while(begin <= end)
{
int *mid = (end - begin) / 2 + begin;
if(*mid > n)
{
end = mid - 1;
}
else if(*mid < n)
{
begin = mid + 1;
}
else
{
return mid;
}
}
return NULL;
}
int *binary(int *begin,int *end,int n)
{
if(begin > end)
{
return NULL;
}
int *mid = (end - begin) / 2 + begin;
if(*mid > n)
{
end = mid - 1;
}
else if(*mid < n)
{
begin = mid + 1;
}
else
{
return mid;
}
binary(begin,end,n);
}
逐个字符地打印传入的字符串s
,直到遇到字符串的结束符('\0'
)。每打印一个字符,就会将指针+1
,移动到下一个字符。第二个函数用来计算字符串s
的长度,也就是字符串中字符的个数(不包括字符串结束符'\0'
)。
void Puts(char *s)
{
while(*s != '\0')
{
putchar(*s);
++s;
}
putchar('\n');
}
int Strlen(char *s)
{
int counter = 0;
while(*s)
{
++s;
++counter;
}
return counter;
}