指针的引入
1.定义一个变量后,系统在内存上给其分配对应的数据类型的空间
2.每个字节在内存中都是有 内存编号的,这个编号就称为该空间的地址(指针)
3.指针就是内存地址,内存地址就是指针
4.由于内存编号是一个非常难记忆的值,一般会定义一个变量来存储。能够存储指针的变量,称为指针变量
指针变量
1.指针:就是某个空间的内存地址
2.指针变量:存储指针的变量称为指针变量
3.定义格式 :数据类型 *指针变量名;4.
4.注意:什么类型的变量的地址就应该定义相同数据类型的指针变量接收
指针变量的初始化
1.如何获取一个变量的地址,使用取地址运算符&来进行,该运算符是一个单目运算符
例如:变量num的地址为 &num
总结一下&的作用
&&:双目运算符,逻辑与运算
&: 双目运算符,按位与运算
&: 单目运算符,取地址运算
1.使用一个相同数据类型的变量的地址,给指针变量进行初始化
int num=520;
int *ptr=num; //使用一个相同数据类型的变量的地址进行初始化
2.使用一个已经初始化了的相同数据类型的指针变量进行初始化
int *qtr=ptr; //此时指针变量ptr和qtr都记录的变量num的地址
3.使用地址的0(NULL)给指针变量初始化
int *ktr=NULL; //该指针变量不记录任何地址
4.定义指针时,如果没有进行初始化,那么该指针变量在是一个随机值(野指针)
#include<stdio.h>
int main(int argc, const char *argv[])
{
int num = 520;
printf("num的地址为:%p\n", &num);
//此处的 &num,就是取得num所在的内存地址编号
int * ptr = # //定义一个指针变量并使用相同数据类型的变量地址进行初始化 定义一个指针,指向num
printf("ptr = %p\n", ptr);
int *qtr = ptr; //使用一个已经初始化了的相同数据类型的指针变量进行初始化
printf("qtr = %p\n", qtr);
int * ktr = NULL; //定义指针变量使用地址的0初始化
printf("ktr = %p\n", ktr);
int * ytr; //定义指针不初始化,是一个野指针
printf("ytr = %p\n", ytr);
return 0;
}
指针变量的使用
指针变量访问元素
1.指针变量的值:该变量存储的其他空间的内存地址
2.指针变量指向的内存空间的值:当前指针变量记录的地址空间的内容
3.当指针变量存储一个地址空间时,我们称为将该指针指向一个空间、
4.使用指针变量时,访问指针变量指向 的内存空间中的值,需要引入一个新的运算符*(取值运算)
总结*号 的使用
*作为双目运算符表示乘法运算
在定义指针变量时,*是身份的象征,表示定义的变量为指针变量
在使用指针变量时,*指针变量名;表示取得某个地址中的值
5.*(取值运算)与&(取地址运算)互为逆运算
6.当一个指针指向某一个变量后,就产生了一个等价
*ptr<==>num
#include<stdio.h>
int main(int argc, const char *argv[])
{
int num = 520; //在内存中申请了4个字节,存储了520,内存的名称为num
//int *ptr; //野指针
int *ptr = NULL; //空指针 变量名为ptr,这里的*号,只是身份的象征
ptr = # //将指针指向 num
printf("ptr = %p\n", ptr); //输出指针变量的值 地址
printf("*ptr = %d\n", *ptr); //输出指针所指向的内存空间中的值 520
//此处的*号是取值运算符
//验证&与*互为逆运算
// *&num ==> *(&num) ==> *ptr ==> num
printf("*&num = %d\n", *&num); //520
// &*ptr ==> &(*ptr) ==> &num ==> ptr
printf("&*ptr = %p\n", &*ptr); //地址
// *&ptr ==> *(指针变量的地址) ==> ptr
printf("*&ptr = %p\n", *&ptr); //地址
// &*num ==> &(*num) //报错,普通变量不能使用取值运算
//printf("&*num = %d\n", &*num);
//验证 *ptr等价于 num
num = 1314;
printf("*ptr = %d\n", *ptr); //1314
*ptr = 666; //通过指针变量,更改内存空间中的值
printf("num = %d\n", num); //666
return 0;
}
指针变量大小相关内容
1.32位操作系统中指针大小为固定4字节,64位系统中,指针大小固定为8字节
2.一般情况下不同类型的指针,指向的是跟其数据类型相同的地址
3.既然所有指针变量所占的内存空间都是一样的,为什么要定义不同类型的指针?
(1)不同类型的指针,使用取值运算符(*)时,解析的字节大小不同(跟数据类型有关)
(2)当指针变量进行数加运算时,偏移的大小不同
4.指针变量可以使用的运算
(1)*(取值运算):取得指针所指向的地址空间中的值
(2)数加运算(偏移):指针变量每加1或者减1,就会向高地址或者低地址处偏移一个数据类型的大小
(3)关系运算:用于判断两个指针所指向的空间是否相等 ptr=NULL
#include<stdio.h>
int main(int argc, const char *argv[])
{
int num = 0x12345678; //定义整形变量
char value = 'A'; //定义字符变量
int *ptr = # //定义整形指针指向整形变量的地址
char *qtr = &value; //定义字符类型的指针,指向字符类型的地址
printf("*ptr = %d, *qtr = %c\n", *ptr, *qtr); //302419896 A
printf("sizeof(ptr) = %ld, sizeof(qtr)=%ld\n", sizeof(ptr), sizeof(qtr)); // 8 8
qtr = (char *)ptr; //将ptr指向的地址赋值给qtr
//此时ptr和qtr同时指向num的起始地址
printf("ptr = %p, qtr = %p, &num = %p\n", ptr, qtr, &num);
printf("*ptr = %#x, *qtr = %#x\n", *ptr, *qtr); //0x12345678 0x78
//对指针变量进行偏移
ptr = ptr+1;
qtr = qtr+1;
printf("ptr = %p, qtr = %p, &num = %p\n", ptr, qtr, &num);
printf("*ptr = %#x, *qtr = %#x\n", *ptr, *qtr); // 0x56
return 0;
}
练习:使用指针完成验证自己的主机是大端存储还是小端存储
#include <stdio.h>
void pd()
{
int num=0x12345678;
//定义一个32位数据
char *ptr=(char *)#
//将整形变量的地址强行转换为字符类型的地址
//赋值给字符指针变量
if(*ptr==0x12)
{
printf("大端存储\n");
}else if(*ptr==0x78)
{
printf("小端存储\n");
}
}
int main(int argc, const char *argv[])
{
//判断电脑大端存储还是小端存储
//调用函数实现
pd();
return 0;
}

指针与一维数组
1.当指针指向一个普通变量时,往往不进行偏移运算,无论向上还是向下都是非法空间
2.当指针指向数组时,指针偏移才有了现实的意义

#include<stdio.h>
int main(int argc, const char *argv[])
{
int arr[5] = {5,7,3,2,6}; //在内存中连续申请5个int类型的空间
//访问数组元素
printf("数组中的元素分别是:");
for(int i=0; i<5; i++)
{
printf("%d\t", arr[i]);
}
printf("\n");
//输出每个元素的地址
printf("数组中的元素地址分别是:");
for(int i=0; i<5; i++)
{
printf("%p\t", &arr[i]);
}
printf("\n");
//通过数组名偏移输出每个元素的地址
printf("数组中的元素地址分别是:");
for(int i=0; i<5; i++)
{
printf("%p\t", arr+i);
}
printf("\n");
//定义一个指针变量,指向整形数组
int *ptr = arr; //int *ptr = &arr[0]
printf("数组中的元素地址分别是:");
for(int i=0; i<5; i++)
{
printf("%p\t", ptr+i);
}
printf("\n");
/************************************/
//使用数组名的方式访问元素
printf("数组中的元素分别是:");
for(int i=0; i<5; i++)
{
printf("%d\t", *(arr+i));
}
printf("\n");
//使用指针名的方式访问元素
printf("数组中的元素分别是:");
for(int i=0; i<5; i++)
{
printf("%d\t", *(ptr+i));
}
printf("\n");
//使用指针名的方式访问元素
printf("数组中的元素分别是:");
for(int i=0; i<5; i++)
{
printf("%d\t", ptr[i]);
}
printf("\n");
//使用指针名的方式访问元素
printf("数组中的元素分别是:");
for(int i=0; i<5; i++)
{
// printf("%d\t", *(ptr+0));
printf("%d\t", ptr[0]);
ptr++; //ptr = ptr+1
}
printf("\n");
/*使用数组名的方式访问元素
printf("数组中的元素分别是:");
for(int i=0; i<5; i++)
{
// printf("%d\t", *(ptr+0));
printf("%d\t", *arr);
arr++; //arr = arr+1
}
printf("\n");
*/
int *qtr = &arr[2]; //将指针指向第三个元素的地址
printf("%d\n", qtr[0]); //arr[2]
printf("%d\n", qtr[-1]); //arr[1]
printf("%d\n", qtr[1]); //arr[3]
return 0;
}
指针与函数的关系
1.指针作为函数的参数
1.指针接收普通变量的地址

#include <stdio.h>
void exchange1 (int m,int n)
{
int temp=m;
m=n;
n=temp;
printf("m=%d,n=%d\n",m,n);//1314 520
}
void exchange2(int *p,int *q)
{
//交接指针所指向内存空间中的值
int temp=*p;
*p=*q;
*q=temp;
printf("*p=%d,*q=%d\n",*p,*q);//1314 520
}
void exchange3(int *p,int *q)
{
int *temp=p;
p=q;
q=temp;
printf("*p=%d,*q=%d\n",*p,*q);//1314 520
}//实质是地址交换
int main(int argc, const char *argv[])
{
//三种数据交换的方法
int num=520;
int key=1314;
//调用函数实现数据交换
//exchange1(num,key); //520 1314
//exchange2(&num,&key); //1314 520
exchange3(&num,&key); //520 1314
printf("num=%d,key=%d",num,key);
return 0;
}
2.指针接收数组
2.指针作为函数的返回值:指针函数

1411

被折叠的 条评论
为什么被折叠?



