C语言——语言——言——盐——yan——an——n——‘/0’——
C语言常见类型大小空间
char 1;
short 2;
int 4;
long int 4;
long long 8;
float 4;
double 8;
long double 8/12;
bool 1;
C语言常识(无限补充。)
1.模块功能和参数应保持性能单一
2.比较时左边因放置常量
3.字符会被计算机识别为ASCII码
4.一个返回值最好不要给太多意义
5.定义变量只有一个意义 不能具有一个以上意义
6.一个返回值最好不要给太多意义
7.返回值分裂,错误信息返回。
8.全局变量都在数据区,局部变量都在栈区。
类型转换分为两种
一种是形和值都要转
一种是只转形不转值
C语言的编译过程
可见性见证编译链接
生存期见证运行过程
未成功编译不要谈生存期
.c/.cpp 源文件 //C语言编写
//*预编译:(看见#就是预编译过程)
1. 删除所有宏定义和注释
2. 处理所有的条件预编译指令 如#if #ifdef #undef #ifndef #endif #elif
3. 处理#include,将包含的文件插入到此处。将.h文件添加入编译文件.i文件种
4. 添加行号和文件名标识,以便于编译时产生的错误警告能显示行号
5. 保留#pragma编译器指令
6. 只做替换,不进行类型检查
.i //预编译后生成
*编译:
1.将预处理完的.i文件进行一系列的词法分析、语法分析、类型检查
2.化后生成响应的汇编代码文件
3.sizeof在编译阶段处理
汇编:
1.将汇编代码编译成机器可执行的指令(每条语句对应一个指令)
.o/.obj //编译后生成 目标文件
*链接:
1.链接动态库与静态库
2.lib静态库
3.dll动态库
4.全局变量都在数据区,局部变量都在栈区,字符串数组也在数据区。
.text .data .heap .stack
.exe //可执行文件,连接后生成
宏定义与常变量
define后面不加分号
没有类型
不开辟空间
单纯操作字符串替换
意义:
避免使用错误返回时return -1等时表意不清。
return -1可读性太低
宏定义替换 见名知意
常变量:开辟空间,需要内存检查。
const与指针
能力收缩
//const 修饰* 封锁指向
const int *p1 =&a; //*p1=100(错误),p1=&b允许
int const *p2 =&a; //同上
//const 修饰变量 封锁自身
int * const p3 =&a; //*p3 =100; p3=&b(错误 变量被修饰,不能改改变)
const int * const p4 =&a //啥都别变了 变啥都是错
能力扩张不能编译成功
const int *p =&a;
int *s1 =&a; //不能通过
循环
//无限循环收集用户信息
do
{
循环语句;
}
while(条件表达式)
执行顺序(条件表达式->循环语句->条件表达式)
while(条件表达式)
{
循环语句;
}
执行顺序(条件表达式->循环语句->条件表达式)
//固定循环次数/条件
for(表达式1;条件表达式;表达式2)
{
循环语句;
}
(执行顺序 表达式1->条件表达式->循环语句->表达式2->表达式1)
//多项选择并显示 根据输入调用不同函数
switch(flag)
{
case flag: 执行的语句;break;// 不加break会向下一直执行case,直到遇见break;
case flag: 执行的语句;break;
}
数组
数组具有类型相同,内存空间连续的特点。
声明时,数组下标满足:
1.不为0;
2.是整数且是整数;
3.是一个常量。
4. 数组名sizeof识别为整个数组(类型和大小),其余编译器皆让ar成为首元素地址;
5. 传递一维数组时,编译器传送的参数不是数组,而是指针;
6. 可以多数组元素进行随机性访问;
7. 访问方法 1.下标法,2.指针法;
8. 实际访问只有一种:指针法。下标法会转化为指针法。
9. 数组初始化没写的的位默认为0。
char str1[]={"123456"}; //字符串
char str2[]={"1","2","3"}; //字符数组
char *str =“123456” //常性字符串 不可改变吧等同于const char *str =“123456” ;
字符串后最后又“/0”
字符数组没“/0”
当数组作为参数传递过去后,如果接收的参数是也是一个数组,那么它就会退化为一个指针,也就是我们常说的“数组就是一个指针”。当接收的参数是一个数组引用时,就会发现它还是保持了自己的原生态,即“数组仍然是一个数组”。这时,数组引用就起到了一个保护自己退化为一个指针的作用
指针
p存地址 p=地址 指针=地址
p中位解引用 *p指向p指向地址中所存的值
初始化指针时 *表示声明,不进行解引用所以需要将地址赋值给int *p;
*和变量名结合 不和类型名结合
指针动态开辟内存在堆区
野指针,新建指针后没有初始化;可以解引用
空指针,兴建后初始化(赋值)为NULL;不能对空指针解引用
char *str =“123456”
//字符串不在所在函数栈帧,在数据区 ,指针自身在栈区
//字符串在这里是字符串常量(str3/str4) 不允许修改
//字符串放到数据区,使得str指向首元素地址
//字符串一样 只开辟一个地址 无论多少指针指 指针都相等 都指向一个字符串
int *(声明意义)p = &a
p =&a
*(指向意义)p =100;
*p 解引用 =a本身
物理地址位0X12345678
空间地址位 变量名
X86体系下 指针开辟四字节
地址八位16进制 4*8=32 bite =4字节
1字节8位
低地址充当首地址 (指针指向的地方)
//失效指针
int main()
{
int a = 10;
int *p = NULL;
if(10 == a)
{
int x =100;
p =&x; //出模块后失效 x属于块内
}
}
//失效指针
int *fun()
{
int a =100;
return &a;
}
int add()
{
int x = 0;
}
int main()
{
int *p = NULL;
p = fun(); //函数结束后分配给a地址中的值释放,新函数中变量占用a地址
add();
printf("%d\n",*p);
return 0;
}
函数
结束后返回调用点,继续执行。
函数功能单一,功能函数不负责报错信息
返回明确且单一,不能具有多意。
设计业务层不能有ui逻辑,用变量记录错误状态,主函数处理
函数调动中,无论是如何调动,一旦被调动都会在栈帧给函数分配空间。
对形参的合法性进行检查,更具函数的功能要求检查形参的合法性。
传值过程:形参的改变不影响实参(函数不具有副作用)
形参和实参的结合,从右到左。
函数以及形参(局部变量)分配了新栈帧,使用完后释放,影响不到主函数栈帧内容。
栈达到了重复利用,释放后调用新函数使用上次释放的栈(数据是连续的,空间重复使用)
return作用: 新建临时量存放返回值(copy到临时量),结束函数(释放栈帧后将临时量返回给主函数)。
static 静态量存放在数据区,第一次创建并初始化,之后再不创建,直到程序结束被销毁。
数组名传送给函数的形参时,退化为指针。(节省了时间和空间,把函数地址给形参调用数组本身,不用copy数组过去,又节约时间不需要copy直接通过地址调用,又节约空间不再次copy存储)
如果使用需要两个形参,一个是指向数组首元素的指针,一个是元素的个数。
C++输入输出流
io 输入输出 stream流操作
'>>'提取符
'<<'插入符
小/大端存放
高地址存高位数
高地址存低位数
引用和别名
引用 别名
:: 作用域解析符
加上使用全局变量
作用域、可见性及生存期
作用域:
局部定义局部使用
包括静态变量
其他函数不可见函数定义的变量
void add()
{
static int max =0; //静态变量前有一个标志位 如果标志位未1 则执行初始化为常数在链接阶段执行,且标志位置零
static int min =x; //如果初始化为一个变量,则初始化为常数在执行阶段,且在第一次执行后标志位置0 第二次执行时标志位为0 不执行
}
可见性
初始化后 后面的代码才可知道
void A();
void A()
{
x=100; //编译器从上到下阅读 读到这一句没有发现X变量 X的可见性在X初始化以后
}
int x=10;
int main()
生存期
全局变量全在 数据区
数据区有啥
全局变量
静态变量
常字符串
char str = “12346”
局部变量 全在 栈区
可见性见证编译链接
生存期见证运行过程
未成功编译不要谈生存期
断言
c 断言
表达式为真 则继续 表达式为假 则退出 就在当前位置、
使用规避手段处理未知语法
#include<stdio.h>
#include<assert.h>
void test(void);
int main()
{
test();
return 0;
}
void test(void)
{
int i=0;
assert(i);
i++;
printf("%d\n",i);
}
前项声明
隐藏结构体/类
暴漏接口