文章目录
前言:关于指针的一些概念
- 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
- 指针的大小是固定的4/8个字节(32位平台/64位平台)。
3.指针是有类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限。
4. 指针的运算。
提示:以下是本篇文章正文内容,下面案例可供参考
一、字符指针
在指针的类型中我们知道有一种指针类型为字符指针char*
1. 一般使用
#include<stdio.h>intmain(){char ch ='w';char* pc =&ch;*pc ='a';printf("%c", ch);return0;}
上述代码使用,char *指针把这个字符变量的地址放到这个char 指针中,然后通过对 pc解引用,找到字符**ch ,然后改变其中的值为a,我们来看一下打印的结果。这就是我们的一般用法.
2. 另一种方法使用
我们来看一个简单的代码
#include<stdio.h>intmain(){char* p ="abcdef";}
这段代码的意思是什么呢?这里是把字符串"abcdef"放到这个char*p的指针变量中了吗?呢我们就需要去想它能放的下吗?现在是在32位环境下,p指针变量是4个字节而"abcdef"是6个字节,在加上/0是7个字节,所以答案是存不下。所以这个代码的意思绝对不是把"abcdef"放到指针变量p中。其实这个代码的意思是把这个常量字符串"abcdef"首字符a的地址存放到指针变量p中。下面画图来说明(假设首字符地址是0x0012ff40)
如果你还是不敢相信,呢么我们可以使用 *p解引用访问这个字符串,其实访问的就是字符a 我们可以打印看看是不是.结果和我们想的一样
在有些初学者,不正确理解上述代码,就会出现下列问题。下面这个程序崩了,这是为什么呢?这是因为,这个字符串是一个常量字符串,常量字符串是不允许被修改的。
其实我们对这个代码,稍做优化可以防止出现这个错误。 这里就提示你编译错误。
#include<stdio.h>intmain(){constchar* p ="abcdef";*p ='w';}
3. 经典面试题
我们观察下列代码,会输出说明结果呢?
#include<stdio.h>intmain(){char str1[]="hello world.";char str2[]="hello world.";constchar* str3 ="hello world.";constchar* str4 ="hello world.";if(str1 == str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if(str3 == str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return0;}
这里最终输出的是:
这是因为: 这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会 开辟出不同的内存块。所以str1和str2不同,str3和str4不同。
二、指针数组
指针数组是一个存放指针的数组
1. 一种使用
来看下面的一段代码 : 这里是3个变量,我们只需创建3个指针变量就可,但是如果变量10个 20个甚至更多呢?我们也需要创建对应的指针变量吗?呢我们就想到创建一个整型指针的数组,来存放变量的地址。
#include<stdio.h>intmain(){//int* arr[10];//存放整型指针的数组//char* ch[5];//存放字符指针的数组int a =10;int b =20;int c =30;int* p1 =&a;int* p2 =&b;int* p3 =&c;int* arr[3]={&a,&b,&c };//arr就是一个指针数组int i =0;for(i =0; i <3; i++){printf("%d ",*(arr[i]));//找到变量对应的地址,然后解引用就拿到了对应的元素}return0;}
2. 第二种使用
来看下面的一段代码 :
#include<stdio.h>intmain(){int arr1[5]={1,2,3,4,5};int arr2[5]={2,3,4,5,6};int arr3[5]={3,4,5,6,7};int* parr[3]={ arr1, arr2, arr3 };//parr是一个指针数组int i =0;for(i =0; i <3; i++)//找到每一行{int j =0;for(j =0; j <5; j++)找到每一个元素
{//printf("%d ", parr[i][j]);printf("%d ",*(parr[i]+j));依次加j,相当于找到每个元素地址,然后在解引用,找到并打印这个元素
}printf("\n");}return0;
我们画图来解释:
我们分别有三个数组arr1 arr2 arr3,数组名表示首元素地址。然后我们把这三个数组名也就是首元素地址,分别存放到parr数组中,每一个类型都是int*
parr[0]–>arr1、parr[1]–>arr2、parr[2]–>arr3 分别对应。这时我们发现好像模拟出一个二维数组,先使用parr找到每一行,然后又可以找到每一个元素,然后就得出下面的打印结果。
三、&数组名vs数组名
我们知道arr是数组名,数组名表示首元素地址。呢么&arr是什么呢?
来看下面的一段代码 :
#include<stdio.h>intmain(){int arr[10]={0};printf("%p\n", arr);//%p打印地址printf("%p\n",&arr);return0;}
运行结果如下:
可见数组名和&数组名打印的地址是一样的。难道这个两个意义相同吗?
我们在看下面的一段代码 :
#include<stdio.h>intmain(){int arr[10]={0};printf("arr = %p\n", arr);printf("&arr= %p\n",&arr);printf("arr+1 = %p\n", arr +1);printf("&arr+1= %p\n",&arr +1);return0;}
运行结果如下:
在这里arr类型是int* 当我们对其+1时由00B6FC70–>00B6FC74 整型指针+1跳过4个字节。而&arr类型是int(*)[10],是数组指针类型,而数组的地址+1,00B6FC74–>00B6FC98 跳过了40个字节,跳过了整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40.
**
通常情况下,我们说的数组名都是数组首元素的地址但是有2个例外:
**
1. sizeof(数组名),这里的数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小
2. &数组名,这里的数组名表示整个数组,&数组名,取出的是整个数组的地址
四、数组指针
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。
一个数组指针的使用:
#include<stdio.h>voidprint_arr1(int arr[3][5],int row,int col){int i =0;for(i=0; i<row; i++){for(j=0; j<col; j++){printf("%d ", arr[i][j]);}printf("\n");}}voidprint_arr2(int(*arr)[5],int row,int col){int i =0;for(i=0; i<row; i++){for(j=0; j<col; j++){printf("%d ", arr[i][j]);}printf("\n");}}intmain(){int arr[3][5]={1,2,3,4,5,6,7,8,9,10};print_arr1(arr,3,5);//数组名arr,表示首元素的地址//但是二维数组的首元素是二维数组的第一行//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址//可以数组指针来接收print_arr2(arr,3,5);return0;}
学了指针数组和数组指针我们来一起回顾并看看下面代码的意思:
1 int arr[5]; arr是一个整型数组,有5个元素,每个元素是int类型的。
2 int parr1[10];parr1是一个数组,数组有10个元素,每个元素的类型是int ;所以parr1是**指针数组。
3 int (*parr2)[10];parr2先和 * 结合,说明parr2是一个指针,该指针指向一个数组,数组是10个元素,每个元素是int类型的,parr2是数组指针。
4 int (*parr3[10])[5];parr3和[]结合,说明parr3是一个数组,数组是10个元素,数组的每个元素是什么类型呢?是一种数组指针,类型是int( * )[5],该类型的指针指向的数组有5个int类型的元素。
以上就是指针的一部分内容, 🌟Hello world 我们下期见!
版权归原作者 Dream_辉辉 所有, 如有侵权,请联系我们删除。