本章内容:
1.C语言数据类型及变量
1)数据类型简单介绍
在C语言中,它提供了丰富的数据类型来描述生活中的各种数据,比如我们去超市买东西,买完东西之后,收银员会给我们一个小票,小票上的信息大概如下表:
| 单号 | 名称 | 单位 | 单价 | 数量 | 小计 |
| 15666 | 麻辣王子 | 袋 | 5.00元 | 3 | 15.00元 |
| 15777 | 白象泡面 | 桶 | 4.50元 | 2 | 9.00元 |
我们对这个表格进行简单的分析发现:
| 单号 | 整数 |
| 名称 | 文本 |
| 单位 | 文本 |
| 单价 | 小数 |
| 数量 | 整数 |
| 小计 | 小数 |
那么在C语言中我们使用整型类型来描述整数,使用字符类型来描述字符,使用浮点型来描述小数,所谓类型就是i相似的数据所拥有的共同特征,编译器只有知道了数据的类型,才知道怎么去操作数据。
在C语言中,数据类型分为以下两个大类,如下图:
- 字符型
char [signed] char //有符号的 unsigned char //无符号的- 整型
//短整型 short [int] [signed] short [int] unsigned short [int] //整型 int [signed] int unsigned int //长整型 long [int] [signed] long [int] unsigned long [int] //更长的整型,C99中引入的 long long [int] [signed] long long [int] unsigned long long [int]上面代码中的[ ]内容是可以省略的,比如[signed] int是等价于int的。
- 浮点型
float //单精度浮点型 double //双精度浮点型 long double //更长的浮点型- 布尔类型:起初C语言并没有为布尔值单独设置一个类型,而是使用整数0表示假,非零值表示真,在C99中引入了布尔类型,是专门用来表示真假的。
_Bool其变量的取值是true或者false,使用布尔类型需要添加相对应的头文件stdbool.h。
这个代码意思就是,如果flag为真,就执行if下面语句,如果flag为假,就执行else下面的语句,if else语句后面会讲解,到时侯各位道友就懂了。
- 数据类型的长度
既然有了数据类型,那我们就来看一下数据类型的大小,我们求数据类型的长度是需要用到sizeof这个关键字的,sizeof同样也是一个操作符,它是专门用来计算sizeof的操作数的类型的长度的,单位是字节。
sizeof操作符的操作数可以是类型,也可以是变量或者表达式,比如:
sizeof(类型) sizeof 表达式那么上面代码中,sizeof后面括号中的内容便是sizeof的操作数,这里也只演示了它的操作数是类型的情况下,至于它的操作数是表达式的情况,还望各位道友可以在自己的电脑上练习操作一下,其实要学好C语言最重要的一个环节就是敲代码,不要觉得你自己眼睛会了,真正上手操作的时候,发现还是不会哈,这就很尴尬。
不同的编译器,相同的类型可能有不同的值,比如说有的编译器中的long的值就是8,而不是4。
2)signed和unsigned简单介绍
C语言是使用signed和unsigned关键字来修饰字符型和整型类型的。
- signed关键字,表示一个类型带有正负号,包含负值。
- unsigned关键字,表示该类型不带有正负号,只能表示零和整数。
对于int类型,默认是带有正负号的,所以上面也说到int等同于signed int,但是如果我们想要我们的数据不包含负值,那么定义变量的时候,就要用到unsigned,这样也有另外一个好处,就是同样长度的内存能够表示的最大整数值,增大了一倍,比如16位的int取值范围是-32768~32767,而unsigned int取值范围则是0~65535,最大值增大到了65535,比32767增大一倍。
注意,C语言规定char类型默认是否带有正负号,是由当前系统决定的,也就是说,char不等同于signed char,这一点与int不同,但是在VS2026软件系统中,char是等同于signed char的。
3)数据类型的取值范围
| 数据类型 | 类型标识符 | 字节数 | 取值范围 |
| 短整型 | short | 2 | -32768~32767 |
| 整型 | int | 2或4 | 同short或long,取决于C编译系统 |
| 长整型 | long | 4 | -2^31~2^31-1 |
| 无符号短整型 | unsigned short | 2 | 0~65535 |
| 无符号整型 | unsigned int | 2或4 | 同unsigned short或unsigned long |
| 无符号长整型 | unsigned long | 4 | 0~2^32-1 |
| 单精度浮点型 | float | 4 | -3.4*10^-38~3.4*10^38 |
| 双精度浮点型 | double | 8 | -1.7*10^-308~1.7*10^308 |
| 字符型 | char | 1 | ASCII码0~127 |
| 有符号字符型 | signed char | 1 | -128~127 |
| 无符号字符型 | unsigned char | 1 | 0~255 |
4)变量和常量简单介绍
C语言中把经常变化的值称为变量,不变的值称为常量。
变量创建的语法形式如下:
datatype name;
| |
| |
数据类型 变量名
变量命名的规则是:
- 只能由字母(包括大写和小写),数字和下划线('_')组成
- 不能以数字开头
- 长度不能超过63个字符
- 变量名中是区分大小写的,比如int A和int a就是两个变量
- 变量名不能使用关键字
int a; //整型变量 char c; //字符变量 float n; //浮点型变量 double f; //浮点型变量变量在创建的时候给一个初始值,就叫初始化。
int a = 10; char c = 'm'; float n = 6.5; double f = 3.14;变量的分类:
- 全局变量:在大括号外部定义的变量就是全局变量,全局变量的使用范围广,整个工程中都可以使用。
- 局部变量:在大括号内部定义的变量就是局部变量,局部变量的使用范围比较局限,只能在自己所在的局部范围内使用。
那如果全局变量的局部变量名字相同呢?
在全局变量和局部变量相同的时候,局部变量是优先使用的,但最好不要给全局变量和局部变量给相同的名字,那么我们在给变量起名字的时候可以稍微有意义,比如你的数据想要描述一群人的年龄,那么我们就可以定义为int age = 0;如果是体重,就可以是float weight = 0.0f;
5)操作符简单介绍
- 算数操作符:+、-、*、/、%
我们在写代码的时候,一定会涉及到计算,C语言就提供了一系列操作符,其中一组就是算数操作符,而算数操作符也是双目操作符,因为它有两个操作数。
+和-:
#include <stdio.h> int main() { int a = 20 + 26; int b = 20 - 26; printf("%d\n",a); //输出46 printf("%d\n",b); //输出-6 return 0; }*
#include <stdio.h> int main() { int a = 5; int b = 6; printf("%d\n",a*b); //输出30 return 0; }/(这个运算符需要特殊注意)
#include <stdio.h> int main() { int a = 6 / 4; float b = 6 / 4; printf("%d",a); printf("%d",b); return 0; }首先a的值是1,b的值是1.000000,很奇怪为什么不是1.5对吧,因为a是一个整型变量,它得到的值一定会是一个整数,所以肯定不会得到小数。
那么为什么b是一个浮点型变量,得到的值还不是1.5呢?因为这就跟操作符两端的操作数有关了,要想得到的结果为小数,两端的操作数必须至少有一个为小数,得到的结果才能是小数。
这就是C语言除法运算符里我们需要特殊注意到的东西。
%(求模运算符):只能用于两个整数之间进行运算,得到的结果是两个整数的余数
#include <stdio.h> int main() { int a = 6 % 4; printf("%d\n",a); //a的值为2,6除4的余数是2 return 0; }这是正数的求模规则,那么负数的求模规则是由第一个操作数的正负号决定:
#include <stdio.h> int main() { printf("%d\n",6%4); //结果是2 printf("%d\n",-6%4); //结果是-2 printf("%d\n",6%-4); //结果是2 return 0; }- 赋值运算符(=)
int a = 20;//初始化
a = 200; //赋值,这里使用的就是赋值操作符,它也是一个双目操作符
- 单目操作符:++,--,+(正号),-(负号)
++和--(分为前置++,-- 和后置++,--)
前置++:
int a = 10;
int b = ++a;
printf("a = %d b = %d\n"); //a的值为11,b的值为11
计算口诀:先+1,后使用,a原来是10,先+1后变为11,后使用就是再赋值给b,b也为11
前置- - :
int a = 10;
int b = --a;
printf("a = %d b = %d\n"); //a的值为9,b的值为9
计算口诀:先-1,后使用,a原来是10,先-1后变为9,后使用就是再赋值给b,b也为9
后置++:
int a = 10;
int b = a++;
printf("a = %d b = %d\n"); //a的值为11,b的值为10
计算口诀:先使用,后+1,a原来是10,先使用后赋值给b,b为10,然后再+1,a为11
后置- - :
int a = 10;
int b = a--;
printf("a = %d b = %d\n"); //a的值为9,b的值为10
计算口诀:先使用,后-1,a原来是10,先使用后赋值给b,b为10,然后再-1,a为9
总而言之:前置++或--就是先+1或-1,后使用,后置++或--就是先使用,后+1或-1。
+和-(正号和负号)
运算符+号对正负值没有影响。
int a = 10; 等价于 int a = +10;
运算符-号用来改变一个值的正负号,在一个正数前面加一个 -号 让其变为负数,在一个负数前面加一个 -号 让其变为正数。
int a = 10;
int b = -a;
int c = -10;
printf("b = %d c = %d",b,c); //这里的b和c都是-10
int a = -10;
int b = -a;
printf("b = %d",b); //这里的b是10
6)强制类型转换
强制类型转换顾名思义就是把一个类型的值强制转换为另一个类型的值,比如:
int a = 3.14;
但是a是一个整型变量,而我们要把3.14这个浮点型值赋给a显然是不可能的,这时候,我们只需要把这个代码改为 int a = (int)3.14;就可以了,但是这样保存下来的值是要舍去小数部分的,最终a的值就是3,各位道友发现没有,强制类型转换它其实不安全,因为它很可能会造成数据的丢失,所以我们使用强制类型转换的时候是万不得已才去使用的,一般情况下就不要去使用了。
那么为什么说它很可能会造成数据丢失呢?在VS2026编译器中,浮点型值默认为double类型,如果想让它是一个float类型的值,在后面加f就好,比如3.14f,那么前面说到double类型是占8个字节的,而int类型是占4个字节的,那么如果强制把8个字节的数据存放到4个字节的空间大小里,是存不下的,那如果你非要存进来,我就会把多余4个字节的数据给截断,那就会造成数据丢失,就好比你非要把1升的水装进500毫升的瓶子里,那结果不就是多余的500毫升水溢出去了对吧。
7)printf、占位符、scanf
- printf
printf函数是一个库函数,它的作用是将参数文本输出到屏幕,它也可以指定输出文本的格式,比如最开始那个C语言代码:
#include <stdio.h> int main() { printf("Hellow World"); return 0; }上面的命令就是在屏幕上输出一行文字"Hellow World",而printf()不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地方,不会自动换行,为了让光标移到下一行的开头,就需要在输出文本的结尾添加换行符\n。如果文本内部需要换行,也可以插入换行符\n来实现。
既然printf函数可以打印字符串,那么也可以打印其他类型的数据,比如:
#include <stdio.h> int main() { int n = 100; char c = 'm'; float f = 5.20; printf("%d\n",n); printf("%c\n",'m'); printf("%f\n",5.20); return 0; }这里的%d,%c等都是占位符,会被后面的值替换,同时我们使用printf这个库函数是需要包含头文件的,就是stdio.h。
- 占位符
所谓占位符就是这个位置可以用其他值代入,就好比大家上课都有帮朋友占座位的时候,用一本书把那个位置占着,直到你朋友来之后,他就坐在那个座位里了,是一个道理,我们来看下面这个代码:
#include <stdio.h>
int main()
{
printf("There are %d apples\n",3);
return 0;
}
代码里的%d就是一个占位符,表示这个位置用其他值来替换,后面我可以填3,也可以填其他数字,但必须是整数,因为%d是表示十进制的整数。
而我们使用占位符的时候第一个字符一律是%,第二个字符表示占位符的类型,%d表示这里代入的值必须是一个整数(十进制的整数)。
当然在输出文本里也可以有多个占位符,而printf()参数与占位符是一一对应关系,如果有n个占位符,printf()的参数就应该有n+1个,如果参数个数少于对应的占位符,printf()可能会输出内存任意值,比如说:
占位符列举:
- %c:字符
- %d:十进制整数
- %f:小数(包含float类型和double类型)
- %hd:十进制short int类型
- %hu:unsigned short int类型
- %ld:十进制long int类型
- %lu:unsigned long int类型
- %lld:十进制long long int类型
- %Lf:long double类型浮点数
- %p:指针(用来打印地址)
- %s:字符串
- %u:无符号整数,unsigned int类型
- %x:十六进制整数
- %zd:size_t类型
- %%:输出一个%
这些是常用的一些占位符,当然还有很多占位符,不是很常用,我这里就不再介绍了。
前面也说到printf()可以指定输出格式:
- 限定宽度
#include <stdio.h> int main() { printf("%5d\n",123); //输出为" 123" return 0; }%5d表示这个占位符的宽度至少为5位,如果不满5位,对应的值的前面会添加空格,输出的值默认为右对齐,如果希望是左对齐,把%5d改为%-5d。
#include <stdio.h> int main() { printf("%-5d\n",123); //输出为"123 " return 0; } 对于小数来说,这个限定符会限制所有数字的最小显示宽度,比如输出:" 123.450000"
#include <stdio.h> int main() { printf("%12f\n",123.45); //输出为" 123.450000" return 0; } %12f表示输出的浮点数最少要占据12位,由于小数的默认显示精度是小数点后6位,所以123.450000输出结果前面加两个空格。
- 总是显示正负号
默认情况下,printf()不会对正数显示+号,但是会对负数显示-号,如果想让正数显示+号,可以在占位符的%后面加一个+:
#include <stdio.h> int main() { printf("%+d\n",12); //输出+12 return 0; }- 限定小数位数
输出小数的时候,如果想要保留后两位就可以写成%.2f:
#include <stdio.h> int main() { printf("%.2f\n",12.3456); //输出"12.35" return 0; }那如果想要限定最小宽度的同时又想保留小数位数,就可以写成%12.2f:输出" 12.35"
- 输出部分字符串
%s占位符用来输出字符串,默认是全部输出,如果只想输出开头的部分,可以用%.[m]s指定输出的长度,其中[m]代表一个数字,表示所要输出的长度,比如:
#include <stdio.h> int main() { printf("%.5s\n","hello world"); //输出"hello" return 0; } - scanf
当我们创建了变量之后,我们也可以给变量输入值,这时候就需要用到scanf这个函数了,也可以说它是一个输入函数,那么printf函数就是一个输出函数对吧,它们两其实是一对函数,使用这两个函数需要添加的头文件是相同的,都是stdio.h,我们来看下面这段代码:
这就是一个简单的输入输出代码。
- scanf基本用法
scanf()函数是用来读取用户的键盘输入,程序运行到这个语句的时候会自动停下来,等待用户从键盘的输入,用户在输入数据之后按下entre键,scanf()就会处理用户的输入,将其存入变量,它的语法基本是和printf()基本一样哈。
int i = 0;
scanf("%d",&i);
它的第一个参数是一个格式字符串,里面会放置占位符,与printf()的占位符基本一致,来告诉编译器如何解读用户的输入,需要提取的数据是什么类型,这是因为C语言的数据都是有类型的,scanf()必须知道用户输入的数据类型,才能处理数据。
上面示例中:scanf()的第一个参数是%d,表示用户要输入的数据是一个整数,第二个参数是&i,将用户从键盘输入的整数存入变量i。
注意的是:变量前面必须加上&运算符(指针变量除外),因为scanf()传递的不是值,而是地址,即将变量i的地址指向用户输入的值。
- scanf()返回值
scanf()的返回值是一个整数,表示成功读取的变量个数,如果没有读取到任何数据,或者读取失败就返回0,如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量EOF(-1),EOF:end of file文件结束标志。
而在scanf()中的占位符,基本是和printf()的占位符一致,除了浮点型有点区别,因为printf()中的float类型和double类型都使用%f,但是在scanf()中,float类型使用%f,double类型使用%lf。
虽然前面说scanf()占位符会忽略起首空白字符,但是%c不会,因为空格也是字符。
本篇文章内容就先到这里哈,也感谢各位道友支持,我们下篇文章再见!