🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 定义 指针0-255是系统保留的,不能读也不能写,NULL是指向0的 ![](https://box.kancloud.cn/4c3579dc7bf9a433f280ece1d286dc94_818x402.png) 无论什么类型的指针,存的都是地址 内存地址都是无符号整形的,所以都是4个字节大小 10是四个字节 `int*` 表示我如果要改的话,对应那边数据的四个字节 `char*` 的话那就是对应那边数据的1个字节 **指针里面只是地址,指针也是个变量** ~~~ int main(int argc, char *argv[]) { int a = 10; int b = 100; //指针是一种数据类型,p是指针类型变量用来指向一个变量的地址 int * p = &a; p = &b; printf("%p\n", &b); //001CF878 printf("%X\n", p); //1CF878 //通过指针修改变量的值 *p = 200; printf("%d\n", b); //200 printf("%d\n", *p); //200 //sizeof()指针类型在内存中的大小,所有指针在32位是4个字节大小 //按照unsigned int为每一个内存分配编号 2的32次方-1 所以32位操作系统最多用4g内存 printf("%d\n", sizeof(p)); //4 printf("%d\n", sizeof(int *)); //4 printf("%d\n", sizeof(char *)); //4 system("pause"); return EXIT_SUCCESS; } ~~~ # 万能指针指定类型 ~~~ int main(int argc, char *argv[]) { int a = 10; //指针里面存的是首地址 void * p = &a; //转成指定类型,如果是char就转成char *(int *)p = 100; printf("%d\n", a); //100 printf("%d\n", *(int *)p); //100 system("pause"); return EXIT_SUCCESS; } ~~~ 如果是数组 ~~~ int main(int argc, char *argv[]) { int arr[10]; //首地址 void * p = arr; //改变首地址的值也就是arr[0] *(int *)p = 100; //改变arr[1],因为里面存的是int,每个元素占用4个字节,但是已经转为int了,int+1就过了4个字节 *((int *)p + 1) = 200; //就是arr[1] for (int i = 0; i < 10; i++) { printf("%d\n", arr[i]); } system("pause"); return EXIT_SUCCESS; } ~~~ # const `int * p` `int * `是指针的指向 p是指针的地址值 ## const修饰指针 const修饰变量是可以被修改的 ~~~ int main() { //这种方式不安全,可以通过指针修改 const int a = 10; printf("%d\n", a); int * p = &a; *p = 100; printf("%d\n", a); printf("%d\n", *p); getchar(); return EXIT_SUCCESS; } ~~~ 建议用define ~~~ #define LVL 100 ~~~ ## const修饰指针类型 ~~~ int main() { int a = 10; int b = 20; //如果const修饰int * 不能改变指针变量指向的内存地址的值 //但是可以改变指针存的地址 const int * p; p = &a; p = &b; printf("%d\n", *p); getchar(); return EXIT_SUCCESS; } ~~~ ## const修饰指针变量 ~~~ int main() { int a = 10; int b = 20; //const修饰指针变量 int * const p = &a; //能改变指针变量指向地址的值,但不能改变指针指向的地址 *p = 100; printf("%d\n", *p); getchar(); return EXIT_SUCCESS; } ~~~ ## const同时修饰指针类型和指针变量 ~~~ int main() { int a = 10; int b = 20; //const修饰指针类型并且指针变量,那么都不能改变 const int * const p = &a; getchar(); return EXIT_SUCCESS; } ~~~ ## const和非const类型转换 当一个指针变量 str1 被 const 限制时,并且类似`const char *str1`这种形式,说明指针指向的数据不能被修改;如果将 str1 赋值给另外一个未被 const 修饰的指针变量 str2,就有可能发生危险。因为通过 str1 不能修改数据,而赋值后通过 str2 能够修改数据了,意义发生了转变,所以编译器不提倡这种行为,会给出错误或警告。 也就是说,`const char *`和`char *`是不同的类型,不能将`const char *`类型的数据赋值给`char *`类型的变量。但反过来是可以的,编译器允许将`char *`类型的数据赋值给`const char *`类型的变量。 这种限制很容易理解,`char *`指向的数据有读取和写入权限,而`const char *`指向的数据只有读取权限,降低数据的权限不会带来任何问题,但提升数据的权限就有可能发生危险。 C语言标准库中很多函数的参数都被 const 限制了,但我们在以前的编码过程中并没有注意这个问题,经常将非 const 类型的数据传递给 const 类型的形参,这样做从未引发任何副作用,原因就是上面讲到的,将非 const 类型转换为 const 类型是允许的 # 指针和数组 指针遍历数组 ~~~ int main() { //数组名是数组的首地址,这是个常量 int arr[10] = { 0 }; //指向数组的指针,当操作指针的时候,间接操作了数组 int* p = arr; for (int i = 0; i < 10; ++i) { // printf("%d\n", p[i]); //这样也可以 printf("%d\n", *(p+i)); } getchar(); return EXIT_SUCCESS; } ~~~ 指针操作数组 ~~~ int main() { //数组名是数组的首地址,这是个常量 int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; //指向数组的指针,当操作指针的时候,间接操作了数组 int *p = arr; //指针操作数组 *p = 100; *(p + 1) = 200; p[5] = 300; *(p + 3) = 700; for (int i = 0; i < 10; ++i) { // printf("%d\n", p[i]); //这样也可以 printf("%d\n", *(p + i)); } getchar(); return EXIT_SUCCESS; } ~~~ # 多级指针 ~~~ int main() { int a = 10; int* p = &a; int** pp = &p; int*** ppp = &pp; //所以 ***ppp = a getchar(); return EXIT_SUCCESS; } ~~~ ![](https://box.kancloud.cn/509467709d75397002bdd26f7aa68e4a_1548x284.png) # 字符常量 ~~~ int main() { //字符数组,创建位置在栈区 char arr[] = "hello world"; //字符串常量,会在程序运行时,常量区,不能被修改的 // char * arr = "hello world"; printf("%p\n", arr); printf("%s\n", arr); getchar(); return EXIT_SUCCESS; } ~~~