C语言——指针基础

  • 指针变量
  • 取地址运算符和间接寻址运算符
  • 指针赋值
  • 指针作为实际参数
  • 指针作为返回值

指针变量

机器层上指针表示的内容是什么?
x表示第几个byte,y表示物理address,x和y一一对应。
一般的对应关系 y = x - 1;
其中一个byte存储的内容为00000000-11111111的机器码。
可执行程序由代码数据两部分构成。
程序中的每个变量占有一个或多个内存字节,把第一个字节的地址称为是变量的地址。
设程序中的一个变量为x,x所占有的内存空间y = x.space(); 内存空间的首地址 即x的地址,x.address = y.firstElement.address
虽然用数表示地址,但是其取值范围可能不同于整数的范围,所以一定不能用普通整型变量存储地址。但是,可以用特殊的指针变量(pointer variable)存储地址。指针就是地址,而指针变量是只存储地址的变量。

声明指针变量
对指针变量的声明和对普通变量的声明的不同就是必须在指针变量名字前放置星:
int *p;
上述声明说明p是指向int型对象的指针变量。指针不止可以指向变量,还可以指向其它非存储变量的内存区域,所以我们说指针指向对象而不是指针指向变量。
指针变量可以和其他变量一起出现在声明种:
int i,j,a[10],b[20],*p,*q;
C语言要求每个指针唯一指向特定类型的对象?(为什么C语言的指针这么设计,以及怎么的设计使之指向唯一特定类型?

关于指针的运算符

  • 取地址运算符&
  • 间接寻址运算符*

声明指针变量:

int *p;

初始化指针变量:

  • int i, *p; p = &i;
  • int i; int *p = &i;
  • int i, *p = &i;

其中第二种 p是i的地址,而*p指向i的值;

只要p指向i,那么*p就是i的别名。p不仅拥有和i同样的值,而且对p的改变也会改变i的值。

#include <stdio.h>

int main(){
	int i = 1;
	int *p = &i;
	*p = 2;
	printf("%d\n",i);
	printf("%d\n",p);
	return 0;
} 

输出结果为:
在这里插入图片描述

指针赋值

C语言允许使用赋值运算符进行指针的复制,前提是两个指针具有相同的类型

int i = 1, j = 2, *p = &i, *q = &j;
p = q;//指针赋值,p指向 q指向的内存空间
*p = *q;//变量赋值,给p指向的内存空间赋q指向的内存空间的值

指针作为实际参数

问题:因为C语言用值进行传递,所以在函数调用种用变量作为实际参数会阻止对变量的改变。
指针提供的解决方法:不再传递变量x作为函数的实际参数,而采用&x,即指向x的指针。声明相应的形式参数p是指针。调用函数时,p将有&x值,因此p将是x的别名。函数体内的p的每次出现都将是对x的间接引用,而且允许函数既可以读取x也可以修改x。

#include <stdio.h>

void decompose(float,int *,float *);

int main(){
	float x = 2.345;
	int *int_part;
	int i;
	float j;
	decompose(x, &i, &j);
	printf("%d\n%f",i,j);
} 

void decompose(float x,int *int_part,float *frac_part){
	*int_part = (int) x;
	*frac_part = x - *int_part;
}

输出结果为:
在这里插入图片描述
警告
向函数传递需要的指针却失败了可能会产生严重的后果,假设调用的i和f前不带&运算符的decompose函数:

decompose(3.1415926,i,f);

函数会把i和f的假值设为指针来使用,decompose函数把值储存到未知的内存单元中,而不是修改i和f。

#include <stdio.h>
void max_min(int[], int, int *, int *);

int main(){
	int n = 5;
	int a[n] = {1,2,3,4,5};
	int max,min;
	max_min(a,n,&max,&min);
	printf("%d\n%d",max,min);
} 

//找出数组的最大元素和最小元素 
void max_min(int a[], int n, int *max, int *min){
	*max =  a[0];
	*min = a[0];
	for(int i = 1; i < n; i++){
		if(a[i] > *max){
			*max = a[i];
		}else if(a[i] < *min){
			*min = a[i];
		}
	} 
}

输出结果为:
在这里插入图片描述
用const保护实际参数

void f(int *);
void main(){
	int x;
	f(&x);
}

为了允许函数f检查传递的指针所指向的实际参数,而不是修改它,可以在参数声明中把const放置在形式参数的类型说明之前:

void f(const int *p){
	*p = 0; /*** WRONG ***/
}

const的使用说明p是指向“整型常量”的指针。试图改变*p将会引发编译器发出特定消息。

指针作为返回值

#include <stdio.h>
int *max2(int *,int *);

int main(){
	int a = 5, b = 10;
	int *p = max2(&a,&b);
	printf("%d",*p);
} 

//比较大小返回两整数中较大数的指针
int *max2(int *a, int *b){
	if(*a > *b)
		return a;
	else
		return b;
} 

输出结果为:
在这里插入图片描述
虽然max函数返回的指针是作为实际参数传递的两个指针中的一个,但是这不是函数可以返回的唯一事情。一些函数返回的指针指向作为实际参数传递的数组中的一个元素。另外一种可能是返回指向外部变量或指向声明为static的局部变量的指针。

void f(const int *p){
	int j;
	p = &j;
}

上述代码是合法的:const修饰的形式参数 指针指向的值不能改变,但不能阻止改变p本身。

void f(int * const p){
	int j;
	*p = 0; //legal
	p = &j; / ***WRONG*** /
}

可以用const保护p使p指向的地址不改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值