二维数组 做函数的形参
形式上: //形参 --数组形式,行数
void printArray(int a[3][4],int row);
实际上:
void printArray(int (*a)[4],int row); //编译器 的最终解释
实参:
printArray(a,row); //数组名 行数
int a[3][4] ---int a[][4]
int[4] a[];
输入设备---CPU ---输出设备
|
V
存储器
总线 -- 0101
总线的宽度
总线
(1.数据总线 2.控制总线 3.地址总线)
二维字符型数组做函数形参:
char s[3][10] = {"hello","world","china"};
形式上:
void printStr(char s[][10],int row) //注意需要传行数,因为操作多个字符串
本质上:
void printStr(char (*s)[10],int row)
实参:
printStr(s,row); //数组名 行数
标识符 作用域 和 可见性问题
作用域:
作用的范围
局部变量 --- 一定在某一个{} 范围内
全局变量 --- 不在任何一个{} 范围内
可见性:
程序运行到某个点,哪些标识符可见
标识符的可见性的规则:
1.先定义,后使用
2.同一作用域中,不能有同名标识符
3.在不同的作用域,同名标识符,相互之间没有影响
4.如果是不同的作用域,
但是作用域之间存在嵌套关系,
则,
内层的作用域的同名标识符,会屏蔽外层的作用域的同名标识符。
(就近原则)
时间上去区分:
动态变量(局部变量-空间是开辟在栈上的--自动申请自动释放) (声明周期):
从定义的语句开始,到所在的作用域范围结束
eg:
栈上的 局部变量
静态变量 (全局变量)
从程序一开始运行,就存在,
直到程序结束时,销毁
eg:
全局变量
static 局部变量
注意:
全局变量(静态变量) --- 此时,
1.不能用变量进行初始化,只能常量初始化
2.静态区的变量
只会被初始化一次
3.值具有 继承性
static
int main()
{
int a; //栈
}
auto //
auto int a; //存放在栈上 这个是一个自动变量 --- 栈上开辟的变量
static int a;
//修饰局部变量时,数据存放在全局区(静态区),程序运行结束,数据a才销毁。延长了局部变量的生命周期。
//修饰全局变量时,将数据限制在本文件中,不能用extern跨文件使用。
extern int a;//扩展 延伸。表示不在这个a不是在当前文件中定义的。如果要用,要到别的文件中寻找。一般用在多文件编程中,如果想在当前文件使用别的文件中的 全局变量,此时可以使用。
extern 可以放在函数声明中 --函数声明 //表示的意思--将函数作用域扩展到当前文件
static 加在函数前面 //此时效果和修饰全局变量效果一样
//将函数作用域限定到本文件中
register int a; //将a存在CPU 寄存器里,用于计算速度要求快的情况
考点:
不能 & (取a的地址) 因为a已经在寄存器中开了空间准备存储,不在栈里
register int i;
for( i = 0; i < 100000000; ++i)
{
}
十:指针
指针:指针+基本数据类型
指针+数组
指针+函数
指针+指针
指针类型:是一种数据类型
指针类型专门用来放 指针(地址编号)这种数据,占八个字节。
1.指针 (如图)
地址----内存单元的编号
2.指针变量
语法:基类型* 指针变量名
//基础数据类型
//数组类型
//基类型 表示指针变量指向的目标的数据类型
* //表示此时定义的变量,是一个指针类型的变量
指针变量名---标识符命名规则 + 见名起意
int *p;//表示定义了一个指针类型的变量 p是 int*型
int a;//a为int型
a = *p;//*p为int型
*p表示数据
p表示一个地址
int a = 10;
int *p = &a;//指针变量p指向了int型变量a
float *p = &b; 不行,因为p的数据类型为int *型,表示被指针p指向的区域a或b必须为int型
得到地址后放在p的空间里。
&b -- 地址值 ---类型?
float
b有一块内存空间--放的是float数据
&b --- 得到了一块存放着float类型数据的 空间的地址
指针变量:
访问变量时:
直接访问
间接访问 通过地址访问到的
*指针运算符
*单目运算
运算数必须是指针类型的值(地址)
*p过程
1.取地址并定位:首先拿出p指针变量中的值(地址值)到内存中定位
2.根据数据类型偏移空间:从定位处开始,偏移出sizeof(基类型)大小的一块空间
3.空间当作变量看:把这块空间当作一个基类型的 变量来看
int a = 10;//整型
int *p = &a;
printf(“%d\n”,*p);// *p <=>a
a = 20;
*p = 20;
想实现:
被调函数修改主调函数
1.想修改谁,就把谁的地址传过去
2.必须要做*运算(间接访问),实现修改
指针的运算:
1.&
2.*
3.p+1 //指向了下一个基类型的数据
//跳过了下一个基类型
4.p++
p-1
p--
指针 + 数组
一维整型数组
int a[5]; //a首元素的地址
//a[0] -- int型
//&a[0] -- int * 因为是地址型 所以是int *型数据
int *p = &a[0]; //想要取a[0]的地址,所以定义这个地址名为p,数据类型为int*型,取a[0]的地址赋给它
= a; //a[i]的首元素的地址也就是a[0]的地址就是a
a[i] <=> *(a+i) //指针运算 首元素的地址a再+ i
野指针:
int *p; 指向随机地址
int *p = NULL; //NULL为0号地址,从0地址开始,不能访问,段错误。