C Programming Basics: Types, Control Flow, Arrays, and Pointers
概览
从这里我们开始最基础的编程语言的学习 C语言作为较为基础的语言没有复杂的面向对象工作并且具有尽可能简单的语法规则 所以从这里开始是个不错的注意
C语言的起源
C语言是为编程人员开发设计的语言 他基于B语言 目前是非常重要的语言之一 理解C语言能够更加深刻的理解计算机底层运行的逻辑
使用C语言的理由
控制特性
这种设计使得用户可以自上而下的规划整体的结构
高效性
由于更加接近底层 C语言有着汇编语言才具有的精细控制能力 此时我们可以让程序有更高的运行效率
可移植性
不香汇编语言和处理器关系密切 C语言可以非常轻易在各个系统之间进行迁移 只有拥有编译器就可以了
灵活性
非常多的操作系统和编译器用C语言编写 了解C语言可以了解很多语言的底层逻辑
面向编程人员
C语言允许我们访问硬件 操作内存 如此高的自由度是编程人员所需要的
其他程序设计语言的基础
在C语言中我们将会学习编程的基本思维和逻辑 用一个简单语言作为开头是有意义的
缺点
过高的灵活性自然需要承担更大的风险 更高的操作效率意味着非常多细致的修改 缺点和优点其实来自同一个地方
发展方向
C++是C语言的后续发展方向 他为C语言添加了模块化编程所需要的面向对象操作 实际上几乎所有C程序都可以看做一个C++程序 C语言的诸多优点让他经常用于嵌入式编程 微处理器编程 科学编程 操作系统开发 等等 学习C语言对以后很多方向学习都有意义
计算机的基本工作原理
在计算机组成原理中 我们已经对计算机的工作原理给出了重要解释 这里我们只用一句说了无数次的话来收尾 现在是高级语言的时代了 汇编语言已经渐渐的失去了市场
C语言的使用
- 设定程序目标
- 设计程序
- 编写代码
- 编译
- 运行
- 测试与调试
- 维护和修改 在编译过程中 我们经历了高级语言向汇编语言的编译和汇编语言向机器语言的汇编 最后让我们的高级语言程变为了硬件能够理解的机器语言
编程机制
这里继续详细的介绍一下前面的一些重要过程 在完成设计好的C代码之后(.c结尾的文件) 编译器首先把我们的目标代码经过编译和汇编转化为目标代码文件 然后向他添加启动代码 这是程序和操作系统之间的接口 再添加我们使用的C库中的代码 把三者链接在一起 就形成我们需要的可执行文件 在目前的开发环境下 编译和链接这两个过程编译器都可以直接代劳 我们一般不需要处理
几种开发环境下的编译
Unix
1 | cc inform.c //编译指令 |
Linux
1 | gcc inform.c //编译指令 |
其他的集成开发环境
我们不需要在命令行界面中操作了 此时编译位置取决于IDE的设计
语言标准
ANSI C 或者 C90
比较基本的C语言标准 他有一些基本的指导原则
- 相信程序设计人员
- 不要妨碍程序员要做的事情
- 让语言保持短小
- 只提供一个方法来完成一个操作
- 牺牲可移植性来提高效率 这其实就是C语言的一些精神的体现
C99
只是进行了一些小的改变
- 支持国际化编程
- 修正和改进他的计算实用性 实际上C99 保持了原本的设计思路 后面会在需要的时候阐述发生的改变 我们会发现C99的改变保持了C语言的特性并且更加好用了
C语言概述
从这里开始简单的介绍C语言的语法规则了 前面的一章仅仅是对我们将要学习的内容的一个概览
简单的例子
1 |
|
变量的命名
我们应该使用具有意义的变量和函数的名字 并且不使用C语言已经使用的标识符 类比 Python基础:一些变量命名规则
调试与修改
debug是程序设计永远无法避免的问题 代码一旦复杂 人肯定会出现问题
错误的分类
- 语法错误 编译器可以帮你分析
- 语义错误 只能靠人自己来
一些DEBUG手法
- 脑内编译
- 使用调试器
- 添加一些输出语句来调试
C语言关键词和语句
不要使用程序设计语言已经有的关键词 这会导致很大的问题 保留的语言标识符 比如那些下划线开头的名字已经已经被使用的函数名 也不可以使用 我们在为函数 和 变量等东西起名字的时候不能忘记他
C90
- auto:声明自动变量;
- break:跳出当前循环;
- case:开关语句分支;
- char:声明字符型变量或函数返回值类型;
- 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:循环语句的循环条件;
- asm:用于在C语言中嵌入汇编指令;
- fortran:为Fortran语言链接而设定的条件性支持类型指令符;
C99
- inline:用来定义一个类的内联函数,引入它的主要原因是用它代替C中表达式形式的宏定义;
- restrict:只可以用于限定和约束指针,并表明指针是访问一个数据对象的唯一且初始的方式。即所有修改该指针指向内存中内容的操作都必须通过该指针来修改,而不能通过其它途径(其它变量或指针)来修改,这样做的好处是,能帮助编译器进行更好的优化代码,生成更有效率的汇编代码;
- _Bool:布尔类型的数据,其值为0或1,主要用来判断条件能否成立的真假;
- _Complex:用来表示复数类型;
- _Imaginary:用来表示虚数类型;
- _Pragma:与#pragma指令相同的功能;
C11
- _Alignas:指定某个变量按照其他数据类型对齐;
- _Alignof:指定数据类型内存对齐的字节数;
- _Atomic:原子类型说明符和限定符;
- _Static_assert:声明在编译时有效,它将测试由用户指定且可以转换为布尔值的整数表达式表示的软件断言。如果表达式的计算结果为零(false),编译器将发出用户指定的消息,并且编译因错误而失败;
- _Noreturn:表明调用完成后的函数不返回主调函数,目的是告诉用户和编译器,这个特殊的函数不会把控制返回主调程序,告诉用于以免滥用该函数,通知编译器可以优化一些代码。
- _Thread_local:它会影响变量的存储周期,被修饰的变量具有线程周期,这些变量在线程开始的时候被生成,在线程结束的时候被销毁。并且每一个线程都拥有一个独立的变量实例。可以和static和extern关键字联合使用,这将影响变量的链接属性;
- _Generic:可以简单地将一组具有不同类型却有相同功能的函数抽象为一个统一的接口; 控制语句已经添加在关键词里面了 至于运算符 我们在后面再谈
数据和C
在这一章我们将要介绍更多的关于C语言的基本知识 非常的简单
简单的示例
1 |
|
各种数据类型我们在关键字一处已经给出了介绍 C语言关键词和语句 使用这么多中数字类型就是为了在需要的时候节约存储空间 如果赋值的数字超过了类型允许的范围 则会出现问题 关于各种数据类型的二进制存储我们在别的地方会给出详细的解释
其他进位制度的数字
八进制数据的标识符是 %o 十六进制数字对应了 %x 和 %X 如果我们愿意在 说明符中添加 # 就可以实现数字前显示进位制度
字符
打印字符
我们使用 char 作为字符的标识 一般我们只会在C语言中使用ASCII编码 Unicode编码可以显示更多的语言 不过放在C里面意义可能并没有那么大
1 | char a = 'x'; |
这是基本的声明方式
非打印字符
| 转义序列 | 含义 |
|---|---|
| \a | 警报 |
| \b | 退格 |
| \f | 换页 |
| \n | 换行 |
| \t | 水平制表符 |
| \v | 垂直制表符 |
| \ | 反斜杠 |
| ‘ | 单引号 |
| ‘’ | 双引号 |
| ? | 问号 |
| \0oo | 八进制 |
| \xhh | 十六进制 |
| \r | 回车 |
使用数据类型
错误的转化数据的类型在C语言中是非常宽容的 但是依然要小心 正式这种宽容让C语言更容易出错误 printf 和scanf 是两个特殊的函数 他们对参数的数量没有任何的限制 所有更要仔细注意这里面可能的错误 因为编译器大几率不会给出明确的提示(C语言有对函数参数数量和类型的检验 但是对这种特殊的函数无法发挥作用) 因此 保证格式说明符的个数和后面参数的数目相同并且类型一致是重要的 printf 和 scanf 这种交互语句都基于缓冲区设计 也就是buffer 机制 如果缓冲区没有刷新 printf语句的结构不会显示在界面上 诸如scanf 和 \n 都会让缓冲区刷新
字符串的格式化输入和输出
前面我们介绍了 整数 浮点数 字符 等数据类型 这里我们来介绍C语言中的字符串 也是非常容易得
简单的示例
1 |
|
这里我们注意到了一点 字符数组就是指针格式被表达了 前面使用C宏进行了 define 引入了几个字符串相关的函数
字符串
我们使用双引号标识他是个字符串 就和单引号标识字符一样 字符数组也就是字符串用 \0 结尾 是一个非打印字符 用来标志结尾 其中%s 是我们给出的用来表示字符串的量 这意味着字符和只有一个字符的字符数组是不一样的 要知道 scanf 对空格 制表符 换行符作为结尾标识 所以他不是读取一句话的好方法 sizeof 给出占用的字节数 其实也可以用来判断长度 只是需要程序设计人员多考虑一点 strlen 这种单独设计的函数显然是个更好的选择
常量和预处理器
前面提到的define宏就是一个进行常量确定的很好方法 后面我们会介绍别的方法 凡是使用# 的预处理指令都不是被编译器执行的 而是要进行预处理 一般预处理干的事情都是非常轻松的 他只会进行一些死板的替换
1 | const int A = 100; |
这是是定义常量的很好方法 此时如果我们修改A会报错的
输入与输出指令
printf其实已经很熟悉了 核心点就是 格式占位符号和变量名两点 其中的f 意思是格式化 他可以实现变量输入输出格式的修正 这点我们在需要的时候查阅就可以 printf 其实是有返回值的 返回的是打印变量的个数 scanf和他原理是基本一致的 他也会按照指定的格式进行输入 理解这两个指令只需要理解格式化就可以了 本质上就是一种二进制的转换规则 格式化中的格式转换有时候是C语言复杂的核心 我们需要仔细考虑变量格式的变化 尤其是有些地方出现格式的自动转换 尽管我们认为自动转换往往是提升进行 不会损失信息 他也有返回值 如果读取失败 返回0 如果读取到文件结尾 返回 EOF 常量
运算符 表达式 语句
这里我们来介绍一些运算的符号 其实原理是容易理解的 同时的 我们介绍一些前面没提到过的语句
while循环
使用方法如下
1 | while(a<b){ |
实现的作用也非常简单 在某个条件下 重复的执行某些语句 正是因为我们需要判断条件是否成立和执行某些语句 运算符才有了意义
基本运算符
赋值
1 | a=b; |
赋值符号右边的指给到左边的可修改变量 我们要求左值一定可修改 否则不可以赋值
一些其他的基础算符
1 | a+b; |
运算符是有优先级 我们只需要知道他和数学一样 如果有记不清的地方 不妨加括号来实现 运算符不是炫技 我们要让代码可读才是核心
关系运算符
1 | <; |
表达式和语句
表达式时运算符和操作数的整体 语句是由表达式和一些语法符号构成的 他们是程序构成的关键 复合语句 也就是多个语句被包含在一个花括号内 被称为代码块
循环
在这里完整的介绍循环的形成 以及一些使用方法
再谈while循环
while 是入口条件循环:先判断条件,条件为真时执行循环体,循环体内部通常要更新与条件相关的变量。
1 | while (a < b) { |
1 | status = scanf("%d",&num); |
计数循环
for循环
对于不同类型的循环 当然我们有更好的写法
1 | for(count=1;count<=max;count++){ |
逗号运算符
1 | for(count=1,cost=1;count<=max;count++){ |
退出条件循环 do while
1 | do{ |
嵌套循环
1 | for(i=0;i<10;i++){ |
循环辅助手段
1 | for(i=0;i<10;i++){ |
数组
数组是用来存储类型相同的一些相关新的的
1 | int array[10]; |
使用函数的返回值
1 | double power(double n,int p){ |
分支和跳转
除了分支和跳转的内容 我们这里也会介绍一些IO函数和他们的使用
if语句
1 | while(scanf("%f") == 1){ |
goto 语句
在这里提示 如果不是必要 不要使用 也就是我们要绝对谨慎的使用 在更高级的语言中 不再存在这个写法 这正是因为他不必要还容易引发错误
1 | #这个语句需要搭配使用 |
字符的输入 输出 确认
- Title: C Programming Basics: Types, Control Flow, Arrays, and Pointers
- Author: Hyacehila
- Created at : 2023-03-23 15:35:43
- Link: https://hyacehila.github.io//blog/2023/03/23/c-programming-basics-learning-notes/
- License: This work is licensed under CC BY-NC-SA 4.0.