C语言基础整理 (3)函数补充及指针

函数补充

可变长参数列表:

例:
有三个点(...)
int printf(const char *format,...);
int scanf(const char *format,...);
第一步:声明va_list变量
	va_list ap; 
第二步:初始化
	va_start(ap,形参列表中最后一个形参名last);
	
第三步: 获取值  每调用一次该方法会获得一个参数  type是参数的数据类型
	type x = va_arg(ap,type)
	
第四步: 关闭资源
	va_end(ap);

函数参数的传递过程:()

(1)实参和形参可以同名,也可以不同名,但是对应位置的类型得一致,一致并不代表完全一模一样,一致可以是隐式类型转换,所以如果类型不一致,编译时将报错
(2)形参在函数调用时被初始化了,是用实参的值初始化
(3)实参和形参是不同的两个变量 它们只是在调用初始化值 一样而已
(4)C语言中函数传递的过程是值传递的过程 即复制
(5)对于普通数据类型 在函数中修改形参的值 并不会影响实参的值
   注意:对于数组而言,在函数中修改数组中的元素  会影响原来实参数组的值,对于指针而言,在函数中修改指针所指向的值,会影响原来实参数组的值。
(6)关于定义函数时不让函数修改形参的值
	形参类型前加 const  表示在该函数中不能对形参的值进行修改
	一般情况下  修改 数组 才有意义
		例:func(const int arr[],size_t len) 数组中的元素在该函数中不能被修改
	const作用:
	形参加const,防止在函数中意外地修改
	增加代码的健壮性 和 可读性
	const修饰的变量,表示 只读  不可以修改

内存地址:

声明变量  这个变量其实代表一块内存区域
操作变量 其实操作的是这片内存区域里存储的值
对于变量可以进行取址(&)运算,取得这个变量所代表的内存地址
对于取址运算符(&) 操作数只有一个,且只能是左值
%p  可以输出一个地址   地址:一个编号 一个十六进制的整数
内存地址即指针
指针变量 可以 保存 内存地址 
一个程序中有多少个地址?   4G
2^32个地址
2^10 * 2^10 * 2^10 *2^2
4 * 1024*1024*1024 Byte  = 4G
每一个运行的C语言程序在内存中都有4G的虚拟内存  0-0xffffffff

4G虚拟内存:

	从低到高地址依次为: 代码段、全局区、堆区、栈区
	代码区: 代码指令   字面值字符串
	静态全局区:
		数据段: 已经初始化的全局变量和已经初始化的静态变量
		BSS段:  未初始的全局变量  和 未初始化的静态变量
	堆区:  动态内存
	栈区:  局部变量  函数调用开销

关于4G虚拟内存之后的补充:

	进程在内存空间中的布局就是进程映像,从低地址到高地址依次为: 

	代码区(text): 可执行指令、字面值常量、具有常属性的全局和静态局部 变量。只读。

	数据区(data):初始化的全局和静态局部变量。 

	BSS区: 未初始化的全局和静态局部变量。 进程一经加载此区即被清0。 数据区和BSS区有时被合称为全局区或静态区。 

	堆区(heap): 动态内存分配。从低地址向高地址扩展。 

	栈区(stack): 非静态局部变量, 包括函数的参数和返回值。 从高地址向低地址扩展。 堆区和栈区之间存在一块间隙,一方面为堆和栈的增长预 留空间,同时共享库、共享内存等亦位于此。 

	命令行参数与环境区: 命令行参数和环境变量。

变量:

	块变量:定义在语句块中的变量
		(1)存储位置:栈区 
		(2)生命周期:语句块执行阶段
				语句块执行时生成,语句块结束消亡
		(3)作用域:在定义块变量开始位置到语句块结束位置
		
		语句块  {   }
	
		注:在同一个作用域下面,变量名不能相同
	
	局部变量:定义在函数中的变量(形参)
		(1)存储位置:  栈区
		(2)生命周期:  函数调用时创建,函数返回时消亡
		(3)作用域:    局部变量定义位置以后至函数结束
		
	全局变量:定义在全局位置(在函数外)的变量
		(1)存储位置:全局区
		(2)生命周期:整个程序运行期间
		(3)作用域:所有代码文件

局部变量和全局变量:

	(1)局部变量如果不初始化是随机值(垃圾值)
	   全局变量即使不初始化 也会 自动初始化为0
	(2)局部变量优先原则:
		局部变量可以和全局变量同名
		在访问同名变量时局部变量会隐藏掉全局变量
		块变量可以和局部变量、全局变量同名 就近原则

变量的修饰:

	auto    自动的   默认是auto   可以省略,一般不写
	static  静态的
		(1)static修饰局部变量 、块变量
			a.存储位置:局部变量的存储位置发生了变化,由栈区变为全局区
			b.生命周期:静态局部变量的生命周期为整个程序
			c.作用域:  没有发生变化
		静态局部变量的声明定义语句在整个程序过程中只会执行一次
		静态局部变量的值不会随着函数的调用而消失
		
		(2)static修饰全局变量
			a.存储位置: 没有变化 
			b.生命周期: 没有变化
			c.作用域:   静态全局变量只能在本文件中访问
		
		(3)static修饰函数
			表示该函数只能在本文件中调用		
	const   只读的
		修饰变量表示只读的  不可以修改
		作用:
			(1)修饰形参,防止在函数中意外修改
		    (2)增加代码的健壮性 和 可读性
	
	register 寄存器变量  不能取址
		申请把变量作为寄存器变量
		如果一个变量经常使用 或者 一直在使用 
		仅仅是一种申请,编译器可能拒绝
		(1) 寄存器要求数据必须是(32位)  int 
		(2) 寄存器变量不可以取地址  &

	volatile 易变的  修饰的变量表示可能随时发生变化 
		多线程的情况下
		volatile int x = 10;
		printf("%d\n",x*x);//有可能不是等于100  10
	
		int y = x;
		printf("%d\n",y*y);
	
	extern  声明一个在其它文件中定义的全局变量 

指针

指针定义:

	指针即内存地址
	指针变量 即 保存内存地址的变量
	内存地址(虚拟内存 -- 物理内存): 0-4G  一个十六进制的整数
	%p  

指针变量的声明:

		数据类型 *指针变量名;
	             * 不能省 表示指针类型
		数据类型: 指针变量存储的内存地址,该内存地址所存储的数据的类型

指针变量的初始化:

		&   取址符    作为取址运算符时,操作数必须是左值
		数据类型 *指针变量名 = &变量;

操作符 *

	取值运算符
	*(内存地址)    取内存地址中保存的数据
	*指针变量      取指针变量保存的那个地址里面的数据

操作符 &

	取地址运算符

	*&x == x 相互抵销
	例:
	int x = 10;
	int *p = &x;
		p == &x 
		*p == *(&x) == x == 10
	*p = 100; //相当于改变了x的值

	int y = 10;
	p = &y;   //指针变量保存了y的地址
	*p = 110; //改变的是y的值

栈内存 从大往小使用
堆内存 从小往大使用

地址+1  本质上加了一个单位长度(数据类型的长度)的地址内存

地址本身虽然只是一个十六进制的整数,但其实地址自带类型
char c = 'a';
char *pc = &c;
short s = 30;
short *ps = &s;

指针类型

   数据类型 * 是一个整体  表示的是地址的类型
	若char c = 'a';
	则char *pc = &c;
	若int x = 1;
	则int *px = &x;

指针变量的定义:

	数据类型 * 标识符;
	一般以p开头
	
	就像以下,看见首字母能知道它的类型
	int iAge;
	char cSex;
	long lDistance;

指针变量的初始化:

	int x = 1;
	int *px = &x;
	
	若不知道它保存什么地址:
	int *px = NULL;

NULL:

	表示一个特殊的内存地址  0  
	这个0地址 保存的是代码
	代码区的数据只读
	一般来说指针初始化都为NULL

野指针:

	一个指针变量没有初始化  指针里面的值为垃圾值  因为存储在指针变量里
	所以看作一个内存地址
	如果对该指针进行取*操作,将发生难以预测的后果 (灾难性的)
	所以在编程过程中一定要避免野指针

悬空指针:

	NULL
	对于悬空指针不能进行取*操作,一旦取*,必然是核心已转储 段错误

	所以一般在对指针进行取*操作前,都要对指针进行悬空判断 
	if(p != NULL){
		*p
	}

指针经典的一个应用,用函数交换两个值:

C语言中的函数的参数传递是值传递,值拷贝
	形参和实参是两个不同的变量
	只是在调用时会把实参的值赋值给形参
所以如果需要在函数中修改实参的值 那必须是传递地址
void swap(int a,int b){//只是交换了形参的值  交换不了实参的值
	int tmp = a;
	a = b;
	b = tmp;
}
void swap(int *pa,int *pb){//交换了形参的值  交换了指针变量的值
	int *pt = pa;
	pa = pb;
	pb = pt;
}
//野指针  非常危险
void swap(int *pa,int *pb){
	int *pt;
	*pt = *pa;
	*pa = *pb;
	*pb = *pt;
}
//正确
void swap(int *pa,int *pb){
	int tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值