用一句Halle认识C 语言
✨博主介绍
初识 C 语言
特点
通俗了解计算机工作原理
高级计算机语言与编译器
使用 C 语言的 7 个步骤
编程机制
C 语言概述
简单的 C 程序示例及分析
进一步使用 C
多个函数
关键字和保留标识符
数据和 C
示例程序(交互式程序引入)
变量与常量数据
数据
数据类型关键字
C 语言基本数据类型
获取类型大小
字符串和格式化输入输出
示例程序
字符串简介
char 类型数组与 null 字符
常量与 C 预处理器
💫点击直接资料领取💫
✨博主介绍
💂 个人主页:苏州程序大白
💂 个人社区:CSDN全国各地程序猿
🤟作者介绍:中国DBA联盟(ACDU)成员,CSDN全国各地程序猿(媛)聚集地管理员。目前从事工业自动化软件开发工作。擅长C#、Java、机器视觉、底层算法等语言。2019年成立柒月软件工作室,2021年注册苏州凯捷智能科技有限公司
💅 有任何问题欢迎私信,看到会及时回复
👤 微信号:stbsl6,微信公众号:苏州程序大白
💬如果文章对你有帮助,欢迎关注、点赞、收藏(一键三连)
🎯 想加入技术交流群的可以加我好友,群里会分享学习资料
初识 C 语言
章节概要:C 语言的特点、计算机工作原理、高级计算机语言、编译器、编程步骤、C 编程机制
特点
设计特性
C 语言融合了计算机科学理论和实践的控制特性
C 语言的设计理念让用户轻松完成自顶向下的规划、结构化编程和模块化设计
高效性
C 语言充分利用计算机的优势,因此程序更紧凑,运行速度很快
C 语言具有通常汇编语言才具有的微调控制能力,可以更具具体情况微调程序以获得最大运行速度或最有效地使用内存
可移植性
C 是可移植的语言,这意味着,在一种系统中编写的 C 程序稍作修改或不修改就能在其他系统上运行
注意程序中针对特殊硬件设备(如显示监视器)或操作系统特殊功能编写的部分通常不可移植
C 语言与 UNIX 关系密切,UNIX 系统通常会将 C 编译器作为软件包的一部分
供个人计算机使用的 C 编译器很多,因此在各个版本的操作系统上,都可以找到合适的 C 编译器
强大而灵活
C 语言功能强大而灵活
UNIX 操作系统、其他语言(FORTRAN、Perl、Python、Pascal)等的编译器和解释器都是用 C 语言编写的
面向程序员
C 语言是为了满足程序员的需求而设计的,程序员可以利用 C 访问硬件、操控内存中的位
大多数 C 实现都有一个大型的库,包含众多有用的 C 函数,可以让程序员更加方便地使用 C 语言
通俗了解计算机工作原理
简而言之,计算机的工作原理是:如果希望计算机做某些事,就必须为其提供特殊的指令列表(程序),确切地告诉计算机要做的事以及如何做。你必须用计算机能直接明白的语言(机器语言)创建程序。这是一项繁杂、乏味、费力的任务
高级计算机语言与编译器
高级编程语言(如 C 语言)以多种方式简化了编程工作。首先,不必用数字码表示指令;其次,使用的指令更贴近你如何想这个问题,而不是类似计算机那样繁琐的步骤
编译器是把高级语言程序翻译成计算机能理解的机器语言指令集的程序,在计算机看来,高级语言指令就是一堆无法理解的无用数据。由此,程序员进行高级思维活动,而编译器则负责处理冗长乏味的细节工作
使用 C 语言的 7 个步骤
C 是
编译型语言,我们把编写 C 语言的程序分解为七个步骤:
1、定义程序的目标
2、设计程序
3、编写代码
4、编译
5、运行程序
6、测试与调试程序
7、维护和修改代码
编程机制
用 C 语言编写程序时,编写的内容被储存在文本文件中,该文件被称为源代码文件(source code file)。大部分 C 系统,都要求文件名以.c结尾
C 编程的基本策略是,用程序把源代码文件转换成可执行文件(其中包含可直接运行的机器语言代码)
典型的 C 实现通过编译和链接两个步骤来完成这一过程。编译器把源代码转换成中间代码,连接器把中间代码和其他代码合并,生成可执行文件
C 语言概述
章节概要:C 语言程序简单示例、#include与头文件、主函数main、注释、花括号、声明与变量、赋值、printf函数、return语句、C 语言程序基础结构、多条声明、打印多个值、多个函数、关键字和保留标识符
简单的 C 程序示例及分析
#include <stdio.h> int main(void) //一个简单的C程序 { int num; //定义一个名为num的变量 num = 1; //为num赋一个值 printf("I am a simple "); //使用printf函数 printf("computer.\n"); printf("my favourite number is %d because it is fitst.\n", num); return 0; }
程序分析及知识概要
#include
指令和
头文件
1、#include 在程序的第一行,该语句作用相当于把stdio.h文件中的所有内容都输入该行所在位置,本质上是一种“拷贝-粘贴”的操作。include文件提供了一种方便的途径共享许多程序共有的信息
2、#include这行代码是一条 C预处理器命令,通常,C 编译器在编译前会对源码做一些准备工作,即预处理
3、所有的 C 编译器软件都提供stdio.h头文件,该文件包含供编译器使用的IO 函数(I:input 输入,O:output 输出)。该文件名含义为标准输入/输出头文件。通常,C 程序顶部的信息集合被称为头文件
main()
函数
1、main()函数是程序的主函数,它是程序的入口点,从这里开始执行
2、int main()中int是函数的返回类型,表明函数返回操作系统的是整数,此处将在后续探讨
3、如果浏览旧式的 C 代码,会发现程序如main()开始,C90 标准勉强接受这种形式,但 C99 和 C11 标准不允许,因此不要这样写
4、你还会看到void main()的形式,部分编译器允许这样写,但所有标准都未认可,因此也不要这样写
注释
1、注释是一种记录程序信息的方式,被注释的部分不会被程序运行
2、可以使用/*注释内容*/进行注释,此类注释可以换行注释,直到*/为止
3、也可以使用//进行注释(C99 新加入),此类注释不能换行,直到行尾为止
花括号
1、程序中花括号{}把main()括起来,一般而言,所有的C 函数都使用花括号标记函数体的开始和结束
2、花括号还可用于把函数中多条语句合并为一个单元和块
声明与变量
1、int num;这行代码叫做声明,声明是 C 语言中最重要的特性之一
2、该条例中,声明完成了两件事。其一,函数中有一个名为num的变量,其二,int表示num的数据类型是一个整数
3、int是 C 语言中的一个关键字,表示一种基本的 C 语言数据类型。关键字是语言定义的单词,不能用做其他用途,例如不可作为函数名或变量名
4、num是一个标识符,也就是一个变量、函数或其他实体的名称
5、把变量声明正确的为数据类型(整型、浮点型、字符等),计算机才能正确的存储、读取和解释数据
6、变量的命名,要尽可能使用有意义的变量名或标识符,如程序需要一个变量属羊,则可起名sheep_count。变量命名时仅可以使用大小写字母、数字和下划线,且第一个字母不能是数字
赋值
1、num = 1是赋值表达式语句,赋值是 C 语言的基本操作之一,意为“把值 1 赋给变量num”
2、在执行int num声明时,编译器在计算机内存中为变量num预留了空间,然后执行赋值表达式语句时,把值存储在预留的位置
3、注意,赋值表达式语句从右侧把值赋给左侧,另外,该语句以分号;结尾
printf
函数
1、printf是 C 语言的一个标准函数,圆括号()表明printf是一个函数名,圆括号中的内容是从main()函数传递给printf函数的信息
2、printf函数会查看双引号中的内容(字符串),并将其打印到屏幕上
3、\n的作用是换行,\n组合代表一个换行符。换行符是一个转义列表,用于代表难以表示或无法输入的字符。如\t代表Tab 键,\b代表Backspace 键,每个转义序列都以反斜杠\开始
4、对比发现,参数中的%d被数字 1代替了,而 1 就是num的值。%d是一个占位符,其作用是指明输入num的位置
return
语句
1、int main(void)中的int表明函数main要返回一个整数,C 标准要求main()这样做。
2、有返回值的 C 函数要有return语句,该语句以return关键字开始,后面是待返回的值,并以分号;结尾
3、如果遗漏main函数末尾的return语句,程序在运行至最外面的}时,会自动返回一个默认值,即 0。因此此处可以省略,但在其他有返回值的函数中不可省略,所以建议保留此习惯
简单程序的结构
程序由一个或多个函数组成,必须有main()函数。
函数由函数头和函数体组成,函数头包括函数名、传入该函数的信息类型和函数的返回值类型
通过函数名后的圆括号可以识别出函数,圆括号里可能为空,可能有参数
函数体被花括号括起来,由一系列语句、声明组成
简言之,一个简单的 C 语言程序格式如下(大部分语句都以分号;结尾):
#include <stdio.h> int main(void) { //语句 return 0; }
进一步使用 C
//把2英寻转换成英尺 #include <stdio.h> int main(void) { int feet, fathoms; fathoms = 2; feet = 6 * fathoms; printf("There are %d feet in %d fathoms!\n", feet, fathoms); printf("Yes,I said %d feet!\n", 6 * fathoms); return 0; }
程序分析及知识概要
多条声明
1、int feet, fathoms;语句,使用多条声明声明了两个变量,使用逗号,隔开,此语句与int feet;+int fathoms;等价
打印多个值
1、程序的第一个printf()进行了两次替换,按顺序将feet、fathoms替换了两个%d
2、第二个printf()说明待打印的值不一定是变量,只要可求值得出合适类型值的项即可
多个函数
把自己的函数添加到程序中,此处只做简单了解,后续学习:
#include <stdio.h> void def(void) { printf("hello world!"); } int main(void) { def(); return 0; }
关键字和保留标识符
下表中粗体表示C90标准新增关键字,斜体表示C99标准新增关键字,粗斜体 表示C11标准新增关键字
数据和 C
章节概要:交互式程序、变量与常量数据、数据、数据类型关键字、C 语言基本数据类型、进制打印显示(int 类型中)、可移植类型、使用程序获得数据类型大小
示例程序(交互式程序引入)
#include <stdio.h> int main(void) { float weight; float value; printf("Please enter your weight in pounds:"); scanf("%f", &weight); value = 1700.0 * weight * 14.5833; printf("your weight in platinum is worth $%.2f.\n", value); return 0; }
新元素简单分析
新的变量声明,使用float浮点数类型,浮点类型可以储存带小数的数字,详细说明见本章后面部分
为了打印新类型的变量(浮点数),printf处使用%f处理浮点值了
%.2f用于精确控制输出,指定保留小数后两位
scanf()函数用于读取键盘的输入,%f说明scanf()读取输入浮点数,&weight告诉scanf()把输入的值赋给名为weight的变量
scanf()函数使用&符号表明找到weight变量的地点,下章将详细讨论,目前请按照这样写
变量与常量数据
变量:有些数据类型在程序运行期间可能会改变或被赋值,这些称为变量
常量:有些数据类型在程序使用之前已经预先设定好了,整个程序运行过程中没有变化,称为常量
数据
位、字节、字
位、字节、字是描述计算机数据单元或存储单元的术语,这里主要指储存单元
位(bit):最小的储存单元。可以储存0 或 1,是计算机内存的基本构成块
字节(byte):常用的计算机存储单位,字节是位的集合,一个字节可以储存8 位。这是字节的标准定义,至少在衡量存储单位时是这样
字(word):是设计计算机时给定的自然存储单位,对于 8 位的微型计算机,一个字长只有 8 位。从那以后,个人计算机字节增至 16 位、32 位,直至目前的 64 位。计算机的字长越大,数据转移越快,允许的内存访问也更多
整数
和数学概念一样,整数是没有小数部分的数,例如 2、-23、2456 都是整数
计算机以二进制数字存储整数,如整数 7 二进制写为 111,因此要在8 位字节中存储该数字,需要前 5 位设置为0,后 3 位设置为1
浮点数
与数学中实数概念差不多,例如 2.75、3.16E7、7.00、2e-8 都是浮点数
注意,在一个值后面加上小数点,该值就成为一个浮点数,所以7 是整数,7.00 是浮点数
此处简要介绍e 计数法(科学计数法):3.16E7表示3.16 * 10^7
这里关键要理解浮点数与整数的储存方案不同,计算机把浮点数分成小数部分和指数部分表示,而且分开存储这两部分。7.0写成0.7E1,这里,0.7 是小数部分,1 是指数部分。计算机在内部使用二进制和2 的幂进行储存,后续探讨(此处图例以十进制下理解为例)
数据类型关键字
C 语言基本数据类型
int类型
1、C 语言中的整数类型可表示不同的取值范围和正负值,一般情况下使用int能应付绝大多数情况
2、int类型是有符号整型,即int的值必须是整数,可以是正整数、负整数、0
3、int类型的取值范围因计算机系统而异,一般而言,储存一个int要占用一个机器字长
4、早期16 位的取值范围为-2^15 ~ 2^15-1,即-32768 ~ 32767,ISO C 规定int最小范围为-32768 ~ 32767
5、一般来说,系统会用一个特殊位的值(未使用的第 16 位)表示有符号整数的正负号
6、使用%d打印整数类型,%d称为转换说明,他指定应该用什么格式显示一个值
7、显示不同进制:使用%d显示十进制,%o显示八进制,%x显示十六进制。显示前缀使用%#o、%#x、%#X
#include <stdio.h> int main(void) { int x = 100; printf("dec=%d ; octal=%o ; hex=%x \n", x, x, x); printf("dec=%#o ; octal=%#x ; hex=%#X", x, x, x); return 0; }
其他整数类型
1、short类型:占用空间可能比int少,有符号类型
2、long类型:占用空间可能比int多,有符号类型
3、long long类型(C99 加入):占用空间可能比long多,至少 64 位,有符号类型
4、unsigned类型:非负整型,16 位取值范围0 ~ 2^16-1,即0 ~ 65535
5、C90 后,新增unsigned short、unsigned long;C99 后,新增unsigned long long
6、在任何有符号类型前添加关键字signed,可强调使用有符号类型的意图
7、空间“可能”多与少是因为 C只规定了short不能多于int,long不能少于int
8、现在个人计算机常见设置是,long long占64 位,long占32 位,int占16 位或32 位,short占16 位
9、打印时,使用%u打印unsigned类型,使用%ld打印long类型,使用%lld打印long long类型,使用%hd打印short类型
浮点数类型
1、浮点类型能表示包括小数在内更大范围的数,浮点数的表示类似科学计数法。在计算机中,科学计数法中的 10 的指数,跟写在字母e后面,如1.02 * 10^3记作1.02e3
2、单精度浮点数float,C 语言规定其至少能表示6 位有效数字,且取值范围至少是10^-37 ~ 10^37。通常,系统储存一个浮点数要占用 32 位,其中 8 位用于表示指数的值和符号,剩下 24 位用于表示非指数部分及其符号
3、双精度浮点数double,其与float类型的最小取值范围相同,但必须至少能表示10 位有效数字,一般来说,double占用 64 位而非 32 位。一些系统将多出来的 32 位全用来表示非指数部分,不仅增加有效数字位数(即精度),还减少了舍入误差;另一些系统把其中一些位分配给指数部分,以容纳更大的指数,增加可表示数的范围。无论哪种类型,double类型的值至少有 13 位有效数字
4、long double,可以满足比double更高的精度要求,不过,C 只保证long double类型至少与double类型的精度相同
5、浮点数后面加上f或F后缀可覆盖默认设置,编译器会将浮点型常量看做float类型,如2.3f,9.11E9F;使用l或L后缀使数字成为long double类型;没有后缀的浮点型常量是double类型
6、打印浮点值时,使用%f打印float类型,用%e打印指数计数法的浮点值,如果系统支持十六进制的浮点数,使用%a打印十六进制的浮点值,打印double或long double要使用%Lf、%Le和%La的转换说明
char字符类型
1、char类型用来储存字符,如字母或标点符号
2、从技术层面来看,char是整数类型,因为char类型实际储存的是整数而不是字符。计算机使用数字编码来处理字符,即用特定整数代表特定字符
3、C 常用编码为ASCII编码,其中如整数 65代表大写字母 A,整数 97代表小写字母 a,整数 48代表数字 0
4、标准ASCII 码范围为0~127,只需 7 位二进制数即可表示。通常,char被定义为8 位的存储单元
5、C 语言把1 字节定义为char类型占用的位(bit)数
6、char赋值时,需要传入char 字符类型的数据,即单引号''包裹的字符,如char set = 'A'。此外也可使用ASCII 码进行赋值,如char set = 65
7、有一些代表行为的非打印字符,如换行、退格、回车、蜂鸣等,这些字符打印不出来。如需要表示这些字符,可以使用ASCII 码,比如蜂鸣:char beep = 7。此外也可以使用转义字符,如char beep = '\a'
8、使用%c打印char类型字符,如果使用%d打印,则会打印字符对应 ACSII 码的整数
_Bool布尔类型
1、C99标准新增了_Bool类型,用于表示布尔值,即逻辑值true和false
2、因为 C 语言用值 1表示true,值 0表示false,所以_Bool类型实质上也是一种整数类型
3、原则上它仅占用1 位存储空间,因为对与0 和 1而言,一位的存储空间足够了
可移植类型:stdint.h和inttypes.h
1、C99新增两个头文件stdint.h和inttypes.h,以确保 C 语言各类型在各系统中功能正常
2、C 语言为现有类型创建了更多类型名,这些新类型名被定义在stdint.h中
3、如在精确宽度整数类型中,int32_t表示 32 位的有符号整数类型。在使用32 位系统时,头文件会把int32_t当做int的别名;而在int为16 位,long为32 位的系统中,系统会把int32_t当做long的别名。然后,使用int32_t类型编写程序并包含stdint.h头文件时,编译器会把int或long替换成与当前系统匹配的类型
4、如果系统不支持精确宽度整数类型,可以使用最小宽度类型,例如int_least8_t是可容纳 8 位有符号整数值的类型中宽度最小的类型的一个别名
5、如果更关心速度而非空间,则可使用最快最小宽度类型,如int_fast8_t被定义为系统中对8 位有符号值而言运算最快的整数类型
6、如果需要最大整数类型,最大的有符号整数类型intmax_t可储存任何有效的有符号整数值。类似的,uintmax_t表示最大的无符号整数类型,这种类型可能比long long和unsigned long long更大
7、C 标准针对这种输入和输出,提供了一些字符串宏来显示可移植类型,例如inttypes.h中定义了PRId32字符串宏,代表打印32 位有符号值的合适转换说明(如 d 或 l)
#include <stdio.h> #include <inttypes.h> int main(void) { int32_t me32; me32 = 45933945; printf("me32 = %" PRId32 "\n", me32); return 0; }
复数和虚数
1、许多科学和工程计算都要用到复数和虚数,C99支持复数和虚数,但是有所保留
2、复数类型:有float_Complex、double_Complex和long double_Complex。例如float_Complex变量应包含两个float类型的值,分别表示复数的实部和虚部
3、虚数类型:有float_Imaginary、double_Imaginary和long double_Imaginary
4、如果包含complex.h头文件,便可用complex代替_Complex,用imaginary代替_Imaginary,还可以用 1 代替-1 的平方根
其他类型
1、C 语言中没有字符串类型,却也能很好的处理字符串,详见后续
2、C 语言还有一些基本类型衍生的其他类型,如数组、指针、结构、联合,详见后续
3、本章程序案例简单使用到了指针,如scanf()函数用到的&前缀,便创建了一个指针,告诉scanf()把数据放在何处
获取类型大小
可以使用sizeof()获取以字节为单位的类型大小,C99和C11提供%zd匹配sizeof()返回值,其余不支持的编译器可用%u或%lu代替
#include <stdio.h> int main(void) { printf("Type int has a size of %zd bytes.\n", sizeof(int)); printf("Type char has a size of %zd bytes.\n", sizeof(char)); printf("Type float has a size of %zd bytes.\n", sizeof(float)); return 0; }
字符串和格式化输入输出
章节概要:字符串简介、char 类型数组与 null 字符、strlen()函数、常量与 C 预处理器、明示常量、printf()函数
示例程序
#include <stdio.h> #include <string.h> #define DENSITY 62.4 // 定义人体密度 int main(void) { float weight, volume; int size, letters; char name[40]; printf("Hi! What's your first name?\n"); scanf("%s", name); printf("%s,whats's your weight in pounds?\n", name); scanf("%f", &weight); size = sizeof(name); letters = strlen(name); volume = weight / DENSITY; printf("well, %s, your volume is %2.2f cubic feet\n", name, volume); printf("Also, your first name has %d letters,\n", letters); printf("and we have %d bytes to store it.\n", size); return 0; }
新元素简单分析
用数组储存字符串。在该程序中,用户输入的名被储存在数组中,该数组占用内存中40 个连续的字节,每个字节储存一个字符值
使用%s转换说明来处理字符串的输入和输出。注意,在scanf中,name没有&前缀,而weight有(稍后解释,&weight和name都是地址)
用 C预处理器把字符常量DENSITY定义为 62.4
用 C 函数strlen()获取字符串的长度
字符串简介
字符串是一个或多个字符的序列,如"I came from America"
双引号"不是字符串的一部分,仅是告知编译器它括起来的是字符串,就如单引号'用于标识单个字符一样
char 类型数组与 null 字符
C 语言没有专门用于存储字符串的变量类型,字符都被储存在char类型数组中。数组由连续的存储单元组成,字符串的字符被储存在相邻的存储单元中,每个单元储存一个字符
数组末尾位置有一个空字符(\0),C 语言用空字符(null)标记字符串结束。这意味着数组容量必须比存储字符数多 1
数组是同类型数据元素的有序序列,方括号[]表示这是一个数组
使用%s来转换打印一个字符串
字符串与字符char不是同一种类型,因为字符串最后有空字符标识,而char只存储该字符
使用strlen()函数可以得到字符串的字符长度,且strlen()并不会计入空字符
常量与 C 预处理器
为什么要使用常量
使用常量名比数字表达的信息更多,如area = PI * d与area = 3.14 * d相比更加直观
对于程序中多次使用同一个常量时,如果常量的值需要修改,只需要修改常量值即可
如何创建符号常量
可以定义变量,将其值定义为所需的值,但这样程序可能会无意间改变它的值
使用
C 预处理器
定义,格式为
#define 常量名 值
,
编译程序时
,所有的
常量名
都会
被替换
为它们的值
定义常量时,习惯上建议全用大写,以此告知他人这是一个常量,提高程序可读性;此外也有小众习惯使用c_变量名或k_变量名表示常量
注意:define常量名后的内容用于替换符号常量,不要将#define NUM 20写成#define NUM = 20,这样定义的WORD值为=20而非20
C90标准新增限定词const,表示只读,也可用此作为常量使用(其只表明只读变量),如const float PI=3.14
明示常量
C 头文件
limits.h
与
float.h
分别提供与
整数与浮点数
类型
大小限制
相关的说明,如
limits.h
中有类似以下代码:
#define INT_MAX +32767 #define INT_MIN -32768
这些明示常量代表int类型可表示的最大值和最小值,该头文件会为这些明示常量提供不同的值,如果系统使用32 位的 int且程序包含limits.h头文件,则可以使用printf()与%d转换输出该常量 32 位 int 的值
如果系统使用4 字节的 int,该头文件将提供符合 4 字节的对应值
下为limits.h中的一些明示常量:
相似的,float.h头文件下也有一些明示常量:
limits.h
与
float.h
分别提供与
整数与浮点数
类型
大小限制
相关的说明,如
limits.h
中有类似以下代码:
#define INT_MAX +32767 #define INT_MIN -32768
这些明示常量代表int类型可表示的最大值和最小值,该头文件会为这些明示常量提供不同的值,如果系统使用32 位的 int且程序包含limits.h头文件,则可以使用printf()与%d转换输出该常量 32 位 int 的值
如果系统使用4 字节的 int,该头文件将提供符合 4 字节的对应值
下为limits.h中的一些明示常量:
[外链图片转存中…(img-JqEyomEq-1653357330355)]
相似的,float.h头文件下也有一些明示常量: