1. 数据类型介绍
C语言的基本数据类型包括整型、浮点型和字符型。整型用于存储整数,浮点型用于存储小数,字符型用于存储单个字符。下面盘点一下C语言提供的各种数据类型,本章节主要探讨内置数据类型。
1.1、字符型
字符型(char)是C语言中用于存储单个字符的数据类型,占用1字节内存空间。字符型变量实际存储的是对应字符的ASCII码值(整数),因此可以直接参与整数运算。
char
[signed] char
unsigned char
char ch1 = 'A'; // 直接赋值字符
char ch2 = 65; // 使用ASCII码赋值(十进制)
char ch3 = '\\x41'; // 使用ASCII码赋值(十六进制)
char ch4 = '\\101'; // 使用ASCII码赋值(八进制)
1.2、整型
//短整型
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.2.1类型修饰符
signed
- 显式声明为有符号整型(默认情况下,int、short、long等为有符号)。
- 示例:signed int i = -10;
unsigned
- 声明为无符号整型,只能表示非负数。
- 示例:unsigned int j = 10;
- 无符号整型只能表示非负数,范围是相应有符号整型的非负部分的两倍。
1.3、浮点型
float
double
long double
1.3.1、浮点型数据类型
C语言中的浮点型用于表示小数或实数,主要包含以下三种类型:
- float:单精度浮点型,占用4字节(32位),精度约6-7位小数。
- double:双精度浮点型,占用8字节(64位),精度约15-16位小数。
- long double:扩展精度浮点型,通常占用10字节(80位)或更多,具体取决于编译器。
1.3.2、浮点型声明与初始化
浮点型变量可以通过以下方式声明和初始化:
float a = 3.14f; // 注意后缀'f'表示float类型
double b = 2.71828; // 默认浮点常量是double类型
long double c = 1.41421356L; // 后缀'L'表示long double
1.3.3、浮点型常量表示
浮点型常量支持科学计数法:
- 十进制形式:3.14、0.001
- 指数形式:1.23e-4(表示1.23×10⁻⁴)
1.3.4、浮点型精度与范围
- float:范围约±1.2×10⁻³⁸到±3.4×10³⁸。
- double:范围约±2.3×10⁻³⁰⁸到±1.7×10³⁰⁸。
- long double:范围通常更大,具体取决于实现。
1.3.5、浮点型的注意事项
浮点型运算可能存在精度误差,例如:
float x = 0.1f + 0.2f;
printf("%.20f\\n", x); // 输出可能不是精确的0.3
比较浮点数时应使用误差范围(如fabs(a – b) < 1e-6)。
1.3.6、常用数学函数
C标准库<math.h>提供浮点运算函数:
#include <math.h>
double sqrt(double x); // 平方根
double pow(double x, double y); // 幂运算
double sin(double x); // 三角函数
1.4、布尔类型
C语言原来并没有为布尔值单独设置⼀个类型,而是使用整数 在 C99 中也引入了 布尔类型,是专门表示真假的。从C99标准开始,C语言引入了_Bool关键字和<stdbool.h>头文件,提供了更直观的布尔类型支持。
#include <stdbool.h>
bool flag = true; // 定义布尔变量并初始化为真
flag = false; // 修改为假
布尔值可以参与逻辑运算:
bool a = true, b = false;
bool c = a && b; // 逻辑与
bool d = a || b; // 逻辑或
bool e = !a; // 逻辑非
隐式类型转换
当其他类型转换为布尔类型时,零值转为false,非零值转为true:
_Bool b = 10; // b的值为1(true)
b = 0.0; // b的值为0(false)
1.5、各种数据类型的长度
每一种数据类型都有自己的长度,使用不同的数据类型,能够创建出长度不同的变量,变量长度的不 同,存储的数据范围就有所差异
1.5.1、sizeof操作符
sizeof 是⼀个关键字,也是操作符,专门是用来计算sizeof操作符数的类型长度的,单位是字节。 sizeof 操作符的操作数可以是类型,也可是变量或者表达式。它可以在编译时求值,返回一个 size_t 类型的无符号整数。
可以直接对数据类型使用 sizeof,例如:
size_t int_size = sizeof(int); // 返回 int 类型的大小
可以对变量使用 sizeof,无需括号(除非是类型名):
int x;
size_t x_size = sizeof x; // 返回变量 x 的大小
对数组使用 sizeof 会返回整个数组的字节大小:
int arr[10];
size_t arr_size = sizeof(arr); // 返回 10 * sizeof(int)
对指针使用 sizeof 返回指针本身的大小(通常为 4 或 8 字节,取决于系统):
int *ptr;
size_t ptr_size = sizeof(ptr); // 返回指针的大小,而非指向的数据大小
sizeof中表达式不计算
#include <stdio.h>
int main()
{
short s = 2;
int b = 10;
printf("%d\\n", sizeof(b = b + 1));
//表达式b = b + 1的类型为int(因b是int类型),所以sizeof返回int的字节数(通常为4)
printf("s = %d\\n", s);
return 0;
}
2. signed 和unsigned
C语言使用signed 和 unsigned 关键字修饰字符型和整型类型的。signed 关键字,表示⼀个类型带有正负号,包含负值; unsigned 关键字,表示该类型不带有正负号,只能表示零和正整数。 对于 int 类型,默认是带有正负号的,也就是说由于这是默认情况,关键字 int 等同于 signed int 。 signed ⼀般都省略不写,但是写了也不算错。
signed int a;
//等同于int a;
可以将 int 类型声明为无符号形式,仅表示非负整数,此时需使用 unsigned 关键字。使用 unsigned 声明整型变量的优势在于:相同内存空间下,可表示的最大整数值将扩大一倍。
unsigned int a;
unsigned int里面的int可以省略,写成下面这样:
unsigned a
字符类型 char 也可以设置 signed 和 unsigned 。
signed char c;
//范围为-128 到127
unsigned char c;
// 范围为0到255
需要注意的是,C语言规定char类型默认是否带符号取决于当前系统。这意味着char并不等同于unsigned char。这一点与int不同,int默认等同于signed int。
3. 数据类型的取值范围
C语言中的基本数据类型及其取值范围主要取决于编译器和系统架构(如32位或64位)。以下是常见数据类型的典型取值范围:
3.1、整型
char
- 大小:1字节(8位)
- 有符号:-128 到 127
- 无符号:0 到 255
short
- 大小:2字节(16位)
- 有符号:-32,768 到 32,767
- 无符号:0 到 65,535
int
- 大小:通常4字节(32位)
- 有符号:-2,147,483,648 到 2,147,483,647
- 无符号:0 到 4,294,967,295
long
- 大小:4字节(32位系统)或8字节(64位系统)
- 32位有符号:-2,147,483,648 到 2,147,483,647
- 64位有符号:-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
- 无符号:0 到 18,446,744,073,709,551,615(64位)
long long
- 大小:8字节(64位)
- 有符号:-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
- 无符号:0 到 18,446,744,073,709,551,615
3.2、浮点型
float
- 大小:4字节(32位)
- 范围:约 1.2E-38 到 3.4E+38
- 精度:6-7位小数
double
- 大小:8字节(64位)
- 范围:约 2.3E-308 到 1.7E+308
- 精度:15-16位小数
long double
- 大小:通常10字节(80位)或更高
- 范围:更大,具体取决于实现
3.3、获取具体值的代码示例
可以使用 <limits.h> 和 <float.h> 头文件获取具体编译环境下的取值范围:
#include <stdio.h>
#include <limits.h>
#include <float.h>
int main() {
printf("char range: %d to %d\\n", CHAR_MIN, CHAR_MAX);
printf("int range: %d to %d\\n", INT_MIN, INT_MAX);
printf("float range: %e to %e\\n", FLT_MIN, FLT_MAX);
return 0;
}
3.4、注意事项
- 实际取值范围可能因编译器或平台不同而变化,建议使用标准库宏(如 INT_MAX)获取具体值。
- 无符号类型的最小值始终为 0,最大值可通过 UINT_MAX 等宏获取。
4. 变量
4.1、变量的创建
了解清楚了类型,我们使用类型做什么呢?类型是用来创建变量的。什么是变量呢?C语言中把经常变化的值称为变量,不变的值称为常量。
data_type name;
| |
| |
数据类型 变量名
int age; //整型变量
char ch; //字符变量
double weight; //浮点型变量
变量在创建的时候就给⼀个初始值,就叫初始化。
int age = 18;
char ch = 'w';
double weight = 48.0;
unsigned int height = 100;
4.2、变量的分类
-
全局变量:定义在大括号外的变量称为全局变量。其作用域覆盖整个工程,可以在任何地方调用使用。
- 局部变量:定义在大括号内的变量称为局部变量。其作用范围仅限于定义它的代码块内部,无法在外部使用。
#include <stdio.h>
int global = 2023;//全局变量
int main()
{
int local = 2018;//局部变量
printf("%d\\n", local);
printf("%d\\n", global);
return 0;
}
#include <stdio.h>
int n = 1000;
int main()
{
int n = 10;
printf("%d\\n" n);//打印的结果是多少呢?
return 0;
}
如果局部和全局变量同名的时候,局部变量优先使用。
在C/C++语言中,变量根据作用域不同存储于内存的不同区域:
5. 算术操作符:+、-、*、/、%
5.1、算术操作符概述
C语言提供五种基本算术操作符,用于执行数值计算:
- +:加法
- -:减法
- *:乘法
- /:除法
- %:取模(求余数)
5.2、加法操作符 +
用于计算两个操作数的和。
int result = 5 + 3; // result = 8
支持整数和浮点数运算,结果为操作数类型。
5.3、减法操作符 –
用于计算两个操作数的差,或表示负数。
int diff = 10 – 4; // diff = 6
int neg = -5; // neg = -5
5.4、乘法操作符 *
用于计算两个操作数的乘积。
int product = 6 * 7; // product = 42
5.5、除法操作符 /
执行除法运算,结果取决于操作数类型:
- 整数除法:截断小数部分(向零取整)。
- 浮点数除法:保留小数部分。
int div_int = 10 / 3; // div_int = 3
float div_float = 10.0 / 3.0; // div_float ≈ 3.333…
5.6、取模操作符 %
返回整数除法的余数,仅适用于整数类型。
int remainder = 10 % 3; // remainder = 1
若操作数为负数,结果符号依赖编译器实现(通常与被除数一致)。
5.7、优先级与结合性
算术操作符的优先级从高到低:
使用括号可显式控制运算顺序:
int value = (2 + 3) * 4; // value = 20
5.8、注意事项
- 整数除以零导致运行时错误。
- 浮点数除以零可能返回 INF(无穷大)或 NaN(非数字)。
- 取模操作符不可用于浮点数。
6. 赋值操作符:=和复合赋值
6.1、基础赋值操作符(=)
在 C 语言中,= 是基础的赋值操作符,用于将右侧表达式的值赋给左侧的变量。语法形式为:
variable = expression;
赋值操作符的优先级较低,通常结合方向为从右向左。例如:
int a, b;
a = 5; // 将 5 赋给变量 a
b = a + 3; // 计算 a + 3 并将结果赋给 b
6.2、复合赋值操作符
复合赋值操作符结合了赋值与算术/位运算,简化代码并提升可读性。常见形式包括:
- +=(加法赋值)
- -=(减法赋值)
- *=(乘法赋值)
- /=(除法赋值)
- %=(取模赋值)
语法形式为:
variable op= expression;
// 等价于 variable = variable op (expression)
示例:
int x = 10;
x += 5; // x = x + 5 → 15
x *= 2; // x = x * 2 → 30
6.3、注意事项
- 右结合性:复合赋值操作符从右向左计算。例如 a += b *= 2 等价于 a += (b *= 2)。
- 表达式求值顺序:右侧表达式会先计算,再与左侧变量运算。
- 类型匹配:需确保左右操作数类型兼容,否则可能触发隐式类型转换或警告。
7. 单目操作符:++、–、+、
7.1、自增操作符 ++
用于将操作数的值增加1,分为前缀(++a)和后缀(a++)两种形式。
-
前缀形式:先自增,再使用变量的值。计算口诀:先+1,后使用;
int a = 5;
int b = ++a; // a先变为6,再赋值给b
printf("%d, %d", a, b); // 输出: 6, 6 -
后缀形式:先使用变量的值,再自增。计算口诀:先使用,后+1
int a = 5;
int b = a++; // b赋值为5,a随后变为6
printf("%d, %d", a, b); // 输出: 6, 5
7.2、自减操作符 —
用于将操作数的值减少1,同样分为前缀(–a)和后缀(a–)。
-
前缀形式:先自减,再使用变量。计算口诀:先-1,后使用。
int a = 5;
int b = –a; // a变为4,b赋值为4 -
后缀形式:先使用变量,再自减。计算口诀:先使用,后-1
int a = 5;
int b = a–; // b赋值为5,a变为4
7.3、正号操作符 +
表示数值的正值(通常省略),但可用于强制类型转换或明确表达式语义。
int a = -10;
int b = +a; // b为-10(无实际变化)
7.4、负号操作符 –
对操作数取负值。
int a = 10;
int b = -a; // b为-10
7.5、注意事项
副作用:++和–会修改操作数的值,避免在同一个表达式中多次使用同一变量的自增/自减。
int a = 5;
int b = a++ + a++; // 未定义行为
类型限制:++和–仅适用于变量,不能用于常量或表达式(如5++非法)。
结合性:单目操作符从右向左结合。例如,-+-a等价于- (+ (-a))。
8. 强制类型转换
int a = 3.14;//a的是int类型, 3.14是double类型,两边的类型不⼀致,编译器会报警告
为了消除这个警告,我们可以使⽤强制类型转换:
int a = (int)3.14;//意思是将3.14强制类型转换为int类型,这种强制类型转换只取整数部分
我们使用强制类型转换都是万不得已的时候使用,如果不需要强制类型转化 就能实现代码,这样自然更好的
9. scanf和printf介绍
9.1、printf
9.1.1、基本用法:
printf是C语言标准库中的输出函数,用于向标准输出(如屏幕)打印格式化数据。它名字里的f代表format(格式化),表示可以定制输出文本的格式。
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
printf() 是在标准库的头⽂件 stdio.h 定义的。使用这个函数之前,必须在源码文件头部引入这 个头文件。
9.1.2、占位符
所谓“占位符”,就是这个位置可以⽤其他值代入。
#include <stdio.h>
int main()
{
printf("There are %d apples\\n", 3);
return 0;
}
在上面的示例中,"There are %d apples\\n"是输出文本,其中的%d作为占位符,表示该位置将被其他值替换。占位符的首字符始终为百分号%,第二个字符则代表占位符的类型。例如%d表示此处必须填入一个整数值。
常用的占位符除了%d之外,还有%s用于表示字符串的插入。
#include <stdio.h>
int main()
{
printf("%s will come tonight\\n", "zhangsan");
return 0
}
9.1.3、占位符列举
以下按字母顺序列出 C 语言中常用的 printf() 占位符,每种占位符对应不同的数据类型:
- %a:十六进制浮点数(字母小写)
- %A:十六进制浮点数(字母大写)
- %c:字符
- %d:十进制整数
- %e:科学计数法浮点数(指数部分小写 e)
- %E:科学计数法浮点数(指数部分大写 E)
- %f:小数(包含 float 和 double 类型)
- %g:6 位有效数字浮点数(自动转为科学计数法时指数部分小写 e)
- %G:同 %g(指数部分大写 E)
- %hd:十进制 short int 类型
- %ho:八进制 short int 类型
- %hx:十六进制 short int 类型
- %hu:unsigned short int 类型
- %i:整数(基本等同于 %d)
- %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、限定占位符宽度
int num = 42;
printf("%5d", num); // 输出 " 42"(右对齐,宽度5)
printf("%-5d", num); // 输出 "42 "(左对齐,宽度5)
在上面的示例中,%5d表示该占位符的宽度至少为5个字符。如果数值不足5位,系统会在值的前面添加空格进行填充。默认情况下,输出内容采用右对齐方式,因此会在数字前添加空格;如需改为左对齐(在数字后添加空格),只需在占位符的%后添加-符号即可。
小数部分的限定符用于控制所有数字的最小显示宽度。
// 输出 " 123.450000"
#include <stdio.h>
int main()
{
printf("%12f\\n", 123.45);
return 0;
}
在上面的示例中,%12f表示输出的浮点数至少占据12位宽度。由于默认显示精度为小数点后6位,因此输出23.45时,结果前会添加2个空格。
9.1.5、总是显示正负号
默认情况下, printf() 不对正数显⽰ + 号,只对负数显示号。如果想让正数也输出 + 号,可 以在占位符的 % 后⾯加⼀个 + 。
#include <stdio.h>
int main()
{
printf("%+d\\n", 12); // 输出 +12
printf("%+d\\n", -12); // 输出 -12
return 0;
}
9.1.6、限定小数位数
如需控制小数位数,可通过格式化占位符实现。例如,保留两位小数可使用"%.2f"格式。
// 输出Number is 0.50
#include <stdio.h>
int main()
{
printf("Number is %.2f\\n", 0.5);
return 0;
}
这种写法可以与限定宽度占位符,结合使用。
// 输出为" 0.50"
#include <stdio.h>
int main()
{
printf("%6.2f\\n", 0.5);
return 0;
}
最小宽度和小数位数这两个参数,都可以使用*来指定,并通过printf()函数进行动态传入。
#include <stdio.h>
int main()
{
printf("%*.*f\\n", 6, 2, 0.5);
return 0;
}
//等同于printf("%6.2f\\n", 0.5);
9.1.6、输出部分字符串
%s 占位符用于输出字符串,默认会显示完整内容。若只需显示开头部分,可使用%.[m]s格式,其中 m 代表要显示的字符数。
// 输出hello
#include <stdio.h>
int main()
{
printf("%.5s\\n", "hello world");
return 0;
}
9.2、scanf
9.2.1、scanf 基本用法
scanf 是 C 语言中用于从标准输入(如键盘)读取数据的函数,其基本语法为:
scanf("%d", &i);
它的第⼀个参数是⼀个格式字符串,里面会放置占位符(与编译器如何解读用户的输入,需要提取的数据是什么类型。 这是因为C语言的数据都是有类型的,(与printf() 的占位符基本一致),scanf() 必须提前知道用户输入的数据类型,才能处理数据。 它的其余参数就是存放用户输入的变量,格式字符串里面有多少个占位符,就有多少个变量。 上面示例中, scanf() 的第一个参数 %d ,表示用户输入的应该是一个整数。 %d 就是⼀个占位 符, % 是占位符的标志, d 表示整数。第⼆个参数 &i 表示,将用户从键盘输入的整数存入变量 i 。
示例:
int num;
scanf("%d", &num); // 读取一个整数并存入 num
9.2.2、scanf 返回值
scanf 返回成功匹配并赋值的输入项数量。若输入与格式不匹配或遇到文件结束符(如 Ctrl+D/Ctrl+Z),返回 EOF(通常为 -1)。
示例:
int a, b;
int count = scanf("%d %d", &a, &b);
// 若输入 "10 20",count 为 2;若输入 "10 abc",count 为 1。
9.2.3、常用占位符
scanf 的占位符需与变量类型严格匹配:
%d | int | scanf("%d", &x); |
%f | float | scanf("%f", &y); |
%lf | double | scanf("%lf", &z); |
%c | char | scanf("%c", &c); |
%s | 字符串(char[]) | scanf("%s", str); |
%u | unsigned int | scanf("%u", &u); |
%x | 十六进制整数 | scanf("%x", &h); |
注意事项:
- %s 读取字符串时遇到空格或换行符停止,可能引发缓冲区溢出(建议用 fgets 替代)。
- %lf 是 double 类型专用,float 需用 %f。
9.2.4、赋值忽略符 *
在占位符前加 * 可忽略输入项(不赋值给变量),常用于跳过不需要的数据。
示例:跳过输入中的日期部分:
int year, month;
scanf("%d-%*d-%d", &year, &month); // 输入 "2023-05-15",month 为 15,中间 05 被忽略
评论前必须登录!
注册