公司动态
C语言基础 1.0
目录1. 第一个c语言程序 “Hello World!”1.1. 结构分析1.1.1. main函数1.1.2. 函数返回类型 int1.1.3. 头文件和库函数1.1.4. return 返回关键字1.1.5. 注释2. 一个变量的诞生2.1. 变量常量2.1.1. 常量2.1.1.1. 符号常量2.1.1.2. 整型常量2.1.1.3. 字符常量2.1.1.4. 浮点型常量2.1.2. 变量2.1.2.1. 命名规则2.1.2.2. 局部变量2.1.2.3. 全局变量2.1.2.4. 生命周期作用域2.1.3. 常变量2.2. 常见数据类型2.2.1. 整型 int2.2.2. 浮点型2.2.3. 字符型2.2.4. 布尔型2.3. 类型修饰符2.3.1. short long2.3.2. signed unsigned2.3.3. 占用空间 取值范围1. 第一个c语言程序 “Hello World!”Hello World! 是学习任何编程语言的第一步。现在就让我们从这第一步开始正式进入 C 语言的世界#include stdio.h // 包含头文件 stdio.h //main 函数 int main() { //printf()库函数 printf(Hello World!); //返回0 return 0; }1.1. 结构分析1.1.1. main函数main函数也称主函数是一个程序的入口。一个工程可以有多个.c文件但main函数有且只有一个语法上main函数对位置没有强制要求但工程中必须遵循‘先声明、后使用’的原则不能随意放置。1.1.2.函数返回类型intint为数据类型中的整型int 不但可以修饰变量还可以修饰函数返回值。1.1.3. 头文件和库函数stdio.h是一个头文件,相当于一个清单它为系统列出了很多函数声明函数声明会告诉系统这个函数的存在、返回值类型和参数存放的函数称为库函数使用不同的库函数就要包含其他头文件。printf()是一个库函数功能为向输出设备通常为屏幕输出格式化字符串它可直接打印字符串也可以搭配占位符打印其他数据类型的数据使用它要加上“ #include stdio.h ”包含一个头文件。1.1.4. return 返回关键字return用于函数返回返回值类型为void时可不返回值其他类型必须返回对应类型的值。注意一. 当编写任何一个程序时通常都会在main函数的最后即函数体结尾写上return 0即使不写在运行完main()之后系统也会自动返回0,这是所有c程序员的习惯。二. 当创建一个函数且它的返回值类型不为void时必须返回相应的数值否则将会报错。1.1.5. 注释注释分为单行注释与多行注释。单行注释以//开头直到行末结束。例如// 需要注释内容。多行注释以/*和*/包裹注释内容。例如/* 需要注释内容 */。单行注释//是 C99 标准才引入的在 C89中只支持多行注释/* */。如果你用版本老一点的编译器可能会遇到这个问题。注释的主要功能为解释某一行、某一段代码或某个函数的作用。运行时被注释的内容会被编译器直接忽略跳过。在日常开发中适当地写注释是一个良好的编程习惯但要注意写注释时要简洁直白避免误导他人。插入2. 一个变量的诞生一个变量在诞生时带有数据类型的标记并且可以在定义时赋予一个初始值常量 。#include stdbool.h int main() { //整型 int a 123; //浮点型 float b 1.0f; // 单精度 double c 2.0; // 双精度 //字符型 char ch a; //布尔型 _Bool i false; //用_Bool 可以不包含stdbool.h bool j true; // 但在用 bool 、true 、 false 时要包含 return 0; }2.1. 变量常量2.1.1. 常量生活中我们说常量是因为常量是不可修改的在c语言中常量具体是什么呢// 符号常量 用宏#define来定义 命名通常都为大写 #define A 65 #define PI 3.1415926 #define LEARN Lets go to learn c int main(){ // 这些为整型常量 1; 114514; // 这些为字符常量 a; b; // 这些为浮点型常量 1.0f; 3.1415926; 350.2341145e4 // 也可以用科学计数法表示 // 这为八进制常量以0开头 077; // 转换为10进制为63 7 * 8^1 7 * 8^0 // 这为16进制常量以0x开头 0x1AC // 转换为10进制为25772 (1 * 16^2 10 * 16^1 12 * 16^0 ) return 0; }2.1.1.1. 符号常量符号常量用宏#define来定义命名通常都为大写它本身不分配内存只是在预处理阶段进行文本替换作用域从定义处开始到文件末尾为止。2.1.1.2. 整型常量整型常量通常都是以十进制形式呈现的整数但也可以以八进制、二进制和十六进制的形式呈现。八进制常量通常是以 0 开头 其余每位数的范围为0-7如016十进制为14。十六进制常量通常为以 0x 开头 其余每位数的范围为0-9 , A-F。如0x1AC (十进制为25772)。二进制常量在C23标准才正式加入通常以 0b 或 0B 开头 其余每位数范围为0-1。如0b1010 十进制为10。2.1.1.3. 字符常量字符常量, 一般是字符也可以是范围为0到255的整数数值。当存放这个范围的数值时表示某个字符的ASCll码值如 char ch 65 ch的值为65整数对应ASCll字符 ‘ A ’ 打印 ch 时会输出 A。2.1.1.4. 浮点型常量浮点型常量一般为小数当赋值给float类型的变量时要在常量后加上f如果要赋值给double类型的变量时则不用因为浮点常量默认就是double类型。2.1.2. 变量在创建一个变量时有变量名、数据类型和常量。2.1.2.1.命名规则在给变量取名时我们应该注意些什么一、只能以大小写字母、数字和下划线 _ 组成 如Is_A1_3434_2aa。二、变量名总长不能超过63个字符。C99起三、不能以数字开头如123_IsNum 错。四、区分大小写如int a 与 int A 它们都为int类型的变量但实际为两个不同的变量。五、不能为关键字和宏定义如int 数据类型 int变量名 4 错。#define M 5int M 65 , 错 M为宏不能被赋值修改。这就是为什么宏定义通常全部大写用大小写本身就能有效避免命名冲突。六、取名时最好有实际意义。 如 int count ; 可以让人一眼看出count作用为计数。这里给大家推荐几种变量名的写法1. 驼峰命名法 如: MyVariableNameLearnCLuaggage Java、C、C# 常用。2. 下划线命名法 如 my_variable_nameC语言最主流风格。3. 全大写下划线 如MY_NAME宏定义、枚举常量。2.1.2.2. 局部变量局部变量没被static修饰一般存放在栈区内存中有栈区、堆区和静态区创建在一个函数或循环内只作用于它所在的局部内当程序运行到局部之外这个变量直接销毁。创建局部变量时一定要初始化。如果不初始化变量的值是内存中残留的不确定值俗称垃圾值使用未初始化的局部变量会导致不可预期的错误。2.1.2.3. 全局变量全局变量一般存放到静态区创建在所有函数之外没有大花括号的约束能作用于整个项目只有当整个项目程序运行完才会被销毁。当没有给全局变量初始化时系统将给此变量初始化为0 、 \0 或 NULL。注意当全局变量和局部变量同名时在局部作用域内局部变量优先全局变量被屏蔽例如2.1.2.4. 生命周期作用域生命周期指一个变量从创建分配内存开始到销毁释放内存结束的过程。全局变量生命周期从程序开始运行时创建到程序运行结束时销毁。局部变量生命周期从程序进入其作用域如一个函数或循环的{ } 内时创建到跳出其作用域时销毁。作用域指一个变量可被访问、使用的区域。全局变量作用域覆盖整个工程所有 .c 源文件。局部变量作用域位于其所在的函数或循环{ }内部。例如2.1.3. 常变量常变量指的是被const修饰的变量。虽然它在语法上属于变量但由于其值在初始化后不可修改因此在实际使用中具有常量的特性所以需要与普通变量和常量分开讨论。#include stdio.h int main() { // 这是一个常变量 a初始值为 10 const int a 10; // 尝试给 a 赋值 5系统会报错因为 a 不可修改 a 5; // 错误不能给常量赋值 return 0; }2.2. 常见数据类型了解了变量、常量和常变量接下来我们看看 C 语言提供了哪些数据类型来存放不同种类的数据。2.2.1. 整型 intint 整型用于存放整数 。int main() { //主要存放整数 int a 123; return 0; }2.2.2. 浮点型float单精度浮点型 double双精度浮点型int main(){ //单精度浮点数 float a 1.0f; // 双精度浮点数 double b 1.0; return 0; }这种类型的变量主要存放小数如1.03、5.123也可以是整数如1.0、120.0和极大或极小的数值如1.23e10、123000000。注意当给float类型的变量赋值时要在赋值的数值最后加上 f 或 F如1.0f 、 120.0F ,因为直接赋值 1.0 编译器会将 1.0 认定为double类型使用时可能造成精度丢失所以常量的类型应当与变量的类型匹配避免编译器进行隐式类型转换。2.2.3. 字符型char表⽰字符类型这种类型的变量主要存放字符也可以存放一个整数表示对应的 ASCII 字符,这个整数的范围为-128 ~ 127有符号或0 ~ 255无符号。int main(){ //字符型 char; //这些为char类型的变量 char ch a; char A 65; return 0; }2.2.4. 布尔型C语言在C99正式引入了布尔 _Bool 类型,布尔类型的变量可存放false和true两个值用于条件判断。因为true 、 false 和 bool定义在stdbool.h头文件里所以在创建布尔类型变量之前要引用stdbool.h头文件。注意_Bool是 C99 引入的关键字bool则是在 stdio.h 中用#define定义的宏本质上等价于_Bool。同时这个头文件还把true 定义为 1false定义为 0。#include stdbool.h int main() { // false 为假 bool a false; // true 为真 _Bool b true; // bool 是 _Bool 的宏别名定义在 stdbool.h 中 return 0; }2.3. 类型修饰符在实际开发过程中内存的分配问题尤为重要为了合理利用内存、避免不必要的浪费我们需要掌握各种类型修饰符。2.3.1. short longshort 与 long 为长度修饰符主要用于修饰整型类型的长度内存长度。int main() { // 正常整型 int; // 短整型 short int a 123; // 等价于short // 长整型 long int b 123123L; // 等价于long // 长双精度浮点型 long double c 123123123.0L; // 长长整型 long long int d 123123123; // 等价于long long return 0; }注意short 主要修饰 int ,不能修饰double类型long可修饰 int也可以和double组成long double 类型存放常量后加上后缀L而long long (C99起) 只修饰 int存放常量后加上后缀LL。2.3.2.signed unsignedsigned 和 unsigned 为符号修饰符专门修饰字符型和整型类型用于限定整数变量是否可以表示正负会改变变量所能存储的数值范围其中 signed 表示有符号能表示正负数和0unsigned 表示无符号只能表示正数和0。int main() { // 有符号整型 signed int; // 等价于 int // 无符号整型 unsigned int a 123; // 有符号长、短和长长整型 , signed 和 int 都可省略 signed long int; // 等价于 long signed short int; // 等价于 short signed long long int;// 等价于 long long // 无符号长、短和长长整型 只有 int 可省略 unsigned long; unsigned short; unsigned long long; // 有符号字符型 signed char ch; // 无符号字符型 unsigned char ch2; return 0; }问为什么signed限定int类型时可省略而 char 却不行答因为char的符号性由编译器决定所以不建议省略signed。总结unsigned 不可省略int 默认为 signed int 所以可省略 signed又因为short 、 long 、long long 修饰 int同样为有符号也可省略 signed。2.3.3. 占用空间 取值范围数据类型不同占用的空间字节也不同占用空间的不同会影响取值范围。类型占用大小字节取值范围有符号char1-128 ~ 127int4-2,147,483,648 ~ 2,147,483,647short2-32,768 ~ 32,767long4 (windows) / 8 (Linux)Windows: -2^31~2^31-1Linux: -2^63~2^63-1long long8-9.22×10^18~ 9.22×10^18float4±1.2×10⁻³⁸ ~ ±3.4×10³⁸ 精度约6-7位有效数字double8±2.3×10⁻³⁰⁸ ~ ±1.7×10³⁰⁸ 精度约15-17位有效数字long double8 / 12 / 16 (看平台)范围极大 精度约18-34位有效数字类型取值范围无符号char0 ~ 255int0 ~ 4,294,967,295short0 ~ 65,535longWindows: 0~2^32-1Linux: 0~2^64-1long long0 ~ 1.84×10^19float\double\long double\问为什么 int和float 占用大小一样但取值不同。答int 和 float 采用了完全不同的编码规则所以占用大小一样取值不同。int 可以精确表示每个整数float 不行float 需要覆盖从极小到极大范围的数值这也是导致精度只有约6~7位的原因。此外C语言中提供了一个运算符 sizeof操作符, 可以获取数据类型或变量在内存中所占的空间单位字节。注意sizeof 会返回 size_t 类型的数值无符号整型所以在打印这个值时最好使用专门的%zu格式占位符来格式化。例如#include stdio.h int main() { int a 10; char b a; float c 1.0f; double d 2.0; short e 1; long f 101010L; long long g 10101010LL; long double h 123123123L; // sizeof(类型 或 变量) printf(%zu\n, sizeof(a)); // 输出4 也可以这样sizeof(int) printf(%zu\n, sizeof(b)); // 输出1 printf(%zu\n, sizeof(c)); // 输出4 printf(%zu\n, sizeof(d)); // 输出8 printf(%zu\n, sizeof(e)); // 输出2 printf(%zu\n, sizeof(f)); // 输出4 64位 Windows 环境下 printf(%zu\n, sizeof(g)); // 输出8 printf(%zu\n, sizeof(h)); // 输出8 64位 Windows 环境下 return 0; }