指针深入2

封装一个函数怎么样返回多个值?

1.用数组,例 int a = 2,b = 3; 返回a +b与 a * b;

int* calculate(int a, int b) {
	int add = a + b;
	int mul = a * b;
	int arr[] = { add,mul }; //假设arr地址为0x111,存放数据5,6
	return arr;//地址在这个函数,在这个花括号内是存在的,出了这个花括号,地址还会存在,只不过值不一定了
}
int main() {
	int a = 10, b = 20;
	int *arr = calculate(a, b);
	printf("%d,%d\n", arr[0], arr[1]);
	return 0;
}

这个方法有缺陷, 在主函数中,变量a,b的地址是定值,一直到程序结束,它们的地址值都不会发生变化。但在封装函数calculate中,一旦封装函数调用完毕,所有局部变量均被回收,系统会重新划分内存,arr地址0x111可能找不到,也可能存放了其它的数据。在这个程序中,因为只有a,b两个变量且地址已经固定。如果,还有其它变量,那么0x111地址可能会被占用,那么add与mul的值会被覆盖掉。

 这种方法有随机性,代码有时候结果正确,有时候不一定。

所以,返回值类型不能是局部变量或临时变量的地址

2.参考scanf 函数的原理,scanf 函数用的时候,先定义一个变量 int num; scanf("%d",&num);

scanf 函数把从键盘上输入的值从scanf的作用域带出来了,并且赋值给了num。参考scanf函数的形式参数&num, 可以得知,从键盘上获取的值连同定义的变量的地址,一起传到scanf函数里面,在内部通过指针的解引用,将键盘上获取的值带出来并且赋值给num

所以,在主函数中定义a,b两个变量同时将它们的地址传到封装函数里,在封装的函数内部进行解引用,通过形参来改变实参。

void calculate(int num1,int num2,int* a, int* b) {
	
    *a = num1 + num2;
	*b = num1 * num2;
	
}
int main() {
	int a = 10, b = 20; 
	calculate(a,b,&a, &b);
	printf("%d %d\n", a, b);
	return 0;
}

一维数组与指针之间的关系

数组名代表数组首元素的起始地址,数组的访问有两种方式1.通过下标访问arr[index]2.通过指针解引用来访问,*(arr +index)。arr[index] = *(arr  + index)

arr + 1 ,数组首元素的地址向后平移一个单元格,单元格的大小与数组类型有关。

指针与const的结合

1.const 放在*前

const  int *q = &value; 等价与 int const*q = &value;这是因为 const 对于基类型int而言,基类型相当于透明的。const在*前,修饰的是*q,也就是说q所指向的变量的值被锁定,可以访问,不能通过*p解引用被修改,但q(指针变量)可以改变,他可以等于&value,也可以等于&p.

2.const 放在*后

int * const q = &a; 这个与上面的区别是, 这个const 锁定的是q指针变量, q 不能改变,它指向a地址,就永远只能指向a地址, 不能等于其它的值,但可以通过解引用改变它所指向的变量的值。

如果碰到不让修改的数据,(const int a = 10; const int *p = &a;) ,我们可以 定义一个const int*p 类型的指针。

指针与字符串

char ch[] = {"hello"}; 字符数组,其中的元素值可以改,char[0] = 'a';

而char*p = "hello"; ,这中定义方式下的字符串以字符串常量的形式存在,字符串中的单个元素不允许被修改,*(p+1}='a'不成立,字符串常量就是常量。char *p 定义与字符串定义相矛盾,不要让*p修改p所指向的常量的值,与const 结合,锁住*p, const char*p = "hello"; 这种才是语法层面上的定义,指针指向字符串 const char * p = "hello";

涉及到函数调用,局部变量在栈区.stack区,而字符串常量,常量,全局变量在数据区.data区存在,

数组指针与指针数组

指针数组,落脚点是数组  char *arr[] = {……};数组内部存储的都是char*类型的元素;而字符串是char*类型元素的一种,所以 const char* arr[] =  {"hello","world'};

字符数组,用char类型定义,字符串数组用char*类型来定义,但字符串就是常量,所以定义字符串数组时,需要在*前加const; 常量没有办法通过解引用来改变值,

数组指针,落脚点在指针,指向整个数组大小的指针变量

 可以看出,数组指针加一,加的是 整个数组的字节数,怎么定义数组指针?

int (*p)[num] = &arr;  解释:1.*的优先级高于[], 2.num为几,就代表指向有几个元素的数组数组指针,指向数组的指针 int(*p)[] = &arr,[]的优先级高于定义指针时的*, 这里,我们把指针,指针加1,数组名,数组首元素的地址,还有数组的地址都打印出来,会发现数组指针加1,加的是整个数组所占的字节数,而且,数组指针指向的地址与数组首元素的地址,数组的地址一模一样。&arr[0]  == &arr ==arr ,区别是,定义数组指针时,如果你在数组名前加了取地址符&,那么这个指针,加的就是整个数组的字节数。

typedef 用法:1.在自定义的头文件中进行函数声明时,可以对函数的类型进行重命名

typedef int ElemType;  将函数类型int 换一个新名字ElemType;

 如果后面你不想用int 类型,想换double类型,只需要将第二行代码中的int 换为double 即可,类型重命名可以方便后面数据类型的切换。

头文件中进行函数声明,要实现函数功能,需要重新添加一个源文件(.cpp)文件,然后在源文件中实现功能。

 在源文件中,我们需要引入自己写的头文件,在此说一下,#include<stdio.h>  与#include“stdio.h"

中<>与“”的区别,尖括号的意思是,在系统配置的路径下可以找到头文件,而双引号的作用是,系统在先在自己的项目中查找自己写的头文件,没有找到,然后会在系统路径下查找头文件。

输入缓冲区,从键盘上获取的所有值全部放到内存当中的一个地方,scanf 从输入缓冲区读取,

输入缓冲区有两个指针,一个头指针,一个尾指针,交替穿插进行, scanf("%d %d %d",&a,&b,&c);

通过指针偏移读取数据,直到读完。两个指针的走法

#define MAX 11  MAX 被替换为了11

typedef与#define 的作用不同,#define只是简单的宏替换,而typedef是类型的重命名

我们会发现,看到pointer就用int* 替换,结果定义出来的m,n,一个是指针,一个是整数,类型不匹配,所以报错。

而typedef是对指针类型进行重命名,重命名后会发现,它定义多个变量时,就与简单的宏替换不一样。

数组指针的重命名

int(*pointer)[3];?//声明了一个数组指针,它的名字是pointer,指向的是一个含有3个元素的数组

第一步,先进行一次数组指针的声明,2. 前面直接加typedef,

函数指针,指针指向函数时,不需要加取地址符

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值