c语言笔记(3)
const用法
1.修饰局部变量,防止只读内存区域的赋值程序立刻异常终止
2.区分常量指针和指针常量:const在*左,为常量指针;在右为指针常量
3.修饰函数,防止修改指针指向的内容/地址
4.修饰函数返回值 防止出现编译错误
5.修饰全局变量
strtok函数
分割字符串
char *strtok(char *str,const char *delim);
str:要分割的字符串 delim:分隔符字符串
函数
把为了实现某一特定功能的所有语句归纳在一起形成了一个函数
函数一般实现单一功能
一般来说函数的定义如下
返回类型 函数名(参数列表)
{
函数的实现语句;
函数返回语句;
}
return语句不可返回指向"栈内存"的“指针”或者“引用”,因为该内存单元在函数体结束时被自动释放
面向对象和面向过程
面向过程是分析解决问题的步骤,再用函数一一实现
面向对象是把构成问题的事务分解成各个对象,为了描述所发生的行为
伪代码:描述模块结构的语言,可以以任何一种编程语言实现
函数传参
传值(对实参值的拷贝,是实参的一个副本)
void Func1(int x)
{
x=1;
}
传指针(int *x)
传引用(int &x)
传值不能改变实参,传指针和传引用效率更高,传引用更安全
数组做函数参数防溢出
1.把数组的元素个数一起传过来做函数的参数
2.传数组的引用
调用约定
参数传递,栈平衡
调用约定类型
cdecl(c语言默认) stdcall(windows API) fastcall(x64) thiscall(C++) nakedcall(底层HOOK)
static函数(内部函数)
1.局部变量只执行初始化一次,延长局部变量的生命周期
2.修饰全局变量或一个函数时只能在本文件中访问调用
3.不想被释放时用static修饰
4.更具有数据安全性
inline内联函数
与函数定义体放在一起使函数成为内联
如果函数体内代码比较长或出现循环,不宜使用内联
内联函数放在头文件
避免调用函数对栈内存重复带来的消耗
外部函数
如果定义函数时在首段开头加extern,则此函数是外部函数,可供其他文件调用
什么时候需要取地址
当变量是指针类型或数组时,不需要取地址符号 scanf输入的是地址
switch语句
没有break时,只要有一个case匹配剩下都要执行;有break直接跳出switch语句
switch只能和break一起用,不能和continue一起用
指针
指针是一个变量,它的值是一个内存地址,指向内存的某一个地方,明确该内存的宽度
指针含义分为三个方面:(变量&&地址&&内存宽度)
定义指针: 类型名 *指针名 char *pch
解引用运算符: *p 通过指针找到对应的内存和里面存放的数据 (运算符后面必须是指针,不能为无效内存或NULL)
*在指针定义时,是和类型结合
*在指针使用时,是取内存(解引用)
*p中,p必须是有效地址 否则会引发程序崩溃
指针类型与互相转换
char *p 指向内存单元1个字节
short *p 2个字节
int *p 4个字节
float *p 4个字节
double *p 8个字节
sizeof(*p) = 所指类型的长度
sizeof(p) 指针的长度
字符指针
既可以指向字符,也可以指向字符串;将字符或者字符串传给函数做参数,也可以通过字符指针完成
假如p是指针,那么*p是指针p所指向的内存位置的值
一级指针:存放普通变量的内存地址
二级指针:存放一级指针的地址
int a = 10;
int *p = &a;
int **pp=&p;
传参
int func1(unt x); //传实参值,不能改变实参
int func2(int *x); //传实参指针,修改实参
int func3(int &x); //传实参引用,修改实参
int func4(int **x); //实参是指针,传指针的指针,修改指针
int func5(int *&x); //实参是指针,传指针的引用,修改指针
程序内存布局
程序内存分为:栈区,堆区,全局区/静态区,常量区,代码区(高地址→低地址)
系统内存主要分为内核空间(用户程序通常无法直接访问)和用户空间
内存地址分类
逻辑地址:编译器生成,使用c语言指针时,指针的值就是逻辑地址;逻辑地址由段地址+段内偏移组成
线性地址:由分段机制将逻辑地址转化而来
物理地址:CPU在存取数据时最终在地址总线上发出的电平信号,靠该地址访问对应数据
寻址:从逻辑地址到物理地址的翻译过程
内存寻址模型主要分为两种:实模式分段模型、保护模式扁平模型
浙公网安备 33010602011771号