C语言中指针是记录数据在内存中的地址(习惯上将这个地址叫做指针),可以直接用来操作和获取数据,本文将带你了解常见的C语言指针。
c语言使用&
来获取数据在内存中的地址,使用*
来获取指定地址所对应的数据。在接受指针时,需要特定的指针类型来接受指针变量,一般类型中会带有*
,也就是说*
有两个作用,一个是用来获取特定地址的数据,一个是用来作为指针类型来声明变量。特殊的,对于数组而言,数组名本身就是数组的首地址。
int a = 1; int* a_point = &a; int b = *a; // a == b char str = 'c'; char* str_point = &str; char str1 = *str_point; // str == str1 int list[10] = {1,2,3,4,5,6,7,8,9,0}; // list == &list[0] 数组名就是首元素地址
不同类型的指针类型每次所能在内存操作的数据量有所不同,下图是使用16进制来表示一个4字节的整型数据,对于int*
类型指针每一次可以操作4
(sizeof(int)
)个字节的数据,而char*
类型的指针每一次可以操作1
(sizeof(char)
)个字节的数据。
不同类型指针操作的数据大小
int int_list[10] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; // int_list是int_list的首地址,且类型是int* for(int i=0;i<10;i++){ printf("%d ", *(int_list + i)); } for(int j=0;j<10;j++){ // 这里先将int_list转换成了char*类型的指针,然后再加一 printf("%d ", *(((char*)int_list + j))); }
使用指针可以改变变量在内存中的值,比如像下面这样
int a = 1; int a_point = &a; *a = 2; printf("%d", a); // 2
这种使用指针在全局位置修改一个整型变量的方法是不常用的,更多的是在函数中使用
void add1(int* number){ *number = *number+1; } int a = 1; add1(&a); printf("%d",a); // 2
对于数组而言,数组名本身是一个指针,如果数组中存储的依然是指针的时候,那么这个数组就是指针数组;如果有一个变量指向整个数组的地址,那么这个变量是一个数组指针。总的来说,数组指针是一个指针,它是指向整个数组的指针,指针数组是一个数组,他里面的元素是指针。
「指针数组」
int* list[6] = {1,2,3,4,5,6};
list
是一个6个元素的数组,而里面的数据类型是int*
「数组指针」
int list[6] = {1,2,3,4,5,6}; int (*list_point)[6] = &list;
这里的&list
和list
的值是相同的,但意义是不同的。&list
表示的整个数组的地址,而list
是表示首元素的地址。他使用起来和一般的首地址相加减也有所不同,下面是两种指针获取元素值的方法。
int list[6] = {1,2,3,4,5,6}; int (*list_point1)[6] = &list; // 整个数组的地址 int* list_point2 = list; //首元素地址 for(int i=0; i<6; i++){ printf("%d ",*(*list_point1 + i)); } for(int i=0; i<6; i++){ printf("%d ",*(list_point2 + i)); }
「函数参数设计」
大部分指针会被用在函数中,这是因为在c语言中参数的传递有两种,一种是值传递,一种是地址传递。而对于字符串、数组这样的数据类型,如果传递的是变量名,其本质是属于地址传递的范畴。
int * return_int_list(int* int_list)
对于上面一个函数而言,函数的返回类型是int*
,参数类型是一个int*
,那么在传参的时候可以直接传入一个int
型的数组名,函数内部返回的时候也可以返回一个int
的数组名,就像下面这样。
int list[10]; int* return_list(int* int_list){ return int_list }
在函数中,还有一种参数类型也会用的十分频繁,那就是二级指针。对于一个指针数组而言,在以数组名传参的时候,他的类型就是一个二级指针。具体的可以看下面这个例子
char * names[3] = { "Jack", "Tom", "Tony" }; void print_names(char** names) { for (int i = 0; i < 3; i++) { printf("%s\n", names[i]); } } print_names(names); // names的类型就是char**
「函数指针」
指向函数的指针就是函数指针。他的形式非常有意思,比如下面的一个函数
int add_two_number(int a, int b){ return a+b; }
函数的返回类型是int
,函数的参数是两个都是int
类型,那么他的函数指针形式就是下面这样
int (*func_point)(int,int) = add_two_number;
总结一下的话,形式就是:
[返回类型] (*函数指针名) [(函数参数的类型)]
以上就是关于c语言中常用的指针知识,除了这些,还有结构体指针、动态内存返回的指针,这些内容不再本文进行讲解,有兴趣了解的同学可以私信告诉我,可以后面再写一篇关于c语言指针的文章。