C语言指针一

在这里插入图片描述


int main()
{
    int a = 10;
    int b = 20;
    
	int * const p = &a;
	*p =100;
	printf("%d\n",a);
	//结果a变成100
return 0;
}

const 修饰指针变量的时候放在*的右边,修饰的是指针变量本身,指针变量不能再指向其他变量,

但是可以通过指针变量,修改指针变量指向的内容

int main()
{
    int a = 10;
    int b = 20;
    
	int const *  p = &a;
	*p =100;
	printf("%d\n",a);
	//结果a不变
	return 0;
}

const 修饰指针变量的时候放在*的左边,修饰的是指针指向的内容(即 *p),指针不能再修改其指向内容,

但是可以修改指针变量本身的值(修改指针变量的指向)

//现在举个例子
int main()
{
	int n = 10;
	int m = 20;
	int * p = &n;
	//现在假设n与p是男女朋友,n有十块钱,现在p想吃凉皮动作就是
	//*p = 0;
	//但是 n还想留着去网吧
	//所以就相当于  int const * p = &n;  让*p = 0;这个动作不能发生
	//于是p就要换男朋友  p = &m;  这样就可以吃凉皮
    //n 一想不划算,为了10快丢啦媳妇 于是就改为  int * const p = &n;
    // *p = 0;就可以完成 但是 p = &n;就无法完成了
    
    // 要是*左右两边都有const, 既不能花钱又不能换对象
	
	return 0;

}



指针运算

一 指针加减整数

//  指针加整数
//  指针加一
//  int a = 10;
//  int *p = &a;
//  p+ --> 跳过四个字节(1*sizeof(int))
//  type*p;   p+1 --> 跳过1*sizeof(type)

#include <stdio.h>
//指针+- 整数
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &arr[0];
 int i = 0;
 int sz = sizeof(arr)/sizeof(arr[0]);
 for(i=0; i<sz; i++)
 {
 //printf("%d ",arr[i]);
 printf("%d ", *(p+i));//前提是数组在内存中是连续存在的
     //p+i 这⾥就是指针+整数  就是跳过几个整形类型
 
 }
 return 0;
}


二 指针减指针

指针减指针的前提条件是:两个指针指向了同一空间

#include <stdio.h>
int main()
{	
	int arr[10] ={0};
	printf("%d\n",&arr[0]-&arr[9]);  //-9
	printf("%d\n",&arr[9]-&arr[0]);  // 9	
		
	return 0;
}


用指针模拟实现strlen函数

	int my_strlen(char*str) {
	int count = 0;
     // char * start = str;
     //while(str!='\0'){
     //   str++;
     //	}         用指针减指针
     //return str-start; 
	while (*str != '\0') {
		count++;
		str++;
	}
	return count;
}

int main()
{
	char arr[] = "ahsjad";
	//strlen 统计的是\0之前的
	int len = my_strlen(arr);
	//数组名arr是首元素arr[0]地址  arr = &arr[0]
	printf("%d ", len);
}

三 指针的运算关系

指针和指针比较大小 地址和地址比较大小

#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
while(p<arr+sz) //指针的⼤⼩⽐较
{
printf("%d ", *p);
p++;
}
return 0;
}

野指针

野指针是指针指向的位置是不可知的(随机,不正确的,没有限制的)

一 指针成因

1. 指针未初始化
int main()
{ 
 int *p;//局部变量指针未初始化,默认为随机值
 *p = 20;
 return 0;
}
2. 指针越界访问

#include <stdio.h>
int main()
{
 int arr[10] = {0};
 int *p = &arr[0];
 int i = 0;
 for(i=0; i<=11; i++)
 {
 //当指针指向的范围超出数组arr的范围时,p就是野指针
 *(p++) = i;
 }
 return 0;
}

3. 指针指向的空间释放
#include <stdio.h>
int* test()
{
	int n = 100;
	return &n;
}
int main()
{
	int* p = test();
	printf("%d\n", *p);
	return 0;
}

二 规避野指针

1. 指针初始化

如果明确知道指针指向哪⾥就直接赋值地址,如果不知道指针应该指向哪⾥,可以给指针赋值NULL. NULL 是C语⾔中定义的⼀个标识符常量,值是0,0也是地址,这个地址是⽆法使⽤的,读写该地址 会报错。

#include <stdio.h>
int main()
{
 int num = 10;
 int*p1 = &num;
 int*p2 = NULL;
 
 return 0;
}
2.小心指针越界

⼀个程序向内存申请了哪些空间,通过指针也就只能访问哪些空间,不能超出范围访问,超出了就是 越界访问。

3.指针不再使用时,及时置为null,指针使用前检查有效性

当指针变量指向⼀块区域的时候,我们可以通过指针访问该区域,后期不再使⽤这个指针访问空间的 时候,我们可以把该指针置为NULL。因为约定俗成的⼀个规则就是:只要是NULL指针就不去访问, 同时使⽤指针之前可以判断指针是否为NULL。

4. 避免返回局部变量的地址

不要返回局部变量的地址。

asssert断言

assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报 错终⽌运⾏。这个宏常常被称为“断⾔”。

assert(p != NULL);验证变量 p 是否等于 NULL 。如果确实不等于 NULL ,程序 继续运⾏,否则就会终⽌运⾏,并且给出报错信息提⽰

assert() 的使⽤对程序员是⾮常友好的,使⽤ assert() 有⼏个好处:它不仅能⾃动标识⽂件和 出问题的⾏号,还有⼀种⽆需更改代码就能开启或关闭 assert() 的机制。如果已经确认程序没有问 题,不需要再做断⾔,就在 #include 语句的前⾯,定义⼀个宏 NDEBUG 。

#define NDEBUG
#include <assert.h>

然后,重新编译程序,编译器就会禁⽤⽂件中所有的 assert() 语句。如果程序⼜出现问题,可以移 除这条 #define NDBUG 指令(或者把它注释掉),再次编译,这样就重新启⽤了 assert() 语 句。

assert() 的缺点是,因为引⼊了额外的检查,增加了程序的运⾏时间。

传值调用和传址调用

在这里插入图片描述
7)

没有完成交换两个数的任务 因为当实参传递给形参是,形参实惨的一份临时拷贝,对形参的修改不会影响实参

所以现在要用传址调用
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值