一、概念
简单的来说,指针就是地址。我们口头上说的指针其实指的是指针变量。指针变量就是一个存放地址的变量。
从语法的角度看,只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。
(1)int*p; //指针的类型是int*
(2)char*p; //指针的类型是char*
(3)int**p; //指针的类型是int**
当指针保存了保存了变量地址,我们称指针指向该变量。
* 是指针运算符,单目运算符,优先级为二级,结合方向是自右向左。
当我们在定义一个指针时:int *p;这里的 * 只是说明p是指针类型,并无指针运算。
指针的主要功能是通过被调函数修改主调函数。
void fn(int *p)
{
*p += 1;
}
指针在程序中只干三件事:
1.根据指针变量中的值到内存中定位。
2.从定位处开始向后偏移sizeof(基类型)
3.整体的将偏移好的那部分内存当作是一个基类型的变量。
*p总是要与基类型的类型匹配。
野指针与疯指针:是指对未经初始化的变量进行指针运算,其指向的位置不可知。当使用指针对数组越界访问时也会出现野指针,导致程序崩溃。
在做关系运算时:&*与*&总是可以相互抵消,但是要注意的点是:*运算要求其对象必须是指针。
int i = 10;
int *p = &i;
printf("%p\n", &*p);
printf("%d\n", *&i);
printf("%p\n", *&p);
//X printf("%d\n", &*i);
当我们在定义了一个指针后,写出下代码:
int *p;
p + n;
其并不是在原有的地址上加n,而是在原有的地址上加 n * sizeof(基类型)。
空指针:在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 。 赋为 NULL 值的指针被称为空指针。 *p = NULL 是将指针置空,是一种状态。
指针与指针之间是无法进行加法运算的,但是可以进行减法运算,但是求差的时候指针的基类型必须相同。求差的结果是指两个指针之间差了多少个基类型,结果可正可负,负数的含义就是地址在前。
int a[] = {1,2,3,4,5,6,7,8,9,0};
int *p = a;
int *q = a + 2;
printf("%ld\n" ,p - q);
const的作用:
1.当const加在变量之前时,表示该变量为只读变量,只可读取,不可更改。
2.当const加在指针前时:如const int *p表示不能通过该指针修改其所指向的的变量。当是
int const *p时,表示指针不可更改。
void* 为万能指针,不能作为指针进行指针运算。
二、指针的使用
1.通过指针的方式实现求三个数的最大值
void maxOfTwoNumbers(int a, int b, int *pMax)
{
*pMax = a > b ? a : b;
}
void maxMinOfThreeNumbers(int a, int b, int c, int *pMax, int *pMin)
{
*pMax = a > b ? a : b;
*pMax = *pMax > c ? *pMax : c;
*pMin = a < b ? a : b;
*pMin = *pMin < c ? *pMin : c;
}
2.通过指针的方式交换两个数
void swap(int *a, int *b)
{
int k;
k = *a;
*a = *b;
*b = k;
}
3.实现对大端存储与小端存储的判断
int i = 0x12345678;
char *p;
p = (char *)&i;
if(1 == *p)
{
puts("little");
}
else
{
puts("big");
}
4.通过指针实现对一维数组的遍历
void printArray(int *a, int len)
{
int i;
for(i = 0;i < len;++i)
{
printf("%d\n", *(a + i));
}
}
5.通过指针实现对一维数组求和
int sumOfArray(int *a, int len)
{
int sum = 0, i;
for(i = 0;i < len;++i)
{
sum += *(a + i);
}
return sum;
}
6.通过指针实现对一维数组的逆序
void reverse(int *a, int len)
{
int i;
for(i = 0;i < len / 2;++i)
{
swap(a + i, a + len - i - 1);
}
}
7.通过指针对一维数组排序(选择排序)
void sort(int *a, int len)
{
int i, j;
for(i = 0;i < len - 1;++i)
{
for(j = i + 1;j < len;++j)
{
if(*(a + i) > *(a + j))
{
swap(a + i, a + j);
}
}
}
}
8.通过指针的方式实现对一维数组的二分查找
int *binaryFind(int *a, int len, int n)
{
int begin = 0;
int end = len - 1;
while(begin <= end)
{
int mid = (begin + end) / 2;
if(*(a + mid) < n)
{
begin = mid + 1;
}
else if(*(a + mid) > n)
{
end = mid - 1;
}
else
{
return a + mid;
}
}
return NULL;
}
9.通过递归与指针实现数组遍历
void printArray(int *begin, int *end)
{
if(begin > end)
{
return ;
}
else
{
printf("%d\n", *begin);
printArray(begin + 1, end);
}
10.使用递归与指针实现数组逆序
void reverse(int *begin, int *end)
{
if(begin >= end)
{
return ;
}
else
{
swap(begin, end);
reverse(begin + 1, end - 1);
}
11.通过指针实现对数组的选择排序
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);
}
}
}
}
12.通过指针与递归实现快速排序
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 && *q >= t)
{
--q;
}
while(p < q && *p <= t)
{
++p;
}
swap(p, q);
}
swap(begin, p);
qSort(begin, p - 1);
qSort(p + 1, end);
}
13.puts
void Puts(const char *s)
{
while(*s)
{
putchar(*s++);
}
putchar('\n');
}
14.strle
int Strlen(const char *s)
{
if(*s == '\0')
{
return 0;
}
else
{
return Strlen(s + 1) + 1;
}
15.strcpy与Memcpy
char *Strcpy(char *dest,const char *src)
{
char *ret = dest;
while(*src)
{
*dest++ = *src++;
}
*dest = 0;
return ret;
}
void *Memcpy(void *dest, const void *src, unsigned long n)
{
char *p = (char *)dest;
char *q = (char *)src;
while(n)
{
*p++ = *q++;
--n;
}
return dest;
}
16.strcat与strncat
char *Strcat(char *dest, const char *src)
{
char *ret = dest;
while(*dest)
{
++dest;
}
while(*src)
{
*dest++ = *src++;
}
*dest = 0;
return ret;
}
char *Strncat(char *dest, const char *src, unsigned long n)
{
char *ret = dest;
while(*dest++)
{
}
while(*src && n)
{
*dest++ = *src++;
--n;
}
*dest = 0;
return ret;
}
17.strcmp与strncmp
int Strcmp(const char *s1, const char *s2)
{
while(*s1 == *s2 && *s1 && *s2)
{
++s1;
++s2;
}
return *s1 - *s2;
}
int Strncmp(const char *s1, const char *s2, unsigned long n)
{
while(--n && *s1 == *s2 && *s1 && *s2)
{
++s1;
++s2;
}
return *s1 - *s2;
}