AutoLeaders控制组——C语言指针笔记

一.指针简介

1.指针定义

什么是指针?从根本上看指针(pointer)是一个值为内存地址的变量。正如char类型变量的值是字符,int类型变量的值是整数,指针变量的值是地址。因此指针即地址

2.声明指针

声明指针变量时必须指定指针所指向变量的类型,这是因为不同的变量类型占用不同的存储空间。下面是一些指针的声明示例

int * pi;	// pi是指向int 类型变量的指针	
char * pc;	// pc是指向 char 类型变量的指针	
float * pf,* pg; // pf、pg都是指向float 类型变量的指针

类型说明符表明了指针所指向对象的类型,星号(*)表明声明的变量是一个指针。int *pi;声明的意思是pi 是一个指针,*pi是int类型

二.指针与函数

1.作为桥梁来修改函数中变量的值

void f(int *p);
指针在被调用的时候得到了某个变量的地址: int i=0; f(&i);
在函数里面可以通过这个指针访问外面的变量i ,同时可以通过对 *p赋值从而改变变量 i 的值。

代码如下

#include <stdio.h>
void f(int *p);
int main(void){
int i = 6;
printf("&i=%p\n", &i);	
f(&i);
printf("%d",i);
return 0;
}
void f(int *p) {
 	printf(" p=%p\n",p);
 	*p=666;
 }

2.在函数中进行变量交换

通过传入变量的地址来进行变量值的交换
代码如下:

#include<stdio.h>
    void swap(int *pa,int *pb);
int main()
{
     int a=5;
	 int b=6;
	 swap(&a,&b);
	 printf("%d %d\n",a,b);
	
	return 0;
}
	void swap(int *pa,int *pb){
		int t=*pa;
		*pa=*pb;
		*pb=t;
	}

3.从函数中返回多个值

函数返回多个值,某些值就只能通过指针返回,传入的参数实际上是需要保存带回的结果的变量
代码如下:`

#include<stdio.h>
    void maxmin(int a[],int len,int *max,int *min);
int main()
{
    int a[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
     int max,min,len;
     maxmin (a,sizeof(a)/sizeof(a[0]),&max,&min);
	printf("%d %d",max,min);
	return 0;
	}     
    void maxmin(int a[],int len,int *max,int *min){
    	int i;
    	*max=*min=a[0];
    	for(i=1;i<len;i++){
    		if(*min>a[i]){
    			*min=a[i];
			}if(*max<a[i]){
				*max=a[i];
			}
		}
	}

4.通过指针返回函数运算的结果

函数返回运算的状态,结果通过指针返回
函数在运算的过程中可能遇到特殊的状态计算,未得到特殊的结果
常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错: 如 返回-1或0(在文件操作会看到大量的例子)
但是当任何数值都是有效的可能结果时,就得分开返回
函数状态用return 返回而结果则用指针返回

 #include <stdio.h> /**
 	@return 如果除法成功,返回1;否则返回0	
 */
int divide(int a, int b, int *result); 
int main(void)
 	int a=5;	
 	int b=2;	
 	int c;	
 	if ( divide(a,b,&c) ) {	
 	printf("%d/%d=%d\n",a, b, c);	
 	}	
 	return 0;	
 }
int divide(int a, int b, int *result) {
int ret = 1;
if( b == 0 ) ret = 0; else {
 	*result = a/b;
 	return ret;	
 }

三. 指针常见错误

定义了指针变量,还没有指向任何变量,就开始使用指针
如下

int *p;
int k;
k=12;
*p=12;

这样会是指针指向未知的位置,从而导致程序的崩溃

四.指针与数组

在函数参数表中,数组就是指针
由于函数原型可以省略参数名,所以下面4种原型都是等价的:

int sum(int *ar, int n); int sum(int *, int);
int sum(int ar[],int n); int sum(int[],int);

数组变量本身表达地址,所以

int a[10]; int*p=a;// 无需用&取地址

但是数组的单元表达的是变量,需要用&取地址
a == &a[0]
[ ]运算符可以对数组做,也可以对指针做: p[0] <=> a[0]
运算符可以对指针做,也可以对数组做: * a=25;此时*a代表的值为a[0]
数组变量是const的指针,所以不能被赋值· int a[ ] <=> int *const a=…
因此数组变量就是特殊的指针

五.指针与const

1. 指针是const

表示指针一旦得到了某个变量的地址,不能再指向其他变量

int * const q = &i; // q 是 const
 *q = 26;// OK
  q++; // ERROR

2.所指是const

表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)

const int *p = &i;
*p = 26;// ERROR!(*p) 是 const 
i= 26;//OK
p=&j;//OK

判断哪个被const了的标志是const在星号的前面还是后面

int i;
const int* p1 = &i;
int const* p2 = &i;
int *const p3 = &i;

如果const在星号前表明所指是const,反之则为指针是const

3.const转换

通过const转换可以把一个非const的值转换成const的值
例如:

void f(const int* x); 
int a = 15;
 f(&a); // ok
const int b = a; f(&b); // ok
b = a + 1; // Error!

把变量a的值进行固定
当要传递的参数的类型比地址大的时候,这是常用的手段:既能用比较少的字节数传递值给参数,又能避免函数对外面的变量的修改

4.const数组

防止数组在函数内被修改可以使用const数组,由于数组变量就是特殊的指针
const int a[ ]={I,2,3,4,5,6,};
数组变量已经是const的指针了,这里的const表明数组的每个单元都是const int,所以必须通过这样的初始化进行赋值

六.指针的运算

1.指针的简单运算

指针的运算并不是简单的加减, 我们的系统中,地址按字节编址,short类型占用2字节,double类型占用8字节。指针加1 指的是增加一个存储单元。对数组而言,加1后的地址是下一个元素的地址,而不是下一个节的地址
指针加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)=%d\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)=%d\n"*(q+1));	
 	return 0;	
 }

同理,同类型指针之间相减得到的值为存储单元(以字节为单位)
指针只能做加减,指针乘除无意义
指针之间可以作比较,比较的是它们在内存中的地址

2.指针运算与数组的关系

若指针p指向数组,那么指针加一将会使数组进入下一个单元
例如:
*p<=>ac[0]
*(p+1)<=>ac[1]

七. 指针的类型转换

void* 表示不知道指向什么东西的指针,指向一个内存空间
计算时与char*相同(但不相通)
指针可以转换类型 例如:
int * p = &i;
void *q= (void *)p;
这并没有改变p所指的变量的类型,i还是int类型。而是让后人用不同的眼光通过p看它所指的变量·我不再当你是int啦,我认为你就是个void!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值