一、数据类型介绍
所谓“类型”,就是相似的数据所拥有的共同特征,编译器只有知道了数据的类型,才知道怎么操作 数据。
使用整型类型来描述整数,使用字符类型来描述字符,使用浮点型类型来描述小数。
c语言的数据类型有俩种:内置类型和自定义类型:
- 内置类型:字符型、整型、浮点型、布尔类型
- 自定义类型:数组、结构体-struct、枚举-enum、联合体-union
1.1字符型
字符的英文单词是 character ,在c语言中使用 char 表示字符类型。
char //character signed char; //有符号的 unsigned char; //无符号的
1.2整型
整数的英文单词是 integer ,在c语言中使用 int 表示整型类型。
//短整型 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]
1.3浮点型
float //单精度浮点型 double //双精度浮点型 long double //更高精度
1.4布尔类型
在c99中引入的布尔类型专门表示真假
布尔类型的使用需要包含头文件<stdbool.h>
布尔类型变量的取值是:true或false
define bool _bool
#define false 0
#define true 1
演示:
_bool flag = true;
if (flag)
printf("i like c\n");
1.5各种数据类型的长度
每⼀种数据类型都有自己的长度,使⽤不同的数据类型,能够创建出长度不同的变量,变量长度的不 同,存储的数据范围就有所差异。
1.5.1 sizeof操作符
sizeof 是⼀个关键字,也是操作符,专门是用来计算 sizeof 的操作符数的类型长度的,单位是字节。 sizeof 操作符的操作数可以是类型,也可是变量或者表达式。
sizeof ( 类型 ) sizeof 表达式
sizeof 的操作数如果不是类型,是表达式的时候,可以省略掉后边的括号的。
sizeof 后边的表达式是不真实参与运算的,根据表达式的类型来得出大小。
sizeof 的计算结果是 size_t 类型的。c语言创造了⼀个类型别名 size_t ,用来统⼀表示 sizeof 的返回值类型。对应当前系统的 sizeof 的返回值类型,可能是 unsigned int ,也可能是 unsigned long long 。
#include <stdio.h>
int main()
{
int a = 10;
printf("%zd\n", sizeof(a));
printf("%zd\n", sizeof a ); //a是变量的名字,可以省略掉sizeof后边的()
printf("%zd\n", sizeof(int));
printf("%zd\n", sizeof(3 + 3.5));
return 0;
}
1.5.2 数据类型长度
#include <stdio.h>
int main()
{
printf("%zd\n", sizeof(char)); 输出1
printf("%zd\n", sizeof(_bool)); 输出1
printf("%zd\n", sizeof(short)); 输出2
printf("%zd\n", sizeof(int)); 输出4
printf("%zd\n", sizeof(long)); 输出4
printf("%zd\n", sizeof(long long)); 输出8
printf("%zd\n", sizeof(float)); 输出4
printf("%zd\n", sizeof(double)); 输出8
printf("%zd\n", sizeof(long double)); 在vs上输出8,在gcc上输出16
return 0;
}
1.5.3 sizeof中表达式不计算
#include <stdio.h>
int main()
{
short s = 2;
int b = 10;
printf("%d\n", sizeof(s = b+1));
printf("s = %d\n", s);
return 0;
}
sizeof 在代码进行编译的时候,就根据表达式的结果的类型,推到并确定了类型的长度,而表达式 真要被执行,却要在程序运行期间才会发生,如果在编译期间已经将 sizeof 处理掉了,所以在运行期间就不会执行表达式了。
二、signed和unsigned
c语言使用signed 和 unsigned 关键字修饰字符型和整型类型的。
signed 关键字,表示⼀个类型带有正负号,包含负值; unsigned 关键字,表示该类型不带有正负号,只能表示零和正整数。
如:
对于 int 类型,默认是带有正负号的,也就是说 int 等同于 signed int 。
由于这是默认情况,关键字 signed ⼀般都省略不写,但是写了也不算错。
int 类型也可以不带正负号,只表示非负整数。这时就必须使用关键字 unsigned 声明变量。
unsigned int 里面的 int 可以省略,所以 unsigned int a 也可以写成 unsiged a 。
但是 char 不等同于 signed char,它可能是signed char,也可能是unsigned char 。
三、数据类型的取值范围
每⼀种数据类型有自己的取值范围,也就是存储的数值的最大值和最小值的区间
某种整数类型的极限值,应该尽量使用这些常量。
- 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 的最大值。
四、变量
4.1 变量的创建
类型是干什么的?类型是创建变量的
那变量是什么呢?变量是经常变化的量
不变的量称为常量
变量创建的语法形式如下:
my_student name; 数据类型 变量名
变量命名的⼀般规则:
- 只能由字母(包括大写和小写)、数字和下划线(` _ `)组成。
- 不能以数字开头。
- 长度不能超过63个字符。
- 变量名中区分大小写的。
- 变量名不能使用关键字。
int age; //整型变量 char ch; //字符变量 double weight; //浮点型变量
变量在创建的时候就给一个初始值,为初始化
int age = 18; char ch = 'h'; double weight = 45.0; unsigned int height = 90;
4.2 变量的分类
- 全局变量:在大括号外部定义的变量就是全局变量全局变量的使用范围更广,整个代码中想使用,都是有办法使用的。
- 局部变量:在大括号内部定义的变量就是局部变量局部变量的使用范围是比较局限,只能在自己所在的局部范围内使用的。
#include <stdio.h>
int time = 2026; //全局变量
int main()
{
int last = 2025; //局部变量
printf("%d\n", time);
printf("%d\n", last);
return 0;
}
当全局变量和局部变量的名字相同时,局部变量优先使用
#include <stdio.h>
int n = 1000;
int main()
{
int n = 10;
printf("%d\n", n);//打印出10
return 0;
}
全局变量和局部变量在内存中存储在哪里?
内存中有三个区域:栈区、堆区、静态区。
- 1. 局部变量是放在内存的栈区
- 2. 全局变量是放在内存的静态区
- 3. 堆区是用来动态内存管理的

五、 算术操作符(运算符):+、-、*、/、%
5.1 + 和 -
位于操作符俩端的就是它们的操作数,这种操作符也叫双目操作符
#include <stdio.h>
int main()
{
int x = 4 + 18;
int y = 32 - 23;
printf("%d\n", x);
printf("%d\n", y);
return 0;
}5.2 *
#include <stdio.h>
int main()
{
int num = 5;
printf("%d\n", num * num); // 输出 25
return 0;
}
5.3 /
除号的两端如果是整数,执行的是整数除法,得到的结果也是整数。
#include <stdio.h>
int main()
{
float x = 6 / 4;
int y = 6 / 4;
printf("%f\n", x); // 输出 1.000000
printf("%d\n", y); // 输出 1
return 0;
}
俩个运算数至少有一个是浮点数时,进行浮点数除法,得到浮点数的结果
#include <stdio.h>
int main()
{
float x = 6.0 / 4; // 或者写成 6 / 4.0
printf("%f\n", x); // 输出 1.500000
return 0;
}
5.4 %
运算符 % 表示模(余)运算,即返回两个整数相除的余值。这个运算符只用于整数,不能用于浮点 数。
#include <stdio.h>
int main()
{
int x = 6 % 4;
printf("%d",x); //输出2
return 0;
}
负数求模的结果的正负号由第⼀个运算数的正负号决定。
#include <stdio.h>
int main()
{
printf("%d\n", 11 % -5); // 1
printf("%d\n",-11 % -5); // -1
printf("%d\n",-11 % 5); // -1
return 0;
}
六、 赋值操作符:=和复合赋值
在变量创建的时候给⼀个初始值叫初始化,在变量创建好后,再给⼀个值,就是赋值。
int a = 100; //初始化 a = 200; //赋值,这⾥ = 就是赋值操作符
赋值操作符 = 是⼀个随时可以给变量赋值的操作符。
6.1 连续赋值
int a = 3; int b = 4; int c = 8; c = b = a+3; //连续赋值,从右向左依次赋值的。
c语言虽然支持连续赋值,但是代码不易理解,建议拆开来写。
int a = 3; int b = 4; int c = 8; b = a + 3; c = b;
6.2 复合赋值符
复合赋值法即对⼀个数进行自增、自减的操作。
int a = 18; a = a+3; a = a-2; 也可以写成: a += 3; a -= 2;
c语言中常见的复合赋值符如下:
+= -=
*= /= %=
>>= <<=
&= |= ^=
七、 单目操作符:++、--、+、-
7.1 ++和--
++是⼀种自增的操作符,分为前置++和后置++,--是⼀种自减的操作符,也分为前置--和后置--
7.1.1 前置++(前置--)
先+1(-1),后使用
int a = 10;
int b = ++a; //++的操作数是a,是放在a的前⾯的,就是前置++
//a+1后变成11,在使用就是赋值给b,所以a b均为11
printf("a=%d b=%d\n",a , b); 输出 11 11
int a = 10;
int b = --a; //--的操作数是a,是放在a的前⾯的,就是前置--
printf("a=%d b=%d\n",a , b); //输出的结果是:9 9
7.1.2 后置++(后置--)
先使用,后+1(-1)
int a = 10;
int b = a++; //++的操作数是a,是放在a的后⾯的,就是后置++
//先使用a,就是先赋值给b,b得到10,然后再+1,a变成11
printf("a=%d b=%d\n",a , b); //输出 11 10
int a = 10;
int b = a--; //--的操作数是a,是放在a的后⾯的,就是后置--
printf("a=%d b=%d\n",a , b); //输出的结果是:9 10
7.2 + 和 -
+ 是正号,- 是负号,都是单目操作符
运算符 + 对正负值没有影响,是⼀个完全可以省略的运算符,但是写了也不会报错。
运算符 - 用来改变⼀个值的正负号,负数的前面加上 - 就会得到正数,正数的前面加上 - 会得到负 数。
int a = 10;
int b = -a;
int c = -10;
printf("b=%d c=%d\n", b, c); //b和c都是-10
int a = -10;
int b = -a;
printf("b=%d\n", b); //b是10
八、强制类型转换
int a = 3.14; //a的是int类型, 3.14是double类型,两边的类型不⼀致,编译器会报警告 int a = (int)3.14; //意思是将3.14强制类型转换为int类型,这种强制类型转换只取整数部分
一般情况下,不使用强制类型转化实现代码
万不得已情况下,才使用强制类型转化
九、printf 和 scanf 介绍
9.1 printf
9.1.1 基本用法
printf() 的作用是将参数文本输出到屏幕
printf() 不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地方,不会自动换 行。
在输出文本的末尾,添加换行符 \n ,使光标移到下一行的开头。
#include <stdio.h>
int main()
{
printf("hello world");
return 0;
}
int main()
{
printf("hello world\n");
return 0;
}printf() 是在标准库的头文件 <stdio.h> 定义的。使用printf前,必须包含头文件 <stdio.h> 。
9.1.2占位符
占位符,就是这个位置可以用其他值代入。
#include <stdio.h>
int main()
{
printf("there are %d boxes\n", 3);
//输出there are 3 boxes
return 0;
}
%d 就是占位符,这个位置可以用其他值代替。
占位符的第二个字符表示占位的类型,%d表示这里代入的必须是一个整数,如上面中的3。
输出的文本中可以使用多个占位符。
printf() 参数与占位符是一一对应关系,如果有 n 个占位符, printf() 的参数就应该有 n + 1 个。如果参数个数少于对应的占位符, printf() 可能会输出内存中的任意值。
#include <stdio.h>
int main()
{
printf("%s says it is %d o'clock\n", "zhangsan", 18);
//有俩个占位符,第一个%s ,第二个%d
//分别对应 printf() 的第二个(zhangsan)和三个参数(18)
return 0;
}
9.1.3 占位符列举
常见的占位符(加粗为常用的占位符):
- %a :十六进制浮点数,字母输出为小写。
- %a :十六进制浮点数,字母输出为大写。
- %c :字符。//char
- %d :十进制整数(有符号的10进制整数)。// int
- %e :使用科学计数法的浮点数,指数部分的 e 为小写。
- %e :使用科学计数法的浮点数,指数部分的 e 为大写。
- %i :整数,基本等同于 %d 。
- %f :小数(包含 float 类型和 double 类型)。//float %f double - %lf
- %g :6个有效数字的浮点数。整数部分⼀旦超过6位,就会自动转为科学计数法,指数部分的 e 为小写。
- %g :等同于 %g ,唯⼀的区别是指数部分的 e 为大写。
- %hd :十进制 short int 类型。
- %ho :八进制 short int 类型。
- %hx :十六进制 short int 类型。
- %hu :unsigned short int 类型。
- %ld :十进制 long int 类型。
- %lo :八进制 long int类型。
- %lx :十六进制 long int 类型。
- %lu :unsigned long int 类型。
- %lld :十进制 long long int 类型。
- %llo :八进制 long long int 类型。
- %llx :十六进制 long long int 类型。
- %llu :unsigned long long int 类型。
- %le :科学计数法表示的 long double 类型浮点数。
- %lf :long double 类型浮点数。
- %n :已输出的字符串数量。该占位符本身不输出,只将值存储在指定变量之中。
- %o :八进制整数。
- %p :指针(用来打印地址)。
- %s :字符串。
- %u :无符号整数(unsigned int)。
- %x :十六进制整数。
- %zd : size_t 类型。
- %% :输出⼀个百分号。
9.1.4 输出格式
9.1.4.1限定宽度
printf() 允许限定占位符的最小宽度。
%5d 表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。输出的值默认右对齐;想输出左对齐时,在%后面加 - ,即 %-5d
#include <stdio.h>
int main()
{
printf("%5d\n", 123); // 输出为 " 123"
printf("%-5d\n", 123); // 输出为 "123 "
return 0;
}对于小数,会限制所有数字的最小显示宽度。
#include <stdio.h>
int main()
{
printf("%12f\n", 123.45); //输出" 123.450000"
return 0;
}
%12f 表示输出的浮点数最少要占据12位。由于小数的默认显示精度为小数点后6位, 所以 123.45 输出结果的头部会添加2个空格。
9.1.4.2 限定小数位数
当限定小数位数为2时,占位符可写为%.2f
#include <stdio.h>
int main()
{
printf("%.2f\n", 0.5); //输出"0.50"
return 0;
}
与限定宽度结合使用时
#include <stdio.h>
int main()
{
printf("%5.2f\n", 0.5); //输出" 0.50"
return 0;
}
最小宽度和小数位数都可以用 * 表示
#include <stdio.h>
int main()
{
printf("%*.*f\n", 5, 2, 0.5);
// 同于printf("%5.2f\n", 0.5);
return 0;
}
9.1.4.3 输出部分字符串
%s 占位符用来输出字符串,默认是全部输出。如果只想输出开头的部分,可以用 %.ns 指定输出 的长度,其中 n 代表⼀个数字,表示所要输出的长度。
#include <stdio.h>
int main()
{
printf("%.5s\n", "hello world"); //,只输出前五个,"hello"
return 0;
}
9.2 scanf
当我们需要在屏幕上输入时,就可以用 scanf 函数
#include <stdio.h>
int main()
{
int amount = 0;
printf("请输⼊金额:");
scanf("%d", &amount);
printf("金额是:%d\n", amount);
return 0;
}
运行之后是:
请输入金额:5
金额是:5
9.2.1 基本用法
scanf() 函数用于读取用户的键盘输入。
程序运行到这个语句时,会停下来,等待用户从键盘输入。
用户输入数据、按下回车键后, scanf() 就会处理用户的输入,将其存入变量。
它定义在头文件 <stdio.h> 中 。
scanf() 的语法跟 printf() 类似。
int i = 0;
scanf("%d", &i);
%d 占位符与 printf 基本类似,告诉编译器输入的类型
&i 表示用户从键盘输入的整数存入变量 i 。
变量 i 前必须加上 &(指针变量除外),scanf传递的是地址,不是值,scanf将变量 i 的地址指向用户输入的值。
变量是指针变量时,不需要&。
scanf("%d%d%f%f", &x, &y, &a, &b);
//前两个用户输入的是整数,后两个是浮点数(小数),依次放入x,y,a,b。
scanf() 处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等
所以用户输入的数据之间有空格、使用回车键不影响 scanf 解读输入数据
但是使用回车键时,每次按下回车键以后, scanf() 就会开始解读,如果第⼀行匹配第⼀个占位符,那么下次按下回车键时,就会从第⼆个占位符开始解读。
scanf() 处理用户输入的原理是,用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存 进行解读。
解读用户输入时,会从上⼀次解读遗留的第⼀个字符开始,直到读完缓存,或者遇到第⼀个不符合条件的字符为止。
#include <stdio.h>
int main()
{
int x;
float y;
// 输入 " 123.45# 0"
scanf("%d%f", &x, &y);
return 0;
}
scanf() 读取用户输入时, %d 占位符会忽略空格,从 1 处开始获取数据,读到 3 停下来,因为后⾯的 . 不属于整数的有效字符。就是 %d 会读到123。
第二次调用时,scanf() 就会从上⼀次停止解读的地方,继续往下读取。这⼀次读取的收字符是 . ,由于对应的占位符是 %f ,会读取到 .45。后面的 # 不属于浮点数的有效字符,所以会停在这⾥。
9.2.2 scanf 的返回值
scanf() 的返回值是⼀个整数,表示成功读取的变量个数。
如果没有读取任何项,或者匹配失败,则返回 0 。
如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量 eof(-1)。
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
float f = 0.0f;
int x = scanf("%d %d %f", &a, &b, &f); //输入 1 2 3.45 x输出3
printf("a=%d b=%d f=%f\n", a, b, f) //输入 1 2 3 x输出3,f的值是3.0000
printf("x = %d\n", x); //输入 1 ,2 3.45 x输出1,只成功读取a
return 0; //输入 1.1 2 3.14 x输出0,解析第一个失败
}
9.2.3 占位符
scanf() 常用的占位符,与 printf() 的占位符基本⼀致,使用时也基本一致。
在使用占位符时,除 %c 以外,会自动忽略空白字符,如果要强制忽略,在使用%c时,在%c前面加空格,scanf(" %c", &ch)。
%s ,它不能简单地等同于字符串。它从第⼀个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。%s 不会包含空白字符,所以无法用来读取多个单词。scanf() 遇到 %s 占位符时,会在字符串变量末尾存储⼀个空字符 \0 。
9.2.4 赋值忽略符
* 加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃。
scanf("%d%*c%d%*c%d", &year, &month, &day);
//输入 2026-1-16 时-会被丢弃%*c 就是在占位符的百分号后面,加入了赋值忽略符 * ,表示这个占位符没有对应的变量,解读后不必返回。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论