回顾
数据类型
-
基本类型:C语言内置
-
整型
-
短整型:short(2字节)
-
基本整型:int(4字节)
-
长整型:long(32位系统4字节/64位系统8字节)
-
长长整型:long long(8字节,C99新增)
-
-
浮点型
-
单精度型:float(4字节)
-
双精度型:double(8字节)
-
长双精度型:long double(如GCC通常是16字节,MSVC可能是8字节),取决于编译器
-
-
字符型:char C语言中 1字节=1字符,因为C语言没有字节对应发类型,使用一般用char表示字节
-
-
构造类型:C语言提供了构建语法,由程序员自己创建类型
-
结构体:struct
-
共用体/联合体:union
-
枚举:enum
-
-
指针类型
-
空类型:void
常量
定义:程序运行过程中值不变的量。
存储位置:
-
常量存储在数据段(字符串常量)或者代码段,具体由编译器来决定。
-
变量默认存储在栈区,但静态变量和全局变量存储在数据段。(后续深入)
常量的分类:
-
整型常量
-
十进制整型常量
-
八进制整型常量
-
十六进制整型常量
-
-
浮点型常量
-
十进制表示法
-
指数表示法
-
-
字符型常量
-
字符串常量
-
符号常量:宏定义
变量
概念
定义:在程序运行过程中值可变的量,称之为变量。
-
变量代表内存中(栈内存)具有特定属性的一个存储单元,它是用来存储数据的,也就是存放变量的值。
-
变量应该有一个名字,以便于通过名字访问变量。
格式
数据类型 变量名列表;
举例
/*************************************************************************
> File Name: demo03.c
> Author: 久念昕
> Description:
> Created Time: 2025年07月09日 星期三 09时56分12秒
************************************************************************/
#include <stdio.h>
int main(int argc,char *argv[])
{
// 1.声明变量并初始化
// 解释:向内存申请一块存储空间,并给这个空间添加一个初始数据
// 命名:变量名就是标识符的一种,命名规则:以字母或者下划线开头,只能包含数字、字母、下划线:set_user
// 演示变量名的命名:_int,num2
int age=21; //注意:= 不是关系运算符等于,这里称作赋值运算符,意思是将右边的常量21赋值给左边的变量。顺序:由右到左
// 2.先声明,再赋值
int count;
count = 10;
// 3.初始化和赋值并行
int number = 12;
printf("%d\n",number);// 12 %d:以十进制int的方法格式化输出
number = 22;// 此时会覆盖掉number原本的值
printf("%d\n",number);// 22
// 4.我们可以为多个变量定义同一类型,多个变量之间使用逗号分隔
int a,b = 10, c;// 此时我们定义了3个变量,只有b初始化类,其他两个变量未出初始化
// 访问未初始化的变量?
// 访问一个未初始化的变量不会报错,但是不建议访问,因为此时变量空间中的数据是系统分配的随机值。
printf("%d %d %d\n",a,b,c);
return 0;
}
基本类型:(整型、浮点型、字符型)我们创建变量的同时,在内存中开辟对应的内存空间。
命名规范
-
以字母或者下划线开头,后面跟字母、数字、下划线。举例:int ,_int,number,num1
-
不能与关键字(如:if..int..float等)或者预定义标识符(如:printf..main..)重名。
-
变量名、变量值、变量所占的存储单元之间的关系:
标识符
定义:用来表示对象名字的有效字符。对象包括变量、常量、函数、数组、构造类型等。也就是标识符是这些对象的名字。
构成:
-
C语言规定的标识符只能由字母、数字、下划线三种字符构成。且只能以下划线或者字母开头。如:_int,num
-
编译系统对字母的大小写敏感(区分大小写)。变量名和函数名一般用小写字母+下划线,常量名和枚举名一般用大写字母+下划线,举例:
变量:set_count setCount(C语言也支持,但是不推荐)
函数:set_count() setCount()(C语言也支持)
常量、枚举:SET_COUNT
-
C语言中有3类标识符:
-
关键字:有32个,系统有特定的含义和用途,不能用作自定义标识符
-
-
系统预定义的标识符:如系统提供的函数名sim,printf,main,scanf等以及预处理指令include,define等。
C语言中的12个预处理指令:
define endif elif error line include isdef ifnodef pargma undef if else
注意:以上预处理指令使用的时候,在前面需添加#,如#
-
用户标识符:用户定义的标识符,用来给变量、自定义函数、符号常量、数组、构造类型、文件等命名。
小贴士:
在C语言中,要求对所用到的变量,在使用前必须强制定义。先定义,后使用
使用
-
一个类型说明语句可以同时定义多个类型的变量,各个变量之间使用逗号分隔,多个同类型的变量也可以用多个类型说明语句定义:
// 写法1:一个类型说明语句可以同时定义多个类型的变量
// 优点:简洁
// 缺点:可读性较差
int a,b,c,d; // 定义多个同类型变量,这是一种省略写法
int a1=3,b1=4,c1=5,d1=6;
// 写法2:索格同类型的变量也可以用多个类型说明语句
// 优点:可读性强
// 缺点:繁琐
int aa;
int bb;
int cc;
int dd;
int aa1=3;
int bb1=4;
int cc1=5;
int dd1=6;
-
同类型说明语句定义的变量只是为这些变量分配了内存空间。以便于存放与之相同类型的数据。未对这些变量赋值前,这些变量中的值是随机的(具体的随机由内存状态来决定),在C标准中访问未初始化的变量是“未定义行为(UB)”
/*************************************************************************
> File Name: demo04.c
> Author: 久念昕
> Description:
> Created Time: 2025年07月09日 星期三 11时03分13秒
************************************************************************/
#include <stdio.h>
int main(int argc,char *argv[])
{
int a,b,c,d;
printf("%d,%d,%d,%d\n",a,b,c,d);// 此时的变量访问属于未定义行为,不建议这样做
return 0;
}
//第一次结果:-101494470,32764,0,0
//第二次结果:630968800,32767,0,0
-
C语言允许定义变量的同时为变量赋初始值。
-
在为长整型变量初始化或者赋值时,如果被赋值的数据为基本整型常量,则C编译系统自动将被赋值数据转换为与之相依变量类型一致的数据。
long a =12L; // 将一个long类型的常量数据12赋值给long类型的变量a,=左右两边类型一致
long b =12; // 将一个int类型的常量数据12赋值给long类型的变量b,此时=左右两边类型不一致
-
由于各种整型变量所占的字节数有限,因此他们存储的整数有一定的范围。
举例:
:1个字节,存储范围:0~255;
:1个字节,存储范围:-128~127
基本类型数据
整型数据
用来存放整型数据的变量
我们定义一个整型的变量,C编译系统实际是在内存中分配了能够存储一个整型数据的存储空间。并用变量名来标识这个空间。对该空间的使用也就是可以通过变量名来访问。(我们可以通过变量名访问变量空间)
如果不知道你所用的C编译系统对变量分配的存储空间的大小,可以通过sizeof运算符查询,如:
int a=10;
printf("%d,%d\n",sizeof(int),sizeof(a)); // 4,4,sizeof返回的大小是以字节为单位,返回类型long unsigned int
整型数据在内存中的存储形式
-
数据在内存中是以二进制形式存放
如果有以下语句:
short i; //定义i为一个存储整型的变量 2字节,默认是有符号数
i=10;
printf("%d\n",i);
则十进制数10的二进制形式为1010(十进制转二进制,使用辗转相除法),则整数10在内存中的实际存储形式为:
-
实际上,整型数据在内存中是以补码的形式表示的,使用补码主要是为了统一加减法运算,使CPU可以使用同一套加法电路处理所有整数运算(包括正数和负数),同时消除+0和-0的歧义,简化硬件设计。
我们程序中的数据直接转换处理的二进制是原码形式的。
-
正数的补码和源码(该数的二进制形式)相同,(反码是原码和补码转换的过程产物)三码唯一
-
负数的补码是将该数绝对值的二进制形式,针对数据位按位取反+1(反码+1为补码)
-
内存数据的读写:
①向内存存数据(二进制形式):程序原始数据→二进制原码→二进制反码→二进制补码
②向内存取数据(二进制形式):二进制补码→二进制反码→二进制原码→程序原始数据
案例:
需求:整型变量的定义和使用
/*************************************************************************
> File Name: demo05.c
> Author: 久念昕
> Description:
> Created Time: 2025年07月09日 星期三 14时56分35秒
************************************************************************/
#include <stdio.h>
int main(int argc,char *argv[])
{
// 定义有符号整型变量,可以存防正数、0、负数,默认就是有符号数
int a,b,c,d; // 等价与signed int a,b,c,d;
//定义无符号整型变量,可以存放正数、0,不能存放负数,必须添加关键字 unsigned
unsigned int u;
// 赋值
a=12;
b=-24;
u=10;
c=a+u,d=b+u;
printf("a+u=%d,b+u=%d\n",c,d); // a+u=22,b+u=-14
// 注意:计算机硬件支持加法运算,不支持减法运算,我们程序中的减法运算,实际上是有负数参与的加法运算,比如:5-2实际上5+(-2)
return 0;
}
有符号和无符号数在内存中的存储形式(以char类型举例):
有符号char的范围:~
无符号char的范围:~
浮点型数据
定义:用来表达实数(小数)的数据类型。
浮点型变量的分类
-
单精度浮点型(float):在64位系统中尺寸是4字节,精确到小数位6位,格式化符号%f
-
双精度浮点型(double):在64位系统中尺寸是8字节,精确到小数位15~16位,格式化符号%lf
-
长双精度浮点型(long double):在Linux下64位尺寸是16字节。
注意:占用内存越多,能标识的精确度越高。
float f1=12.25f; // 单精度
double f2=12.5; // 双精度
long double f3; // 长双精度
浮点型数据在内存中的存储形式
浮点型数据在内存中按照指数形式(IEEE 754标准)存放。系统将一个浮点型数分为尾数部分和指数部分,分别存放。
举例:
→
→
类别 | 字节数 | 符号位 | 指数位(指数部分) | 尾数位(小数部分) | 指数偏移量 |
---|---|---|---|---|---|
单精度浮点数 | 4 | 1位[31] | 8位[30~23] | 23位[22~00] | 127 |
双精度浮点数 | 8 | 1位[63] | 11位[62~52] | 52位[51~00] | 1023 |
float内存示意图:
案例
-
需求:写出27.5f在内存中的存放形式 27.05
-
解析:
-
27.5f的二进制为11011.1
-
转换为指数形式:11011.1 → 1.10111*2^4
-
指数:4+127=131,转换为二进制:
1000 0011
-
尾数:10111,需要补够23位,右侧补0:
1011 1000 0000 0000 0000 000
-
浮点型数据如何转二进制?
①整数部分:采用辗转除2直到出现小数为止。
②小数部分:采用辗转乘2直到整数位出现1,小数位出现0为止,但是有时候会出现乘不尽的情况,此时需根据内存大小来决定保留位数。
- 用二进制表示就是符号位(1位)、指数位(8位)、尾数位(23位),最终显示:
※ 科学计数法(指数法):
C语言中一般浮点数有两种表示形式:
十进制形式:指的是数字必须以整数形式+小数形式组成,比如 10.0 、3.14 ......符合规则,以10为底数,并且科学计数法要在范围值之内。
指数形式(科学记数法):一般数学上对于小数可以以10为底进行表示 比如3.14 *10²,但是在使用英文半角输入法的时候没办法输入上底或者下底,所以C语言规定以字母e或者E来表示指数,并且要求字母e或者E的前面必须有数字,字母e或者E的后面必须为整数。 -3.14E-2 2E-3 0.3E4
printf("%e", 10000000.00);
所以:E3 错误 因为E的前面有数据 比如说 3.14E3
3.1e5.6 错误 因为 E的后面必须是整数
相当于
![]()
等价于
字符型数据
概念:字符型变量用来存放字符常量。
定义:
char 变量列表;
举例:
char a='A';
char b=a;
举例:
/*************************************************************************
> File Name: demo06.c
> Author: 久念昕
> Description:
> Created Time: 2025年07月09日 星期三 16时44分36秒
************************************************************************/
#include <stdio.h>
int main(int argc,char *argv[])
{
char c1,c2;
c1='A';
c2='B';
printf("c1=%c\n",c1);//A %c是字符的格式化符号
printf("c2=%c\n",c2);
printf("c1=%d\n",c1);
printf("c2=%d\n",c2);
return 0;
}
运行结果:
说明:
一个字符变量只能存放一个字符。C编译系统规定以一个字节的存储空间来存放一个字符,因此,一个字符变量在内存中的大小是1个字节(1字节=1字符)
字符数据在内存中的存储形式
将一个字符常量存入一个字符变量,实际上并不是把该字符本身存入内存中,而是将该字符对应的ASCII(系统内置)码存入内存单元。
范例:
-
需求:
-
分析:
-
的ASCII为
,
的ASCII为
,它们在内存中的存储形式:
-
进一步理解,实际上是按照ASCII码的二进制形式存放,形式为:
由此可见,在内存中字符数据的存储形式与整型数据类似,这就使得字符型数据和整型数据之间可以调用,也就是1个字符数据既可以以字符形式输出,也可以以整数形式输出。
-
以字符形式输出时,编译系统将内存单元中的ASCII码转换为对应的字符,然后输出。
-
以整型输出时,直接将ASCII码作为整数输出。
-
因此,可以对字符数据进行算术运算,这时相当于对其ASCII码进行算数运算。
案例:
-
要求:给字符变量赋整数值
/*****************************************************************
********
> File Name: demo03.c
> Author: 久念昕
> Description: 字符型数据
> Created Time: 2025年01月21日 星期二 16时05分09秒
*****************************************************************
*******/
#include <stdio.h>
int main(int argc,char *argv[])
{
char c1,c2;
c1 = 97;// char既能赋值字符,也能赋值整数(ASCII码)
c2 = 98;
printf("%c %c \n",c1,c2);// a b, 以字符形式输出
printf("%d %d \n",c1,c2);// 97 98, 以整数形式输出
return 0;
}
说明:char类型可以赋值为字符,也可以赋值为整数(char a = 128,显示的结果范围:-128~127),演示案例:
c1在内存的存储形式以及不同形式的输出,如下图所示:
案例
-
需求:大小写字母转换
-
代码:
/*****************************************************************
********
> File Name: demo03.c
> Author: 久念昕
> Description: 字符型数据
> Created Time: 2025年01月21日 星期二 16时05分09秒
*****************************************************************
*******/
#include <stdio.h>
int main(int argc,char *argv[])
{
char c1,c2;
c1 = 'm';
c2 = 'Y';
printf("转换前:%c,%c\n",c1,c2);
// 转换
c1 = c1 - 32;
c2 = c2 + 32;
printf("转换后:%c,%c\n",c1,c2);
return 0;
}