、
一.数据类型介绍
人有黄人白人黑人,那么数据呢?
我们大家可以看出谁是黄种人,谁是白种人,谁是黑种人,这是因为他们是类似的。
数据也是有类型的,就譬如整数类型,字符类型,浮点型类型。
每种类型也都是能够抽象出共同特征的,编译器也是只有知道了数据的类型才能操作数据。
我们在本文中将学习整数类型,字符类型,浮点型类型,布尔型。
在C语言中,数据类型决定了变量在内存中存储的方式以及可以进行的操作。本文将简要介绍C语言中常见的数据类型,包括字符型、整型、浮点型和布尔类型,并在示例中详细解释其使用原因。
1.sizeof()操作符
1. 1用法
**sizeof()**
可以用于以下几种情况:
-
基本数据类型:获取基本数据类型的大小,如
int
、char
、float
等。 -
用户自定义类型:获取结构体、联合体和枚举等自定义数据类型的大小。
-
数组:获取整个数组的大小,而不仅仅是指针的大小。
-
变量:获取已声明变量的大小。
使用
对类型的使用:
sizeof(type)
其中 type
可以是任何有效的数据类型,比如 int
、float
、struct
等。
-
对变量的使用:
sizeof(variable)
其中
variable
是已声明的变量。
sizeof 运算符的返回值,C语⾔只规定是⽆符号整数,并没有规定具体的类型,⽽是留给
系统⾃⼰去决定, sizeof 到底返回什么类型。不同的系统中,返回值的类型有可能是
unsigned int ,也有可能是 unsigned long ,甚⾄是 unsigned long long ,
对应的 printf() 占位符分别是 %u 、 %lu 和 %llu 。这样不利于程序的可移植性。
C语⾔提供了⼀个解决⽅法,创造了⼀个类型别名 size_t ,⽤来统⼀表⽰ sizeof 的返
回值类型。对应当前系统的 sizeof 的返回值类型,可能是 unsigned int ,也可能是
unsigned long long
2. 字符型
字符型用于表示单个字符,通常占用1个字节。C语言中有三种字符类型:
char
:表示字符类型。[signed] char
:有符号字符类型,默认情况下char
是有符号的,范围通常为 -128 到 127。unsigned char
:无符号字符类型,范围通常为 0 到 255。
示例:
char c = 'A'; // 'A' 是单个字符,存储在1个字节中,ASCII值为65。
signed char sc = -1; // 使用有符号字符类型,允许负值。此时 -1 会被存储为 2的补码形式。
unsigned char uc = 255; // 无符号字符,表示 0-255 的正值,255 是最大值。
解释:char
默认是有符号类型,因此我们可以使用 [signed] char
来明确表示有符号或 unsigned char
来表示无符号字符,确保不出现负数溢出。
3. 整型
整型用于表示整数,包括短整型、整型、长整型等多种规格。以下是整型的具体类型:
- 短整型:
short
:表示较小范围的整数,通常占用 2 个字节。[signed] short
:有符号短整型,允许存储负数。- `unsigned short :无符号短整型,范围扩展至 0 到 65535。
- 整型:
int
:默认的整型,通常占用 4 个字节。[signed] int
:有符号整型,默认范围为 -2147483648 到 2147483647。unsigned int
:无符号整型,范围为 0 到 4294967295。
- 长整型:
long [int]
:比标准整型更大,通常占用 8 个字节(具体实现可能不同)。[signed] long [int]
:有符号长整型。unsigned long [int]
:无符号长整型。
- 更长的整型(C99引入):
long long [int]
:表示非常大的整数,通常占用 8 个字节。[signed] long long [int]
:有符号长长整型。unsigned long long [int]
:无符号长长整型。
示例:
short s = 32767; // 最大的有符号短整型数值,short 通常占 2 字节。
unsigned int ui = 4294967295; // 最大的无符号整型值,unsigned int 扩展了范围到 0-4294967295。
long long ll = 9223372036854775807; // long long 是 C99 引入的类型,用于存储极大的整数。
解释:根据具体的需求选择合适的整型类型。例如在资源有限的嵌入式系统中,短整型可能用于节省内存,而 long long
适合需要表示极大数的应用场景。
4. 浮点型
浮点型用于表示小数或科学计数法表示的数值。C语言提供了三种浮点类型:
float
:单精度浮点数,通常占用 4 字节,精度较低。double
:双精度浮点数,通常占用 8 字节,精度较高。long double
:扩展精度浮点数,占用更多的字节,依赖于具体实现。
示例:
float f = 3.14f; // 'f' 后缀强制将常量 3.14 视为 float 类型,否则它会被视为 double 类型。lf为long float
double d = 3.141592653589793; // 双精度浮点数,提供了更高的精度,适合科学计算。
long double ld = 3.14159265358979323846L; // 'L' 后缀表示 long double 类型,精度比 double 更高。
解释:C语言默认将小数视为 double
类型,因此对于 float
类型的变量,必须在常量后加上 f
后缀。对于需要极高精度的场合,例如高精度的科学计算,可以使用 long double
类型。
5. 布尔类型
在早期的C语言中,并没有专门的布尔类型,通常使用整数来表示真假:0 表示假,非零表示真。
从C99标准开始,C语言引入了专门的布尔类型,名为 _Bool
。为了使代码更加可读,C99还引入了 <stdbool.h>
头文件,它定义了 bool
、true
和 false
这几个宏,便于程序员使用。
示例:
#include <stdbool.h>
#define true 1
#define false 0
bool b = true; // 使用 C99 的布尔类型 _Bool,true 表示 1。
bool flag = false; // 使用 <stdbool.h> 定义的 bool 类型,false 表示 0。
解释:虽然布尔类型的本质是整数(0 或 1),但使用 bool
和 true/false
使代码更具可读性,尤其在逻辑判断中。
unsigned和signed
有符号数和无符号数表示的数字总量是相同的,但有符号数可以表达负数,而无符号数只能表示非负整数,因此它们的数值范围不同。
下图:
**
6.数据类型大小
#include <stdio.h>
int main()
{
printf("%zd\n", sizeof(char));
printf("%zd\n", sizeof(_Bool));
printf("%zd\n", sizeof(short));
printf("%zd\n", sizeof(int));
printf("%zd\n", sizeof(long));
printf("%zd\n", sizeof(long long));
printf("%zd\n", sizeof(float));
printf("%zd\n", sizeof(double));
printf("%zd\n", sizeof(long double));
return 0;
}
数据类型的取值范围
在C语言中,有多种整型数据类型,如 short、int、long 和 long long。为什么会有这么多不同的类型呢?其实,每种数据类型都有自己的取值范围,也就是能够存储的数值的最大值和最小值。通过提供丰富的数据类型,程序员可以根据具体场景选择最合适的类型,从而优化内存使用和性能。
如果我们需要查看某种数据类型在当前系统上的极限值,可以通过头文件 limits.h 和 float.h 来查阅。这些头文件定义了各种整数和浮点类型的取值范围。为了保证代码的可移植性,建议使用这些文件中定义的常量来获取不同数据类型的极限值。
常见的极限值常量如下:
SCHAR_MIN 和 SCHAR_MAX:signed char 的最小值和最大值。
**SHRT_MIN 和 SHRT_MAX:**short 的最小值和最大值。
**INT_MIN 和 INT_MAX:**int 的最小值和最大值。
**LONG_MIN 和 LONG_MAX:**long 的最小值和最大值。
**LLONG_MIN 和 LLONG_MAX:**long long 的最小值和最大值。
**UCHAR_MAX:**unsigned char 的最大值。
**USHRT_MAX:**unsigned short 的最大值。
**UINT_MAX:**unsigned int 的最大值。
**ULONG_MAX:**unsigned long 的最大值。
**ULLONG_MAX:**unsigned long long 的最大值。
二.变量
2.1 变量的创建
变量是可以存储数据的名字,类型用于确定变量可以存储的数据种类。变量的语法是:
数据类型 变量名;
例如:
int age; // 整型变量
char ch; // 字符变量
double weight; // 浮点型变量
变量在声明时可以赋初值,这称为初始化,例如:
int age = 18;
char ch = 'w';
double weight = 48.0;
4.2 变量的分类
- 全局变量:定义在main函数
{}
外部,作用范围全局可见,整个程序都可以访问。 - 局部变量:定义在函数
{}
内部,只能在当前函数或代码块中使用。
示例:
#include <stdio.h>
int global = 2023; // 全局变量
int main() {int local = 2018; // 局部变量printf("%d\n", local);printf("%d\n", global);return 0;
}
注意:当全局变量与局部变量同名时,局部变量优先。(就近原则)
5. 算术运算符
常见的算术运算符包括:+
(加),-
(减),*
(乘),/
(除),%
(取模)。这些操作符在运算时遵循左到右的运算顺序。
5.1 加法与减法
int x = 4 + 22; // x = 26
int y = 61 - 23; // y = 38
5.2 乘法
int num = 5;
printf("%d\n", num * num); // 输出 25
5.3 除法
整数除法只保留整数部分:
float x = 6 / 4; // 1.000000
int y = 6 / 4; // 1
当至少有一个操作数为浮点数时,进行浮点除法:
float x = 6.0 / 4; // 输出 1.500000
5.4 取模运算
取模运算 %
返回两数相除的余数,适用于整数:
int x = 6 % 4; // 输出 2
负数取模时,结果的正负号取决于第一个操作数:
printf("%d\n", 11 % -5); // 1
printf("%d\n", -11 % 5); // -1
- ps:被操作符操作的数称为操作数。
6. 赋值运算符
=
是基本的赋值运算符,此外还有复合赋值运算符,如:+=
, -=
, *=
, /=
, %=
。
例如:
int a = 10;
a += 3; // 相当于 a = a + 3
a -= 2; // 相当于 a = a - 2
赋值操作符也可以连续赋值,如:
int a = 3;
int b = 5;
int c = 0;
c = b = a+3;//连续赋值,从右向左依次赋值的。 相关知识点:操作符优先级
C语⾔虽然⽀持这种连续赋值,但是写出的代码不容易理解,建议还是拆开来写,这样⽅便在调试中观察代码的执⾏细节。
int a = 3;
int b = 5;
int c = 0;
b = a+3;
c = b;
7. 单目运算符
单目运算符只有一个操作数,如 ++
(自增),--
(自减),正号+
,负号-
。
7.1 自增与自减
前置自增/自减:先执行加/减操作,再使用该值。
int a = 10;
int b = ++a; // a先加1,a和b均为11
后置自增/自减:先使用该值,再执行加/减操作。
int a = 10;
int b = a++; // b为10,a加1后变为11
如果有机会给大家讲这两个操作符的实现的话,会讲的。
7.2 正负号运算
正号 +
不改变值,负号 -
用于取反:
int a = 10;
int b = -a; // b = -10
8. 强制类型转换
强制类型转换用于将一种数据类型转换为另一种,语法如下:
(类型) 表达式
例如:
int a = 3.14;//int-double类型不一样,报警告
int b=(int)3.14// a的值为3,取整数部分
二.printf()
2.1基本用法
print的意思是打印,f是format(格式化)。printf就代表可以按照自己规定的格式进行打印。
printf("hello 401!");
printf不会在行尾默认添加换行符,运行结束后,光标就停留在输出结束的地方。
使用\n可以让光标移到下一行
printf("hello 401\n");
2.2占位符
printf是自己定制格式的,程序做出来是给别人用的,也就是说,我们用的是我们定制的格式打印出它们个性化的语句的。
如何达到这个效果呢?
这就需要占位符了。
所谓的“占位符”,是表示这个位置可以用其他值取代。
int a;
scanf("%d",a);
printf("This is %d apples",a);
上⾯⽰例中, There are %d apples\n 是输出⽂本,⾥⾯的 %d 就是占位符,占位符的第⼀个字符为百分号 % ,第⼆个字符表⽰占位符的类型, %d 表⽰这⾥代⼊的值必须是⼀个整数。
printf() 的第⼆个参数就是替换占位符的值,上⾯的例⼦是整数 a替换 %d 。执⾏后的输出结果就是 There are “输入的a” apples 。
一行输出语句中也可以有多个占位符
printf("%s说现在%d点了", "kuzi", 21);
对于现在的你们而言,只需要记住格式即可,等学完函数,就能搞懂了。
下面列举占位符:
%d:十进制整数
%s:字符串
%c:单个字符
%f:浮点数
%x:十六进制整数
%o:八进制整数
%u:无符号整数
%%:输出百分号
%zd: 无符号整数
%p: 指针类型
2.3输出格式的限定
我们可以限定占位符的格式,如下例:
printf("%5d\n",123);
%5d 表⽰这个占位符的宽度****⾄少为5位。如果不满5位,对应的值的前⾯会添加空格。
输出的值默认是右对⻬,即输出内容前⾯会有空格;若是想要左对齐的话,可以在占位符的 % 的后⾯插⼊⼀个 - 号,会在输出内容后⾯添加空格。
printf("%-5d401\n",123);
如果是小数的话,
printf("%12f\n", 4.01);//小数默认6位,占了7位,还有5位用空格补全。
当然,也是可以显示正负号的,这个采取的方式很简单,如下:
printf("%+d401\n",123);
printf("%-d401\n",123);
输出⼩数时,有时需要限定⼩数的位数。
举例:希望⼩数点后⾯只保留两位,占位符可以写成 %.2f 。
printf("%.2f\n", 4.01);
因此,我们需要限定几位,就可以写.几(你先要的数字)了。
除此之外,.几(你想要的数字)还可以限定字符串的长度。
如下:
printf("%.5s\n","我在401学习知识");
最后一点:最小宽度和小数位数这两个限定值可以一起使用。
printf("%10.2f\n", 4.01);//占10位,保留两位小数。
三.scanf
3.1scanf使用
scanf函数用于读取用户的键盘输入,当程序运行到scanf语句时,会停下来,等待用户从键盘输入。
用户输入数据,按下回车键后,scanf会处理用户的输入,并将其存到变量当中去。
因此,scanf是用来给变量赋值的函数,使用格式如下:
scanf("%d", &a);//&为取地址符,现在记住要这么写即可。以后会教
scanf("%d%d",&a,&b);
它的第⼀个参数是⼀个格式字符串,里面会放置占位符(与 printf() 的占位符基本⼀致),告诉编
译器如何解读用户的输⼊,需要提取的数据是什么类型。
这是因为C语⾔的数据都是有类型的, scanf() 必须提前知道⽤⼾输⼊的数据类型,才能处理数
据,它的其余参数就是存放用户输⼊的变量地址的。(现在只需要记住即可,不需要懂原理,后续会讲。)
int a=0,b=0,c=0,d=0,e=0;scanf("%d", &a);//&为取地址符,现在记住要这么写即可。以后会教printf("%d\n",a);scanf("%d%d", &b,&c);//中间可以用空格隔开,也可以enter隔开printf("%d %d\n", b, c); //中间可以用空格,也可以enter隔开scanf("%d,%d", &d, &e);//不推荐用这种,只能用逗号隔开printf("%d %d\n",d,e);