AutoLeaders控制组——指针学习笔记

本文是关于C语言指针的学习笔记,涵盖了取地址运算、指针概念、指针使用场景、指针与数组的关系、指针与const的结合,以及动态内存分配的malloc和free函数。内容包括指针变量的地址获取、指针作为变量的值、函数参数传递、指针常量与常量指针的区别,以及指针运算和类型注意事项。
摘要由CSDN通过智能技术生成

AutoLeaders控制组——指针学习笔记

C语言指针笔记

一.取地址运算
运算符&
scanf(“%d”,&i);里的&
&用来获取变量的地址

地址用十六进制表达比较方便
%x能输出十六进制
%p能以十六进制输出变量的地址

 #include <stdio.h>
int main()
{
	int i=0;
	printf("%p\n",&i); //输出的为地址
	return 0;
}

地址的大小,它的数据类型和int是否相等取决与编译器
&只能对变量取地址,不能对i++,++i,p+i这类取地址

数组的地址

 #include <stdio.h>
int main()
{
	int a[10];
	printf("%p\n",&a);
	printf("%p\n",a);
	printf("%p\n",&a[0]);
	//上面三个输出地址相同
	printf("%p\n",a[1]);
	//与上面三个地址差距是4
	return 0;
}

&a=&a[0]
数组相邻单元地址相差是4

二.指针
就是保存地址的变量

int *p,q;
int* p,q;
//以上两个意义相同,且只有p是指针

普通变量的值是实际的值
指针变量的值是具有实际值的变量的地址

 #include <stdio.h>
void f(int *p);
int main()
{
	int i=6;
	printf("&i=%p\n",&i);
	f(&i);
	return 0;
}
void f(int *p)
{
	printf("p=%p\n",p);      //输出的为变量i的地址
	printf("*p=%d\n",*p);    //输出的为变量i的值
	*p=26;                   //实际改了i的值
                             //p是一个指针指向i这个变量
}

*是一个单目运算符,用来访问指针的值所表示的地址上的变量
可以做右值也可以做左值
如:int k=*p ; *p=k+1

int i=3;
scanf("%d",i);//会误将i的值当成地址去处理

三.指针的使用

应用场景1

函数返回多个值,某些值就只能通过指针返回

 #include <stdio.h>
void swap(int *pa,int *pb);

//交换a与b的值 
int main(void)
{
	int a=5;
	int b=6;
	swap(&a,&b);
	printf("a=%d,b=%d\n",a,b);
	return 0;
}
void swap(int *pa,int *pb)
{
	int t = *pa;
	*pa = *pb;
	*pb = t;
}

应用场景2

函数返回运算的状态,结果通过指针返回

 #include <stdio.h>
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;       //返回0即表示不可除
	else{
		*result = a/b;     
	}
	return ret;              //返回1表示满足条件
}

指针最常见错误
定义了指针变量,还没有指向任何变量,就开始使用指针

int *p; 
*p=12   //不能直接这样写!

四.指针与数组
函数中输入数组:
函数参数表中的数组实际上是指针,故数组输入函数时[]里不写数
sizeof(a)==sizeof(int*)
可以用数组的运算符[]进行运算

//在参数表中以下四种函数是等价的
int sum(int *ar, int n);
int sum(int *, int);
int sum(int ar[],int n);
int sum(int [], int);

数组变量是特殊的指针
数组变量本身表达地址,所以

  • int a[10];intp=a; //无需用&取地址
  • 但是数组的单元表达的是变量,需要用&取地址
  • a==&a[0]
  • []运算符可以对数组做,也可以对指针做:
  • p[0]<==>a[0]
  • 运算符可以对指针做,也可以对数组做:
  • *a = 25;
  • 数组变量是const的指针,所以不能被赋值
  • int a[] <==> int * const a=…

五.指针与const
指针可以是const,指针指向的变量也可以const
1.指针是const

  • 表示一旦得到了某一个变量的地址,不能再指向其他变量
  • int * const q = &i //q是const
  • *q = 26 //OK
  • q++ //ERROR

2.所指是const

  • 表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)
  • const int *p = &i
  • *p = 26 //ERROR
  • i=26 //OK
  • p = &j //OK
//前两个为所指不能被修改
const int* p1 = &i;
int const* p2 = &i;
//第三个为指针不能被修改
int *const p3 = &i;

判断哪个被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!
  • 当要传递的参数的类型比地址大的时候,这是常用的手段:既能用比较少的字节数传递值给参数,又能避免函数对外面的变量的修改

const数组

  • const int a[]={1,2,3,4,5,6,}
  • 数组变量已经是const的指针了,这里的const表明数组的每一个单元都是const int
  • 所以必须通过初始化进行赋值
  • 可以设置参数为const,用来保护数组不被函数破坏
  • 如:int sum(const int a[], int length)

指针运算
指针+1不是在地址值上+1而是在地址上加一个size of那个指针所指的类型

 #include <stdio.h>
int main(void)
{ 
	long ac [] = {0,1,2,3,4,5,6,};
	long *p = ac;
	printf("p = %p\n",p);
	printf("p+1 = %p\n",p+1);
	printf("*(p+1)=%d\n", *(p+1));     //*(p+n)<->ac[n]
	int ai [] = {0,1,2,3,4,5,6,};
	int *q = ai;
	int *q1 = ai[6]
	printf("q = %p\n",q);
	printf("q+1 = %p\n",q+1);

	printf("q1-1=%d\n",q1-q);          
	//结果为这两个地址的差除以sizeof的类型,表示在它们中间能放几个这样类型的东西
	
	return 0;
}

*p++

  • 取出p所指的那个数据来,完事之后顺便把p移到下一个位置去
  • *的优先级虽然高,但是没有++高
 #include <stdio.h>
int main(void)
{
	char ac [] = {0,1,2,3,4,5,6,-1,};
	char *p = ac;
	int i;
	//以前的遍历方法
	for ( i=0; i<sizeof(ac)/sizeof(ac[0]);i++){
		printf("%d\n",ac[i]);
	}
	//用指针进行遍历
	while (*p != -1){
		printf("%d\n",*p++);
	}
	return 0;
}

指针比较

  • <,<=,==,>,>=,!=都可以对指针做,
  • 用来比较它们在内存中的地址,
  • 数组中的单元的地址肯定是线性递增的

0地址

  • 0地址通常是不能随便碰的地址
  • 所以指针不应该具有0值
  • NULL是一个预定定义的符号,表示0地址

指针的类型

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

指针的用途

  • 需要传入较大的数据时用作参数
  • 传入数组后对数组做操作
  • 函数返回不止一个结果
  • 需要用函数修改不止一个变量

六.动态内存分配
malloc
#include<stdib.h>
void* malloc(size_t size);

  • 向malloc申请的空间的大小是以字节为单位的
  • 返回的结果是void*,需要类型转换为自己需要的类型
  • (int*)malloc(n*sizeof(int))
 #include <stdio.h>
 #include <stdlib.h>    //malloc的头文件
 
int main(void)
{
	int number;
	int *a;
	int i;
	printf("输入数量:");
	scanf("%d",&number);
	a = (int*)malloc(number*sizeof(int));      //申请一块内存空间
	for (i=0; i<number;i++){
		scanf("%d",&a[i]);        //此时申请来的空间可以当数组使用
	}
	for(i=number-1;i>=0;i--){
		printf("%d",a[i]);     //逆序输出数组
	}
	free(a);       //要用free还回去
    
	return 0;
}

free()只能还申请来的空间的首地址

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值