1、指针变量 指针是一个变量,如:int*p; p是一个指针变量
2、变量(的)指针 一个变量的地址。&a
3、 野指针 指向的空间不属于任何指针变量,如:int *p
4、空指针 初始化为0,或NULL, 打印时输出nil, 没有办法检查一个指针是否是野指针,但可以检测出空指针,宁可用空指针,不用野指针
5、悬空指针 所指向的动态申请的内存空间释放后,没有对其赋值为NULL,且程序未退出
6、常(量)指针 表示这个指针是一个指向常量的指针变量,指针指向的对象是常量,那么这个对象不能被更改。const int *a, int const *a
7、 指针常量 指针常量的值是指针,这个值因为是常量,所以不能被赋值。 int *const a;
8、指向常量的指针常量 指向常量的指针常量就是一个常量,且它指向的对象也是一个常量。 const int *const a
9、双(二级)指针 指向指针的指针
10、void*指针(万能指针) 代表任何类型的指针,对此不能用*取变量,可以用类型转换还原类型。经常用于内存的分配。
11、字符串指针: 以""括起来的字符串赋给字符串指针时,字符串指针不能修改其内容,因为其数据是存储在代码区中,不可修改,但可以修改字符串指针的指向。
char *str = "12123"; // const char *str ="12123";
12、指针数组: 存放指针的数组
格式:类型 *p[2] // 首先p与[]结合,表示p是一个数组,再与*结合表示数组里面存放的是地址。
如:int *p[2];
例:
int a = 10;
int b= 11;
int *p[2]; // int *p[2] = {&a, &b}; //p 表式第一个地址元素
p[0] = &a;
p[1] = &b;
printf("%d\n", **p); // *p取出的是p[0]/a的地址,再对取出的地址作*运算,得出地址对应空间的值,
printf("%d\n", *p[0]); //*(*p+0);
printf("%d\n", *p[1]);//*(*p+1);
printf("%d\n", (*p)[2]);
对于操作字符串数组指针时要特别注意,对于一个""括起来的字符串可以当作一个const char*的字符串指针处理,
char *str[2] = {"Hello","world"};
printf("%s\n", str[1]); //*(str+0);
printf("%s\n", str[2]);// *(str+1);
char str1[] = "Hello";
char str2[] = "world";
char *str[] = {str1, str2};
#include <stdio.h>
double add(double x, double y)
{
return x + y;
}
double sub(double x, double y)
{
return x - y;
}
int main()
{
int a = 10;
int b = 20;
int c = 30;
int *p_int[3] = {&a, &b, &c};
*p_int[0] = 11;
*p_int[1] = 22;
*(*p_int+2) = 33;// *p_int[2] = 33;
printf("%d, a = %d\n", *(*p_int+0), a);
printf("%d, b = %d\n", *(*p_int+1), b);
printf("%d, c = %d\n", *(*p_int+2), c);
double (*p_double[2]) (double, double) = {add, sub};
printf("%f\n", p_double[0](20.2, 2.3));
printf("%f\n", p_double[1](22.2, 10.2));
return 0;
}
13、 数组指针: 存放的是含有N个元素的数组的地址
格式: 类型 (*p)[N]; //首先p与*结合,表示p是一个指针,再与[]结合表示p指向的是一个含有N个元素的数组。
int a[2] = {1, 2};
int (*p)[2] = &a; //注意存放一维数组时,要取数组的地址。
printf("%d\n",*(*p+0));
printf("%d\n",*(*p+1));
也可以用指针数组操作二维数组;
int value[3][2] = {{1, 2}, {3, 4}, {5, 6}};
int(*p)[2] = value;
for(int i=0; i<3; i++) {
for(int j=0; j<2; j++) {
printf("%d", *(*(p+i)+j));
}
printf("\n");
}
14、 函数指针: 存储函数的入口地址的指针
格式:类型 (*p)(参数表)
例:
double sum(double a, double b)
{
returna+b;
}
intmain(void)
{
double(*psum)(double, double) = sum;
typedefdouble (*PFUNC)(double,double);
PFUNCf = sum;
// psum = sum;
doubles = psum(1.2, 3.3);
printf("s= %g\n", s);
return 0;
}
#include <stdio.h>
int main()
{
int a[3] = {1, 2, 3};
int (*p)[3] = &a;
*(*p+0) = 11;
*(*p+1) = 12;
*(*p+2) = 13;
printf("a[0] = %d\n", p[0][0]);
printf("a[1] = %d\n", p[0][1]);
printf("a[2] = %d\n", p[0][2]);
int array[3][2] = {{1, 2}, {3, 4}, {5, 6}};
int (*pa)[2] = array;
for (int i=0; i < 3; i++)
{
for (int j =0; j < 2; j++)
printf("%d ", *(*(pa+i)+j));
printf("\n");
}
}
15、 指针函数: 返回值为指针的函数
格式: 类型* 函数名(参数表)
例:
int*swap(int a, int b) {}
16、 const 的用法:
1、修饰除指针以外的所有数据类型时,无论const在数据类型的前面还是后面,都表式变量的内存空间的数据不可修改.即常量
const int m; // int const m;
2、修饰指针变量名时,表式指针变量是常指针,不可再指向其它变量
int* const p = &a // p 不可指向其它变量p = &b //error
3、修饰指针类型时,表式指针不可修改所指向内存空间的数据
const int* p = &a == int const *p;
4、修饰函数形参时,表式在函数内不可修改形参的值。
归根结底:const修饰除指针以外的所有类型时,表式内存空间的数据不可修改;const修饰指针变量名时,表式指针变量的指向不可改变;