1、什么是指针
????要搞懂指针,我们先要了解数据在内存中如何存储、如何读取的。
我们在程序中定义了一个变量(假如是整型),系统就会为该变量分配4byte大小的内存空间,然后把它放进去;在内存中,每一个字节都对应着一个地址编号,根据这个第一个Byte的编号就可以找到我们想要的数据,我们可以把这个地址形象化的称为指针。
? 上面的程序中,定义了一个整型变量的a,并赋初值为10,整型10的在内存中的存储形式为:00000000 00000000 00000000 00001010,转为16进制为:0000000a(VS以小端字节序存储数据)。
? a的地址为0x006FFB18,注意,一般我们说的地址都是首地址。
? ????指针用于存放变量的地址,指针也是变量(指针变量)
2、指针变量
????在使用指针变量之前我们先看一下这两个操作符:
- &:取地址操作符
- *:解引用操作符(间接访问操作符)
? 下面我们来开一个通过指针变量访问整型变量的例子
int main() {
int a = 10;
printf("%p\n", &a);
int *pa = &a;
printf("%p\n", pa);
printf("%d\n",*pa);
return 0;
}
? 运行结果如下:
? 程序分析:
注释内容已有部分分析,第7行我们定义了一个整型的指针变量pa,pa指向整型变量a的地址
3、 如何定义指针变量
? 定义指针变量的一般形式为:
*数据类型 指针变量名 = &变量名;
如:double *pd = &a;
注意:*号的位置可以只要实在数据类型的左边,指针变量名的右边就行。
如:double* pd = &a; 和 double * pd = &a; 均是合法的
不能写为:double *pa = 0x00DFFA68; 指针变量指向的地址不能是一个数值,只能用取地址符"&"得到并赋给一个指针变量。
????&a不仅包含变量a的地址,还包括它对应的数据类型。
4、指针变量的基本使用
????在编译器中运行如下代码,观察变量a的输出结果。
#include <stdio.h>
int main() {
int a = 10;
int* pa = &a;
*pa = 20;
printf("%d\n", a);
return 0;
}
上述的代码中,我们通过指针变量来间接改变变量a的值
练习:使用指针变量来交换两个整型变量的值
#include <stdio.h>
int main()
{
int a = 10;
int b = 20;
int *pa = &a;
int *pb = &b;
int temp = *pa;
*pa = *pb;
*pb = temp;
printf("a = %d b = %d\n", a, b);
}
5、指针的大小
????经过前面知识的学习,我们都知道了指针就是地址。 ????指针的大小只会随着机器的位数不同而不同,32bit的机器上的指针大小均为4Byte,64bit的机器上的指针大小均为8bit。因为地址的大小总是固定的。 ????这里我在VS2017中分别模拟32bit和64bit的机器,让大家看看,大家也可以在自己的机器上测试:
6、指针运算
????我们这里主要讲指针+/-整数 和指针+/-指针 ????在此之前我们先来看看指针的数据类型的意义:
1、指针的数据类型类型决定了移动一个或多个单位时的步长是多少,这个步长就是数据类型的长度,比如int的长度为4Byte,char的长度为1Byte 2、指针的类型决定了指针解引用是的权限有多大(即能操作多少个Byte)
6.1 指针与整数的加减运算
先看一个例子:
#include <stdio.h>
int main()
{
char ch[] = "hello world!";
int arr[] = { 1,2,3,4,5 };
printf("%p\n", ch);
printf("%p\n", ch+1);
printf("%p\n", arr);
printf("%p\n", arr+1);
return 0;
}
运行结果如下:
前置知识:数组名代表的是数组中首元素的地址
根据图中的运行结果可以看到,单独的打印数组名,打印的实际是数组首元素的地址,而数组名+1打印的则是下一个元素的地址。
接下来我们来做一个小练习:使用指针变量打印数组元素
#include <stdio.h>
int main()
{
int arr[5] = {1,2,3,4,5};
int *p = arr;
for (int i = 0; i < 5; i ++)
{
printf("%d ", *(p+i) );
}
return 0;
}
或
#include <stdio.h>
int main()
{
int arr[5] = {1,2,3,4,5};
int *start = arr;
int *end = arr + 9;
while (start <= end)
{
printf("%d ", *p );
p ++;
}
return 0;
}
6.2 指针与指针的加减运算
????我们这里不讨论指针与指针的加法,因为目前在我的认知里好像它没什么用;所以我这里只看指针与指针的减法运算。 ????指针与指针的减法运算的值为它们地址范围内的元素个数。 我们通过一个例子来看看:
int main()
{
int arr[10] = { 0 };
printf("%d \n", &arr[9] - &arr[0]);
return 0;
}
以上代码我们做的是用arr数组的最后一个元素地址减去首元素地址,打印结果为9。为什么呢,我们来看图解: ????前面我就说了指针减指针的值为它们地址范围内的元素个数,使用输出结果为9这是必然的。 ????大家应该用过C语言的库函数strlen吧,它是用来计算字符串长度的,该函数就是使用指针减指针的方式来计算机字符串长度的了,我们来看一看strlen库函数的实现:
size_t __cdecl strlen (
const char * str
)
{
const char *eos = str;
while( *eos++ ) ;
return( eos - str - 1 );
}
7、指针与数组
|