翁恺老师C语言学习笔记(十)指针_指针运算

我们先看一段代码

#include <stdio.h>

int main(void)
{
	char ac[] = {0,1,2,3,4,5,6,7,8,9,};
	char *p = ac;
	printf("p  =%p\n", p);
	printf("p+1=%p\n", p+1);
	
	int ai[] = {0,1,2,3,4,5,6,7,8,9,};
	int *q = ai;
	printf("q  =%p\n", q);
	printf("q+1=%p\n", q+1);
	
	return 0;
 } 

输出结果

p =0062FE8E
p+1=0062FE8F
q =0062FE64
q+1=0062FE68

这里可以看出:
char 类型下,p和p+1只差1个字节
int 类型下,q和q+1却差了4个字节

为什么char类型指针是1个字节,而int类型指针却是4个字节
因为上一节讲到 sizeof(char)占用一个字节,而size(int)占用4个字节
从这里可以看出当我们给一个指针地址+1时,其实是给指针地址+sizeof()指针所指的类型

我们再看另外一段代码,如果我们有一个数组

*p -> ac[0]
*(p+1) -> ac[1]		// *是单目运算符运算优先级高,所以(p+1)要加上括号
#include <stdio.h>

int main(void)
{
	char ac[] = {0,1,2,3,4,5,6,7,8,9,};
	char *p = ac;
	printf("p  =%p\n", p);
	printf("p+1=%p\n", p+1);
	printf("*(p+1)=%p\n", *(p+1));

	int ai[] = {0,1,2,3,4,5,6,7,8,9,};
	int *q = ai;
	printf("q  =%p\n", q);
	printf("q+1=%p\n", q+1);
	printf("*(q+1)=%p\n", *(q+1));
	
	return 0;
 } 

运行输出结果:

p =0062FE8E
p+1=0062FE8F
*(p+1)=00000001
q =0062FE64
q+1=0062FE68
*(q+1)=00000001

这里*(p+1)和*(q+1)都=1,没有任何意义,所以指针+1需要加上sizeof()

**· 给一个指针+1表示要让指针指向下一个变量
int a[10];
int *p = a;
*(p+1) --> a[1]
· 如果指针不是指向一篇连续分配的空间,如数组,则这种运算没有意义
**
*(p+n) <–> ac[n]

在代码里,我们让p(p+n)和ac[n]是一回事

扫描二维码关注公众号,回复: 11278039 查看本文章

指针计算
· 这些算术运算可以对指针做:
· 加、减一个整数(+,+=,-,-=)
· 递增递减(++/–)
· 两个指针可以相减

int main(void)
{
	char ac[] = {0,1,2,3,4,5,6,7,8,9,};
	char *p = ac;
	char *p1 = &ac[5];
	printf("p1-p=%d\n",p1-p);
	
	int ai[] = {0,1,2,3,4,5,6,7,8,9,};
	int *q = ai;
	int *q1 = &ai[6];
	printf("q1-q=%d\n",q1-q); // 指针和指针相减
	printf("q =%d\nq1=%d\n",q,q1);
	
	return 0;
 }

运行输出结果

p1-p=5
q1-q=6
q =6487644
q1=6487668

从这里可以看出

· p1-p=ac[5]-ac[0]=5-0=5
· q1-q=ai[6]-ai[0]=6-0=6
· q1-q=24
指针和指针相减时,是sizeof()-sizeof()

** p++的含义
· 取出p所指的那个位置的数据,然后把p移到下一个位置
· 的优先级高,但是没有++高
· 常用于数组类的连续空间操作
· 在某些CPU上,剋有直接被翻译成一条汇编指令
遍历数组例子

int main(void)
{
	char ac[] = {0,1,2,3,4,5,6,7,8,9,-1};
	char *p = ac;
	int i;
	/*遍历方法1*/
	for(i=0;i<sizeof(ac)/sizeof(ac[0]);i++){
		printf("%d\n",ac[i]);
	}
	/*遍历方法1*/
	while(*p != -1){
		printf("%d\n",*p++);
	} 
	int ai[] = {0,1,2,3,4,5,6,7,8,9,};
	int *q = ai;
	
	return 0;
}

执行输出结果

0
1
2
3
4
5
6
7
8
9
-1
0
1
2
3
4
5
6
7
8
9

指针比较
· <,<=,==,>,>=,!=都可以对指针直接操作
· 比较他们内存中的地址
· 数组中的单元的地址肯定是线性递增的

0地址
· 内存中有0地址,但是0地址通常不能随便用的 地址,读0地址也不可以
· 指针不应该具有0值,可以初始化为0
· 可以用0地址表示特殊的事情:
· 返回的指针是无效的
· 指针没有不真正初始化(先初始 化为0)
· NULL是一个预定义的符号,表示0地址
· 有的编译器不愿意用0来表示0地址

指针的类型
· 无论指向什么类型,所有的指针的大小都是一样的,因为指针都是地址
· 但是指针指向不同类型的指针是不饿能直接互相赋值的
· 这是为了避免用错指针

指针的类型转换
· void 可以表示不知道指针什么东西的指针
· 计算时与char
相同(但不相通)
· 指针也可以转换类型
· int p = &i; void q = (void)p;
· 这并没有改变p所指的变量类型,而是让后人用不同的眼光通过p看它所指的变量
· 它不再是int了,而是一个void

指针用来做什么
· 需要传入比较大的数据时,用作参数,比如传入数组
· 传入数组后可以用指针对数组可以进行操作
· 函数返回不止一个结果时,可以用指针作参数,让指针带出结果
· 需要用函数修改不止一个变量时,可以用传指针进去,比如swap,让指针进去帮我们修改这个值
· 动态申请的内存的时候

猜你喜欢

转载自blog.csdn.net/sevensolo/article/details/94342934
今日推荐