第二讲:C语言数据类型和变量

📅 2026/7/24 22:09:39
第二讲:C语言数据类型和变量
目录一、数据类型介绍1. 什么是数据类型2. 常见的数据类型分类2.1 内置数据类型2.2 自定义数据类型二、变量1. 变量的创建与命名规则1.1 变量的创建声明与初始化1.2 变量的命名规则2. 变量的作用域全局变量与局部变量2.1 全局变量2.2 局部变量2.3全局变量和局部变量在内存中存储的位置2.4 对比与注意事项三、算数操作符1. 加法与减法操作符 和 -2. 乘法与除法操作符* 和 /3. 取模操作符%4. 算术操作符的优先级与结合性四、 赋值操作符和复合赋值1. 连续赋值2. 复合赋值五、单目操作符 、-- 、 、-1. 和--2. 和 -六、强制类型转换七、scanf 和 printf 的介绍1. printf 函数格式化输出1.1 基本用法1.2 占位符1.3 占位符举例1.4 输出格式1.4.1 限定宽度1.4.2 总是显示正负号1.4.3 限定小数位数1.4.4 输出部分字符串2. scanf 函数格式化输入2.1 基本用法2.2 scanf 的返回值printf返回成功输出的字符数失败时返回负值。2.3 占位符与 printf 类似一、数据类型介绍1. 什么是数据类型在计算机科学中数据类型Data Type是一个基础且核心的概念。它定义了数据的性质、取值范围、存储方式以及可以对其执行的操作。简单来说数据类型决定了计算机如何理解和处理一段数据。例如数字42和文本42对人类来说可能含义相似但对计算机而言前者是整数可以进行加减乘除运算后者是字符串可以进行拼接、查找等操作。明确数据类型是编写正确、高效程序的第一步。2. 常见的数据类型分类数据类型通常可以分为两大类内置类型和自定义类型。2.1 内置数据类型内置数据类型是不可再分的最小数据单元。它们通常直接存储在栈内存中操作速度快。整型用于表示整数如int、short、long。在 C/C 等语言中整型还可以分为有符号signed和无符号unsigned两种。有符号整型可以表示正数、负数和零而无符号整型只能表示非负数零和正数因此其正数表示范围更大。浮点型用于表示带小数点的数字如float、double。字符型用于表示单个字符如char。字符类型存储的时候是存储ASCII值ASCII值是整数所以字符类型是属于整型家族的。布尔型用于表示逻辑真或假只有两个值true和false。2.2 自定义数据类型自定义数据类型是由基本数据类型或其他复合类型组合构造而成的。它们的数据通常存储在堆内存中变量本身存储的是对数据的引用地址。数组用于存储固定大小的同类型元素集合。字符串用于存储文本在许多语言中如 Java 的String被视为特殊的引用类型。结构体/类用于将不同类型的数据封装成一个逻辑单元是面向对象编程的基石。集合如列表、字典、集合等用于动态存储和管理数据。二、变量了解清楚了类型我们使用类型做什么呢类型是用来创建变量的。什么是变量呢C语言中把经常变化的值称为变量不变的称为常量。1. 变量的创建与命名规则变量是程序中用于存储和表示数据的基本单元。你可以将变量理解为一个有名字的“盒子”用来存放特定类型的数据。1.1 变量的创建声明与初始化在大多数编程语言中创建一个变量通常需要两个步骤1.声明Declaration告诉编译器/解释器变量的类型和名称。2.初始化Initialization为变量赋予一个初始值。这两个步骤可以分开进行也可以合并为一步。示例以 C/Java 风格为例1.2 变量的命名规则为了代码的可读性和可维护性变量的命名需要遵循一定的规则和约定基本规则通常由语言强制规定只能包含字母A-Z, a-z、数字0-9和下划线_。不能以数字开头。不能是语言的关键字如int,if,for。区分大小写myVar和myvar是两个不同的变量。长度不超过63个字符。命名约定最佳实践见名知意变量名应清晰描述其用途如student_count优于sc。风格统一小驼峰式camelCase如firstName,totalAmountJava, JavaScript 常用。蛇形命名snake_case如first_name,total_amountPython, C 常用。帕斯卡命名PascalCase如FirstName,TotalAmount常用于类名。避免使用单个字母除了循环计数器i,j,k等。2. 变量的作用域全局变量与局部变量根据变量在程序中声明的位置其可被访问的范围即作用域不同主要分为全局变量和局部变量。2.1 全局变量在括号外部定义的变量就是全局变量。特点从声明处开始到整个程序文件结束都有效。可以被该文件内的所有函数、代码块访问和修改。生命周期与程序运行周期相同。2.2 局部变量再大括号内部声明的变量称为局部变量。特点只在声明它的函数或代码块内部有效。外部无法直接访问。生命周期短暂通常在函数调用结束时或离开代码块时被销毁。注意局部优先2.3全局变量和局部变量在内存中存储的位置变量创建的本质是在内存中开辟空间一般我们在学习C/C语言的时候我们会关注内存中的三个区域栈区、堆区、静态区。局部变量是放在内存的栈区全局变量是放在内存的静态区堆区是用来动态内存管理的2.4 对比与注意事项特性全局变量局部变量声明位置所有函数/代码块之外函数或代码块内部作用域整个程序文件声明它的函数/代码块内部生命周期程序开始到结束函数/代码块开始到结束内存区域通常位于静态存储区或全局数据区通常位于栈Stack内存默认初始值通常自动初始化为零值如 0, NULL不会自动初始化值是未定义的垃圾值使用建议谨慎使用避免过度使用导致代码耦合度高、难以维护。优先使用有助于封装和减少副作用。核心原则在满足功能需求的前提下应尽量使用作用域小的局部变量这有利于模块化、减少命名冲突和内存管理。三、算数操作符在编程中计算是基本且频繁的操作。C语言为了方便各种运算提供了一系列操作符也称为运算符。其中算术操作符是最基础、最常用的一组用于执行基本的数学运算。算术操作符主要包括加、-减、*乘、/除、%取模。这些操作符都是双目操作符即需要两个操作数左操作数和右操作数才能完成运算。1. 加法与减法操作符 和 -和-分别用于完成加法和减法运算其用法与数学中的加法和减法基本一致。基本用法操作数可以是变量、常量或表达式。注意事项类型转换当两个操作数类型不同时如int和float会发生隐式类型转换最终结果的类型通常是“更宽”的类型。溢出对于整型需要注意运算结果可能超出该类型所能表示的范围导致溢出未定义行为。2. 乘法与除法操作符* 和 /*用于乘法/用于除法。基本用法除法操作的特性整数除法当两个操作数都是整数时/执行的是整数除法结果会截断小数部分只保留整数部分。浮点数除法如果至少有一个操作数是浮点数float或double则执行浮点数除法结果保留小数。注意事项除以零在 C 语言中整数除以零会导致运行时错误通常是程序崩溃。浮点数除以零可能会得到无穷大inf或 NaN非数字具体取决于编译器和标准。3. 取模操作符%%操作符用于计算两个整数相除后的余数。它只适用于整数类型不能用于浮点数。基本用法常见用途判断奇偶性if (num % 2 0)表示num是偶数。循环数组索引index (index 1) % array_size可实现循环访问。数字拆分获取一个整数的个位数等。注意事项取模运算的结果符号与被除数左操作数的符号相同。右操作数不能为零否则会导致运行时错误。4. 算术操作符的优先级与结合性当表达式中包含多个操作符时需要遵循优先级和结合性规则来确定运算顺序。优先级从高到低*、/、%乘法、除法、取模、-加法、减法结合性算术操作符的结合性都是从左到右。示例当优先级相同时按从左到右的顺序计算。四、 赋值操作符和复合赋值1. 连续赋值赋值操作符也可以连续赋值如C语言虽然支持着这种连续赋值但是写出的代码不易理解建议还是拆开来写这样方便观察代码的执行细节。这样写在调试时每一次的赋值的细节都是可以很方便的观察的。2. 复合赋值C语言提供了将算术操作与赋值结合的复合赋值操作符可以使代码更简洁。操作符示例等价于含义a 5;a a 5;加后赋值-b - 3;b b - 3;减后赋值*c * 2;c c * 2;乘后赋值/d / 4;d d / 4;除后赋值%e % 7;e e % 7;取模后赋值x 2;x x 2;左移后赋值y 1;y y 1;右移后赋值z 0xFF;z z 0xFF;按位与后赋值|w | 0x01;w w | 0x01;按位或后赋值^v ^ 0x0F;v v ^ 0x0F;按位异或后赋值五、单目操作符 、-- 、 、-前面介绍的操作符都是双目操作符有两个操作数的。C语言中还有一些操作符只有一个操作数被称为单目操作符。 、-- 、正、-负就是单目操作符。1. 和--自增和--自减是单目操作符用于将变量的值增加 1 或减少 1。它们有前缀和后缀两种形式行为略有不同。前缀形式先增减后使用后缀形式先使用后增减注意事项避免在同一个表达式中对同一个变量多次使用自增/自减操作符其结果是未定义行为如i i;。常用于循环控制变量如for (int i 0; i n; i)。2. 和 -这里的 是正号- 是负号都是单目操作符。运算符 对正负没有影响是一个完全可以省略的运算符但是写了也不会报错。运算符 - 用来改变一个值的正负负数的前面加上 - 就会得到证书正数的前面加上 - 会得到负数。六、强制类型转换在操作符中还有一种特殊的操作符是强制类型转换。在编程中我们经常需要在不同类型的数据之间进行转换。当编译器无法自动完成这种转换或者我们需要明确指定转换方式时就需要使用强制类型转换Type Casting。语法形式很简单形式如下语法通常是在要转换的值或变量前加上目标类型并用括号括起来示例1浮点数转整数示例2整数除法得到浮点数结果示例3字符与整数的转换注意强制类型转换是一把双刃剑。它提供了强大的灵活性允许程序员跨越类型系统的限制但也带来了数据丢失、未定义行为等风险。基本原则是尽量避免不必要的强制转换如果必须使用请确保你完全理解转换的后果 。数据丢失截断从浮点型转换为整型时小数部分会被直接丢弃而不是四舍五入。值域溢出如果转换后的值超出了目标类型的表示范围结果将是未定义的通常会发生溢出。符号问题在有符号和无符号整数之间转换时负数的表示会发生变化。指针转换的危险性不相关的指针类型之间的强制转换如int*转float*可能导致程序崩溃或产生难以调试的错误。七、scanf 和 printf 的介绍在 C 语言中scanf和printf是两个最基础、最常用的输入输出函数它们都定义在标准输入输出头文件stdio.h中。它们是程序与用户交互的桥梁也是调试和展示结果的重要工具。1. printf 函数格式化输出1.1 基本用法printf的作用是将参数文本输出到屏幕。它名字里面的f代表format格式化表示可以定制输出文本的格式包含要输出的普通文本和格式控制符以%开头。上面命令会在0屏幕上输出一行文字“Hellow World”printf不会再行尾自动添加换行符运行结束后光标停在输出结束的地方不会自动换行。 为了让光标移到下一行的开头可以在输出文本的结尾添加一个换行符\n。如果内部有换行也是通过插入换行符来实现的如下方代码printf()是在标准库的头文件stdio.h定义的。使用这个函数之前必须在源代码文件头部引入这个头文件。1.2 占位符printf可以在输出文本中指定占位符。所谓“占位符”就是这个位置可以用其他值代入。上面实例中There are %d apple \n 是输出文本里面的 %d 就是占位符表示这个位置要用其它值来代替。占位符的第一个字符一律为 % 第二个字符表示占位符的类型%d 表示这里带入的值必须是一个10进制的整数。printf的第二个参数就是替换占位符的值。上面的例子是整数3替换%d 。执行后输出结果就是There are 3 apple。输出文本里面可以使用多个占位符上面示例中输出文本 %s says it is %d oclock 有两个占位符第一个占位符是字符串占位符 %s 第二个是整数占位符 %d ,分别对应printf的第二个参数lisi和第三个参数21。执行后的输出是 lisi says it is 21 oclock。printf参数与占位符是一一对应的关系如果有n个占位符printf的参数就应该有n1个。如果参数个数少于对应的占位符printf可能会输出内存中的任意值。1.3 占位符举例格式控制符说明对应类型示例%a/%A输出十六进制浮点数小写/大写double,floatprintf(%a, 3.14);%c输出单个字符charprintf(%c, A);%d输出有符号十进制整数intprintf(%d, 42);%e/%E输出科学计数法浮点数小写e/大写Edouble,floatprintf(%e, 3.14);%f输出十进制浮点数默认保留6位小数double,floatprintf(%f, 3.14);%g/%G根据值自动选择%f或%e格式小写/大写double,floatprintf(%g, 3.14);%hd输出有符号短整型short intprintf(%hd, 32767);%ho输出无符号短整型八进制unsigned short intprintf(%ho, 65535);%hx/%hX输出无符号短整型十六进制小写/大写unsigned short intprintf(%hx, 65535);%hu输出无符号短整型十进制unsigned short intprintf(%hu, 65535);%ld输出有符号长整型long intprintf(%ld, 1000000L);%lo输出无符号长整型八进制unsigned long intprintf(%lo, 4000000000UL);%lx/%lX输出无符号长整型十六进制小写/大写unsigned long intprintf(%lx, 4000000000UL);%lu输出无符号长整型十进制unsigned long intprintf(%lu, 4000000000UL);%lld输出有符号长长整型long long intprintf(%lld, 10000000000LL);%llo输出无符号长长整型八进制unsigned long long intprintf(%llo, 10000000000ULL);%llx/%llX输出无符号长长整型十六进制小写/大写unsigned long long intprintf(%llx, 10000000000ULL);%llu输出无符号长长整型十进制unsigned long long intprintf(%llu, 10000000000ULL);%Le/%LE输出长双精度科学计数法浮点数long doubleprintf(%Le, 3.14L);%Lf输出长双精度十进制浮点数long doubleprintf(%Lf, 3.14L);%n将已输出的字符数写入指针参数int *int count; printf(Hello%n, count);%o输出八进制整数unsigned intprintf(%o, 64);%p输出指针地址十六进制void *printf(%p, var);%s输出字符串char *printf(%s, Hello);%u输出无符号十进制整数unsigned intprintf(%u, 100u);%x/%X输出十六进制整数小写/大写unsigned intprintf(%x, 255);%zu输出size_t类型无符号整数size_tprintf(%zu, sizeof(int));%%输出百分号字符无字面量printf(完成度: 50%%);1.4 输出格式printf可以定制占位符的输出格式1.4.1 限定宽度printf允许限定占位符的最小宽度示例一上面示例输出“ 123”%5d表示这个占位符的宽度至少为5位。如果不满5位对应的值起那面会添加空格。输出的值默认是右对齐及输出内容前面会有空格如果希望改成左对齐在输出内容后面添加空格可以在占位符的%的后面输入一个 - 号。上面示例输出“123 ”后面添加了空格。示例二对于小数这个限定符会限制所有小数的最小显示宽度。%f 在打印小数的时候默认小数点后6位。上面示例输出“ 123.450000”%12表示输出的浮点数在最少要占据12位。由于小数的默认显示精度是小数点后6位所以输出结果头部会添加2个空格。1.4.2 总是显示正负号默认情况下printf不对正数显示 号只对负数显示 - 号。如果想要正数也输出 号可以在占位符的 % 后面加一个 。上面的示例中%d 可以确保输出的数值总是带有正负号。1.4.3 限定小数位数示例一输出小数时有时希望限定小数位数。举例来说希望小数点后面只保留2位占位符可以写成%.2f。这种写法可以与限定宽度占位符结合使用。上面示例中%6.2f表示输出字符串最小宽度为6小数位为2。所以输出字符串的头部有两个空格。示例二最小宽度和小数位数这两个限定值都可以用 * 代替通过printf的参数传入。上面示例中%**f 的两个星号通过 printf() 的两个参数 6 和 2 传入。1.4.4 输出部分字符串%s 占位符用来输出字符串默认是全部输出。如果只想输出开头部分可以用 %.[m]s 指定是输出长度其中 [m] 代表一个数字表示所要输出的长度。上面实例中占位符 %.5s 表示只输出字符串“hellow world”的钱5个字符即“hellow”。2. scanf 函数格式化输入当我们有了变量我们需要给变量输入值就可以使用scanf函数如果需要将变量的值输出在屏幕上的时候可以使用printf函数编译时常见的出错情况2.1 基本用法scanf函数用于读取用户的键盘输入。程序运行到这个语句时会停下等待用户从键盘输入。用户输入数据按下回车后scanf就会处理用户的输入将其存入变量。它的原型定义在头文件stdio.h。scanf的语法与printf类似。scanf处理用户输入的原理是用户的输入先放入缓存等到按下回车键后按照占位符对缓存进行解读。解读用户输入时会从上一次解读遗留的第一个字符开始知道读完缓存或者遇到第一个不符合条件的字符为止。2.2 scanf 的返回值printf返回成功输出的字符数失败时返回负值。scanf的返回值是一个整数表示成功读取的变量个数可用于验证输入是否合法。如果没有读取任何项或者匹配失败则返回 0 。如果在成功读取任何数据之前发生了读取错误或者遇到读取到文件结尾则返回常量 EOF-1。EOF - end of file 文件结束标志WindowsCtrlZLinux/MacCtrlD。示例一示例二示例三示例四示例五2.3 占位符与 printf 类似格式控制符说明示例%c读取单个字符包括空格、换行scanf(%c, ch);%d读取有符号十进制整数scanf(%d, num);%f读取单精度浮点数float类型scanf(%f, score);%lf读取双精度浮点数double类型scanf(%lf, price);%Lf读取长双精度浮点数long double类型scanf(%Lf, ld_val);%s读取字符串遇到空格、制表符、换行停止scanf(%s, name);%[]扫描字符集合读取匹配指定字符集的字符串scanf(%[a-zA-Z], letters);注意上面所有占位符之中除了 % c 以外都会自动忽略起首的空白字符。% c 不忽略空白字符总是返回当前第一个字符无论该字符是否为空格。如果要强制跳过字符前的空白字符可以写成 scanf (% c, ch)即 % c 前加上一个空 格表示跳过零个或多个空白字符。下面要特别说一下占位符 % s它其实不能简单地等同于字符串。它的规则是从当前第一个非空白字符开始读起直到遇到空白字符即空格、换行符、制表符等为止。因为 % s 不会包含空白字符所以无法用来读取多个单词除非多个 % s 一起使用。这也意味着scanf () 不适合读取可能包含空格的字符串比如书名或歌曲名。另外scanf () 遇到 % s 占位符会在字符串变量末尾存储一个空字符 \0。scanf () 将字符串读入字符数组时不会检测字符串是否超过了数组长度。所以储存字符串时很可能会超过数组的边界导致预想不到的结果。为了防止这种情况使用 % s 占位符时应该指定读入字符串的最长长度即写成 %[m] s其中的 [m] 是一个整数表示读取字符串的最大长度后面的字符将被丢弃。2.4 赋值忽略符有时用户的输入可能不符合预定的格式解决方法