日记大全

日记大全 > 句子大全

千字长文 用通俗易懂的方式让你读懂什么是C语言指针(值得收藏)

句子大全 2010-07-08 19:13:03
相关推荐

什么是指针?

在计算机里讲的指针它就是内存地址(内存编号);

在了解各类指针前,先了解什么是指针变量?其实就是存放指针(内存地址)的变量,同时不管什么类型的指针,大小只和系统编译器有关系;

如何分析定义指针?

*与星花符号结合代表是一个指针变量,想保存谁的地址,将它的定义形式放在此处,同时用*p替换掉定义的变量。

比如 int *p;

以上的p就是变量,p的类型是将变量p本身抹掉,剩下的类型就是指针变量的类型 int*。如果指针变量p 用来保存什么样类型数据的地址,就是将指针变量p和指针变量p最近的*星花一同抹掉后剩下的是什么类型就保存什么类型数据的地址。

#备注: *p = 100; //在使用时,*与p结合代表,取p指针所指向那块空间的内容;

以下代码结果得到的就是200;

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(){ int num = 100; int *p = # *p = 200; printf("%d\n", num); // 200 return 0;}

提示:在使用的时候注意对一个表达式若取*, 就会对表达式减一级*, 如果对表达式取&, 就会加一级*。

常见形式的指针有哪些?

什么是野指针?

所谓的野指针就是没有初始化过的指针,在写程序代码的时候,这种情况要避免,因为指针的指向是随机性的,所以指针p保存的地址一定是你向系统申请过的,否则不可以操作。比如以下代码,运行就会崩掉:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>// 有问题的代码int main(){ int *p; *p = 1; printf("%d\n", *p); return 0;}

什么是空指针?

所谓空指针,一般使用场景在使用完指针后将指针赋值为NULL的形式,可以在使用时进行判断一下指针是否为NULL,可以知道指针有没有被使用过,一般写程序最好习惯性加上;

什么是万能指针?

见名思义,所谓的万能就是可以保存任意地址的指针,使用的时候有一些注意的地方,用代码演示如下,看注释部分:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>int main(){ int num1 = 1; double num2 = 2.2; void *p = (void *)&num1; void *pp = (void *)&num2; //printf("%d\n", *p); // 这是错误的 因为p的类型是void*,系统编译器不知道要取多少个字节的大小 printf("%d\n", *(int *)p); // *(int *)地址 printf("%lf\n", *(double *)pp); // *(double *)地址 return 0;}

const修饰的指针有哪些问题?

关于const修饰的是*还是变量,两者有什么区别?以代码形式演示,主要看注释:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>int main(){ int num1 = 1; int num2 = 2; /* // 1.const修饰的是* const int *p = &num1; *p = 100; // 会报错,因为const修饰的是*,所以不能通过*p,改p所指向空间的内容 // 2.const修饰的是变量p int * const p = &num1; // p保存的地址不可以被修改 p = &num2; // 会报错,因为const修饰的是变量p,所以p本身的值不能被更改 */ return 0;}

什么是多级指针?

定义多级指针有哪些需要注意的?

定义多级指针保存数据地址的时候,所定义的指针类型只需比要保持的数据的类型多一级*星花,如下图所示:

用代码表示如下:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>int main(){ int a = 10; int *b = &a; int **c = &b; int ***d = &c; printf("%d\n", ***d); // 10 return 0;}

数组与指针的关系

有个注意的问题:对首元素地址加*星花是取首元素的内容。指针加1,跨过一个步长,如int *p,步长表示为:sizeof(int)。要得到内存的数据,就该先得到数据的地址,在地址前面加*星花,*(地址) 得到的是地址里面的内容;代码如下所示:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>int main(){ int arr[5] = { 0 }; // arr为数组名,也为首元素的地址 int *p = arr; // 指针p保存的是首元素的地址 for (int i = 0; i<sizeof(arr) / sizeof(arr[0]); i++) { *(p + i) = i; printf("%d ", *(p + i)); // 通过p+i之后取*星花得到i的值; } return 0;}

指针如何运算?

这里运算的问题也有注意的地方:比如两指针相减(前提类型要一致),得到的是中间跨过多少个元素,而两个指针相加是没有任何意义的;代码如下所示:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>int main(){ int arr[] = { 1,2,3,4,5 }; int *p = arr; int *q = &arr[3]; printf("%d\n", q - p); // 3 printf("%d\n", *(p + 2)); // 3 return 0;}

[]中括号跟指针有什么关系?

为什么说[]中括号不是数组的专属?请看代码:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>int main(){ int arr[] = { 1,2,3,4,5 }; int *p = arr; for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { printf("%d ", arr[i]); } return 0;}

一般我们会写成arr[i]的形式,但是可以用这种方式写代码:*(arr + i);可见,[] == *()

什么是指针数组?

简单来说就是一个数组,数组的每一个元素都是一个指针,如图所示:

代码如下:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>int main(){ int arr1 = 1; int arr2 = 2; int arr3 = 3; int *num[3] = { &arr1,&arr2,&arr3 }; // 以上得知num[0]的类型是int *,要保存int*类型的地址,所以就需要比它多一级*,如以下: int **nums = num; for (int i = 0; i < sizeof(num) / sizeof(num[0]); i++) { printf("%d ", **(nums + i)); } return 0;}

指针作为形参的作用

作用:指针作为函数的形参,可以改变实参的值;用交换函数作例子的代码如下:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>// 交换函数例子void swap(int*a, int*b){ int tem = *a; *a = *b; *b = tem; return;}int main(){ int a = 10; int b = 20; swap(&a, &b); printf("a = %d b = %d\n", a, b); // a = 20 b = 10 return 0;}

数组作为函数的参数时

数组作为函数的形参会退化为指针,当数组名传入到函数中﹐数组名被退化为一个指针,指针指向的数组中第一个元素的地址。

const修饰的指针变量

代码如下:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <string.h>int main(){ char src[] = "hello"; char dst[] = "world"; const char *p = src; //const修饰指针,不能通过指针修改指针所指向的空间内容 如 *p = "w"; // 是会报错的 char * const pp = dst; //指针变量pp初始化之后不能改变pp指针变量本身的指向 如 pp = "world"; // 是会报错的 return 0;}

什么是字符指针数组

所谓的字符指针数组它是一个数组,每一个元素是字符指针;

代码如下所示:

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <string.h>int main(){ // 定义一个指针保存arr数组首元素的地址 char *arr[3] = { "hello" ,"world", "nihao" }; char **p = arr; for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++){ printf("%s\n", p[i]); } printf("%c\n", *(*(p + 1) + 2)); // 也可以写成这两种形式的 *(p[1]+2) 或 p[1][2] system("pause"); return 0;}

字符指针数组作为main函数参数时

int main(int argc, char *argv[]);

只要知道argc 是执行可执行程序的参数个数;

argv是一个字符指针数组,保存的是参数(字符串)的首元素地址;

阅读剩余内容
网友评论
相关内容
拓展阅读
最近更新