一.地址与指针的概念
地址:计算机对内存单元中的数据进行操作,一般按“地址”存取的,也就是对内存单元进行标识编号
指针:它存储的是一个内存地址。这个地址指向的是另一个变量或数据的位置,也就是说,指针可以直接访问内存中的数据。 通过变量的地址进行操作,用指针访问内存和操作地址
使用变量p访问变量x的过程实现了对变量x的间接操作,C语言中把专门存放变量地址的变量称为“指针变量”。
二.定义指针变量
取地址运算符&:单目运算符&是用来取操作对象的地址。例:&i 为取变量 i 的地址。对于常量表达式、寄存器变量不能取地址(因为它们存储在存储器中,没有地址)。
指针运算符*(间接寻址符):与&为逆运算,作用是通过操作对象的地址,获取存储的内容。例:x = &i,x 为 i 的地址,*x 则为通过 i 的地址,获取 i 的内容。
指针声明符 * 在定义指针变量时被使用,说明定义的那个变量是指针。
通常格式:
数据类型 *指针变量名;
eg: int *p; // 定义一个数据类型为int型,变量名为p的指针
char *cp;
float *fp;
double *dp1,*dp2;
注意:定义多个指针变量时,每一个变量都需要在变量前加上 指针声明符 *
三.指针的基本运算
1.取地址(对指针变量赋值)
int a=1,*p;
p=&a; // “ & ”为取地址符,也就是指针p被看作成指向变量a或者存放变量a的地址
取a所在的地址
p | a |
变量a的地址 | 1、(*p) |
①取地址运算和使用指针访问变量
#include<stdlib.h> #include<stdio.h> int main() { int a,*p; // 定义整型变量a,指针变量 p scanf("%d",&a); p=&a; // 把a的地址赋给指针p,即p指向a printf("a=%d *p=%d\n",a,*p); //*p 表示指针p所指向变量的值 (*p==a) *p=a+1; printf("a=%d *p=%d\n",a,*p); ++*p; //*p++; *++p; printf("a=%d *p=%d\n",a,*p); // system("pause"); return 0; }
2.指针的算术运算 (右结合)
++*p;
*p++;*++p; // 都是指针变量先加1,再取其地址对应的内容 *p++ == *(p++)
关于 *(p++) 运算后,p不再指向a,即 p 的内存单元不再是 a 的内存地址
3.指针的赋值
int a=2,*p1,*p2;
p1=&a; //使指针p1指向整型变量a
p2=p1; // 使指针p2指向p1
此外指针的使用会影响到原变量的值
下面来个例题(利用指针交换 a 和 b 的值)
①在主函数中交换的写法
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int *px,*py;
int a,b;
int main()
{
scanf("%d%d",&a,&b);
px=&a; py=&b; // 指针取a,b的地址
int t=*px;
*px=*py; *py=t; // 交换 *px *py的值 --> 交换 a b 的值
printf("%d %d",a,b);
system("pause");
return 0;
}
②调用函数的写法
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int *px,*py;
int a,b;
void swap(int *a,int *b) // 定义指针类型变量 区别与 *px *py
{
int t=*a;
*a=*b; *b=t;
}
int main()
{
scanf("%d%d",&a,&b);
px=&a; py=&b;
swap(px,py);
printf("%d %d",a,b);
system("pause");
return 0;
}
4.指针的关系运算
① px>py // 判断 px 存储的地址是否大于 py 存储的地址
② px==py // px 与 py 是否对应同一个储存单元
③px==0 || px!=0 // 判断px是否为空指针
四.指针与数组
定义数组与指针:
int a[6]={0,1,2,3,4,5},*p;
1.指向数组的指针:
一维数组:一个数组的首地址为数组名a,或者是数组的第一个元素的地址
p=a; // 数组名为首地址
p=&a[0]; // 取数组中第一个元素a[0]的地址
2.对指针数组的操作
例:以上述数组a的值为例
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int *px;
int num[5]={0,1,3,5,7};
int main()
{
px=num; // 取数组的地址操作(或者) px=&num[0];
for(int i=0;i<=4;i++)
{
printf("%d ",*(px++)); // (p+i) 为指针加整数操作 对应p指向下一个元素即a[i]
} // 其中区别 (*px)++ 与 *(px++)
system("pause");
return 0;
}
其中 (p+1) 对应 a[1] (p+k) 对应 a[k]
对上述两种 (*px)++ 与 *(px++) 操作的理解与区别 (指针在数组的应用)
① (*px)++ : *px 为px指向元素的值 然后再自加
②*(px++) : px++ 表示为指针加整数操作 指向 a 的下一个元素 然后再通过 * 指向其元素值
注 : 考虑边界范围,不能超出数组长度
五.指针与字符串
1.格式
字符串指针和整型数组指针的使用差不多
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char ch[1001];
char *str;
int main()
{
scanf("%s",ch);
str=ch; // 或者 str=&ch[0]; 都会取其第一个字符的地址
printf("%c %c",*str,*(str+1)); // str++ 指向下一个字符
system("pause");
return 0;
}
2.关于字符串处理函数
①字符串的拼接 strcat
核心代码:
strcat(s1,s2); // 将 s2 拼接到字符数组 s1 的尾部 注: s1 的长度需要足够容纳两个字符串
输入样例: woai biancheng
拼接输出: woaibiancheng
②字符串的复制 strcpy
strcpy(s1,s2) // 将 s2 的字符 赋给 s1 确保 s1 的长度
③ 字符串的比较 strcmp
printf("%d",strcmp(s1,s2));
// 比较字符串的大小(按字典序)
s1 > s2 返回数>0 返回字典序的差
s1 < s2 返回数<0
s1 == s2 返回 0
例如: s1[5]='hello';
s2[5]='aello'; 返回 7