avatar

目录
C语言学习笔记

Tips

C区分大小写
空格编译时会忽略不影响程序效率
字符型与整形互相通用
空白符:空格、制表、换行
宏变量EOF == -1
scanf如果重复读取,会自动沿用缓冲区数据,可以跟getchar();或者fflush(stdin);清空输入缓冲区

循环

  1. 反编译可知while相对于do whilefor效率更高

数组

  1. C中为线性存储结构

  2. 定义[]中为元素数,[]中常量表达式不叫下标

引用数组元素(也叫下标变量)时,数组下标从0开始。原因:可以参见《C陷阱与缺陷》

只能逐个引用下标变量

  1. 由1可得,数组大小不可动态定义

  2. int a[100]={0};集体赋值

  3. 初始化赋值时可以不指定数组长度。若赋值个数与长度不同,则不可

  4. scanf的第二个参数为地址,所以应为&A[i]

  5. 多维数组

定义时,[]间有空格。

内存中从前[]向后[]排列,单个[]中从小向大排列

初始化:只要有元素手动初始化,剩余元素默认初始化为0。若没有,初始化为内存中随机值

题目中iXj的···代表i行j列的···

c
A[i] [j] [k] = {{0},{},{0}}
A[i] [j] [k] = {0,0,0,0}
//i可以不填

函数

注意读音:标识(zhi)符

  1. main(){}void main(){}均可,即可以省略类型标识符。

C99规定:main只能用int

默认省略类型标识符等价于int,C++不可省略,建议都加

  1. 函数不能嵌套定义,除了main()

  2. 可以使用参数、返回值、全局变量、外部变量传递参数

  3. 调用函数时,形参才被分配内存空间,将实参赋值给形参,调用结束后释放

  4. 类型说明与返回值类型不一致时,以类型说明为准

  5. 函数调用约定

__cdeclC语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。(已遗弃)(需要自己手动清除)

__stdcall被这个关键字修饰的函数,其参数都是从右向左通过堆栈传递的(__fastcall 的前面部分由ecx,edx传), 函数调用在返回前要由被调用者清理堆栈。(由编译器自动清除)

pascal自右向左入栈

  1. 调用约定判断
c
int main(){
int i = 1;
F(i,++i);
}
void F(int i,int j){
printf("%d %d",i,j);
}
//1 2 自左向右求实参值
//2 2 自右向左求实参值
  1. 使用库函数时,先执行包含命令

使用非库函数时,若函数定义部分在主调函数后,需先在调用前声明(declaration)此函数

声明将函数名、参数数、参数类型通知编译器。即声明时可以只写形参类型(顺序必须对应)。声明不占内存

  1. 嵌套定义在C中非法,但可以嵌套调用
    递归:直接、间接调用本身,必有一终止条件eg.Hanoi塔问题

  2. 数组名作为参数

作为实参时,形参必须为类型相同的数组,为址传递不是值传递,即形参不被分配内存。
详见指针

  1. 变量作用域

局部变量:包括auto、局部staticregister变量

tips:形参不可以是静态变量

全局(全程)变量:外部staticexternmain函数体外的变量

全变在程序全部执行过程中占内存,而非仅需要时

全局变量可能会在文件包含时导致错误

一般要求函数封闭,只传参联系外界

  1. 变量的存储类别(生存期)

动态存储方式:需要时分配,不需要时释放

静态存储方式:程序运行开始时由系统分配空间

用户存储空间:程序区、静态存储区、动态存储区

变量和函数的属性:数据类型、存储类别

auto(自动)变量:形参,局部默认为此类,所以可以省略,在栈中存储(若不赋值,则初值不定)

static(静态)变量:在静态存储区储存,编译时赋值(若不赋值,数值变量或空字符默认赋值为0。因为空字符NULL的ASCII码为0),函数调用后保留值直到程序销毁

内存主要四大区:CODE,DATA,STACK,HEAPstatic将变量放入DATA

register(寄存器)变量:存取速度快。声明时若寄存器满,则自动变为auto变量。只有局部自动变量和形参可以做寄存器变量

extern(外部,全局)变量:放于静态存储区。

c
//也可用于扩展全变作用域
void main(){
extern A;
printf("%d",A);
}
int A = 0;
  1. 多文件程序使用外部变量

extern:用来声明变量,表示变量存在于其他文件中

static:使得全局变量仅限被本文件引用,而不被其他文件引用

  1. 声明与定义

定义式声明:需要建立储存空间。eg.int a;。简称定义

引用式声明:不需要建立储存空间。eg.extern a;。简称声明

广义上声明包括定义

  1. 内部、外部函数

内部函数:只能被本文件调用,标识符前加static

外部函数:extern默认省略

指针

  1. 指针就是元素的地址起始位置

指针变量是存放地址的变量,简称指针

  1. *P的含义是取P指向的变量地址的值,而非取此指针变量的值(若要如此,应为&P或者直接P

  2. ++*&等部分一元运算符属同级且均为自右向左运算

  3. 数组名在编译时,会翻译为下标为0的第一号元素。所以P = A等价于P = &A[0]

如此衍生得A[i]等价于*(A+i)等价于*P(tips:P = A

  1. 指针加减数字含义为加减单元格数,而非加减地址。单元格数为相应类型的字节数,而非字节数

指针加指针非法,指针减指针为间隔字节数除相应类型字节数

  1. 用数组名或指针作函数参数

编译时:将数组按照指针变量来处理

形参数组可以不填数组元素数,也可为指针变量。eg.F(int A[]){}

由4可知,调用时可以只给数组名。

  1. 多维数组与指针

预处理

在编译前执行,句末无分号

  1. 使用#define代换表达式时,最好给表达式整体加一个括号

  2. 调用宏时,实质是用实参代替了形参,而不是像函数一样赋值

  3. typedef在编译时处理,非预处理,对类型说明符重命名。被定义的标识符具有类型定义说明的功能。

  4. #include命令可以嵌套使用(在包含文件中包含子文件)

#include ""优先查找源文件目录,#include <>查找包含文件目录

  1. 条件编译
c
//形式1
#ifdef 标识符
#else
#endif
//形式2
#ifndef 标识符
#else
#endif
//形式3
#if 常量表达式
#else
#endif
//形式3变种,方便写注释
#if 0
//注释
此处不编译,可以不加双斜线
#else
#endif

未完待续

文章作者: 自由灵
文章链接: https://lemona.tk/13675369.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 自由灵的梦境
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论