vlambda博客
学习文章列表

C语言学习笔记之基础篇

0x00 前言概览

这个系列主要是整理 C 语言相关的一些知识,方便后期的复习与检索,适用者为学过基础的入门者编写程序时提供快捷便利的检索条件,纯小白可先收藏。 此系列大致分为基础篇、指针篇和实战篇,本文为基础篇,主要是一些零散知识点的整理,内容没有先后顺序,建议读者 Ctrl+F 查询; 同时本着极简原则,一些知识点会直接举例说明。

0x01 切入正题

  • 注释
 /* 单多行注释*/ //单行注释(C99新增标准)
  • 命名
编译器只识别前63个字符,对于外部标识符只允许使用31个字符(C99/C11); 名称第一个字符必须是大小写字母或下划线,不能是数字,区分大小写,但标识符最好不要超过8位。
  • 变量与常量
变量未初始值可能为 0 或垃圾值,不允许连续赋值,如 int a=b=c=5; 是不合法的。
定义常量:#define identifier valueconst type variable = value;
  • 参数
实参是传递给函数的特定值; 形参是函数中用于存储值的变量。
  • 编译器
编译器报错的位置比真正的错误位置滞后一行,无法检测语义错误,即遵循了C规则,但输出结果错误。
使用调试器,通过跟踪程序执行步骤,记录每个变量,监视程序状态排错。
  • 关键字和保留标识符
auto 声明自动变量break 跳出当前循环case 开关语句分支char 声明字符型变量或函数返回值类型const 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变continue 结束当前循环,开始下一轮循环default 开关语句中的"其它"分支do 循环语句的循环体double 声明双精度浮点型变量或函数返回值类型else 条件语句否定分支(与 if 连用)enum 声明枚举类型extern 声明变量或函数是在其它文件或本文件的其他位置定义float 声明浮点型变量或函数返回值类型for 一种循环语句goto 无条件跳转语句if 条件语句int 声明整型变量或函数long 声明长整型变量或函数返回值类型register 声明寄存器变量return 子程序返回语句(可以带参数,也可不带参数)short 声明短整型变量或函数signed 声明有符号类型变量或函数sizeof 计算数据类型或变量长度(即所占字节数)static 声明静态变量struct 声明结构体类型switch 用于开关语句typedef 用以给数据类型取别名unsigned 声明无符号类型变量或函数union 声明共用体类型void 声明函数无返回值或无参数,声明无类型指针volatile 说明变量在程序执行中可被隐含地改变while 循环语句的循环条件
C99 新增关键字
_Bool 布尔值 _Complex 复数 _Imaginary 虚数 inline restrict
C11 新增关键字
_Alignas _Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local
  • 基本数据类型及取值范围
C语言学习笔记之基础篇
注: ANSI标准定义int是占2个字节,TC是按ANSI标准的,它的int是占2个字节的。 但是在VC里,一个int是占4个字节的。
  • 类型转换
自动类型转换:如下图
强制类型转换:(数据类型) (表达式)
注: 转换后不会改变原数据的类型及变量值,只在本次运算中临时性转换;
强制转换后的运算结果不遵循四舍五入原则。
C语言学习笔记之基础篇
C语言学习笔记之基础篇
常用的算术转换是隐式地把值强制转换为相同的类型。 编译器首先执行整数提升,如果操作数类型不同,则它们会被转换为上列层次中出现的最高层次的类型; 常用的算术转换不适用于赋值运算符、逻辑运算符 && 和 ||。
C 语言中 printf 输出 double 和 float 都可以用 %f 占位符混用,而 double 还可以用 %lf。
而 scanf 输入情况下 double 必须用 %lf,float 必须用 %f 不能混用。
  • 格式符/占位符
C语言学习笔记之基础篇
sizeof是C语言的内置运算符,以字节为单位给出指定类型的大小。 C99 和C11 提供%zd转换说明匹配 sizeof 的返回类型。 一些不支持 C99和C11 的编译器可用%u或%lu代替%zd。
  • 转义序列
    用于代表难以表示或无法输入的字符。
C语言学习笔记之基础篇
从C90开始,可以用十进制、八进制、十六进制形式表示字符常量
C语言学习笔记之基础篇
  • 运算符及优先级
C语言学习笔记之基础篇
C语言学习笔记之基础篇
注释: https://zh.cppreference.com/w/c/language/operator_precedence#cite_note-1
括号成员是老大; // 括号运算符 []() 成员运算符. ->
全体单目排老二; // 所有的单目运算符比如++、 --、 +(正)、 -(负) 、指针运算*、&
乘除余三,加减四; // 这个"余"是指取余运算即%
移位五,关系六; // 移位运算符:<< >> ,关系:> < >= <= 等
等与不等排行七; // 即 == 和 !=
位与异或和位或; // 这几个都是位运算: 位与(&)异或(^)位或(|)
"三分天下"八九十;
逻辑与,逻辑或; // 逻辑运算符: || 和 &&
十一十二紧挨着;    // 注意顺序: 优先级(||)  低于 优先级(&&)
条件只比赋值高, // 三目运算符优先级排到 13 位只比赋值运算符和 "," 高
逗号运算最低级! //逗号运算符优先级最低
  • 循环
1.在没有循环结构的情况下,break 不能用在单独的 if-else 语句中2.在知道循环次数的情况下更适合使用 for 循环;3.在不知道循环次数的情况下适合使用 while 或者 do-while 循环
4.如果有可能一次都不循环应考虑使用 while 循环;5.如果至少循环一次应考虑使用 do-while 循环
switch语句时还应注意以下几点:1.case后的各常量表达式的值不能相同,否则会出现错误。2.case子句后如果没有break;会一直往后执行一直到遇到break;才会跳出switch语句。3.switch后面的表达式语句只能是整型或者字符类型。4.case后,允许有多个语句,可以不用{}括起来。5.casedefault子句的先后顺序可以变动,而不会影响程序执行结果。6.default子句可以省略不用。
0.自定义函数尽量放在 main 函数之前,若要放在 main 函数后面, 需要在 main 函数之前先声明自定义函数
  • 存储类别
自动(auto静态(static寄存器(register外部(extern
只有局部自动变量和形式参数可以作为寄存器变量;
一个计算机系统中的寄存器数目有限,不能定义任意多个寄存器变量;
局部静态变量不能定义为寄存器变量。
auto 是局部变量的默认存储类, 限定变量只能在函数内部使用;register 代表了寄存器变量,不在内存中使用;static是全局变量的默认存储类,表示变量在程序生命周期内可见;extern 表示全局变量,即对程序内所有文件可见
  • 字符串函数
  • 获取数组长度
    int length = sizeof(arr)/sizeof(arr[0]);
    二维数组定义的时候,可以不指定行的数量,但是必须指定列的数量。

0x02 References

《The C Primer Plus》
C语言入门这一篇就够了-学习笔记
C语言教程

0x03 写在最后

因为基础篇的知识点比较零散,好在断断续续写了几天总算写完了,细心的朋友可以发现我在文中指出了一些 C99 和 C11 的新特性与 C89 和 C90 作为区分,以便在不同的编译器上能够更好的排错。 还有很多知识点没有提到,后期补充时会另写一篇续章。 文中难免有纰漏之处,请读者不吝指出。

0x04 更多精彩




xcbyao's HACK-PWN 欢迎叨扰