前面我们已经见识过一个简单的完整 C 语言程序了,下面让我们来认识一下如何在 C 语言中定义变量,以及 C 语言中存在哪些数据类型吧!

前置知识:计算机中都是用二进制 0 和 1 来存放数据的。我们把一个二进制位称作一个比特或比特位,1字节=8比特

1. 定义变量

基本语法如下,和我们日常语言认知中的赋值是一样的思维逻辑。只不过在编程语言中,我们定义一个变量需要告诉编译器它是什么数据类型的。这也是 C/C++ 作为强类型语言的特性之一(变量的数据类型固定,不可以修改数据类型)

plaintext
1
2
3
数据类型 变量名1 = 初始值; // 声明并赋值(声明并定义)
数据类型 变量名2; // 只声明,不赋值(声明和定义分离)
变量名2 = 参数值; // 给变量2赋值

下面给出对应的示例

cpp
1
2
3
int a = 10;  // 声明并赋值
int b; // 只声明,不赋值
b = 20; // 给变量赋值

2. 数据类型

C 语言支持的数据类型如下

2.1 整形

类型存储大小值范围
char1 字节 -128 到 127 0 到 255
unsigned char1 字节 0 到 255
signed char1 字节 -128 到 127
int2 或 4 字节 -32,768 到 32,767 -2,147,483,648 到 2,147,483,647
unsigned int2 或 4 字节 0 到 65,535 0 到 4,294,967,295
short2 字节 -32,768 到 32,767
unsigned short2 字节 0 到 65,535
long4 或 8 字节 -2,147,483,648 到 2,147,483,647 -9,223,372,036,854,775,808 到 +9,223,372,036,854,775,807
unsigned long4 或 8 字节 0 到 4,294,967,295 0 到 +18,446,744,073,709,551,616
long long8 字节 -9,223,372,036,854,775,808 到 +9,223,372,036,854,775,807
unsigned long long8 字节 0 到 +18,446,744,073,709,551,616

上面的所有数据类型,都是整形家族的成员。

longlong long 本质上是 long intlong long int,写的时候可以省略 int

在很多项目 / 库函数源码中,你还会看到下面两种整数类型。他们都是基础类型的一个别名。

类型实际对应的类型操作系统
szie_tunsigned intwindows 11
szie_tlong unsigned intLinux (CentOS8)
sszie_twindows 不支持 windows 11
sszie_tlongLinux (CentOS8)

2.1.1 char 也是整形

char 字符类型也是整形家族的一员,其底层和整形 int 的存放方式是一模一样的,只不过其只占用了 1 个字节。

在 printf 函数中,我们也可以用 %d 来打印 char 类型,最终输出的结果是 char 对应的数字。

在计算机底层中,会使用 ASCII 码表来进行数字和 char 字符之间的转换,将该表粘贴如下

定义字符的时候,我们需要给字符带上单引号作为标识,不能删除单引号,否则会被识别为变量名;也不能用双引号,双引号代表的是字符串。

cpp
1
2
3
char a = 'A'; // 字符A需要带上单引号
char b;
b = 'B';

2.1.2 long 和 int 的区别

这里对 int 和 long 做一定说明:在 32 位操作系统上,int 和 long 都是 4 个字节

这时,你可能和初学的我会有一样的疑惑:既然存放大小一样,能存放的长度也一样,那 int 和 long 有什么区别?

这是因为不同操作系统 / 编译器会有不同的默认策略,在一些很古早的操作系统上,可能会出现下面的情况:

  • int 只有 2 个字节
  • long 是 4 个字节

long 类型的含义,就是告知使用者,不管在什么操作系统上,其至少能达到和 int 一样的长度,或比 int 更长。这样只要我们需要的数据长度在 2~4 个字节之间,那就可以使用 long 来保证该变量一定会用 4 个字节来存储。避免不同平台中 int 的默认策略不同而导致的异常

比如我们有一个占用了 3 字节的整数,在 int 为 4 字节的平台上代码能正常运行,但在 int 只有 2 字节的平台上,就无法正常运行该代码。用 long 就能避免这个问题

当然,如果你所编写的项目对内存占用不敏感,也可以无脑用 long long

在 64 位操作系统下,int 类型是 4 个字节,longlong long 都是 8 个字节。

2.1.3 确定长度的 int 类型

前文提到了:“只要我们需要的数据长度在 2~4 个字节之间,那就可以使用 long 来保证该变量一定会用 4 个字节来存储。”,但实际上这种需要确定长度来存放整形的时候,还有更合适的做法。

C 语言在 ISO C99 中引入了定长整形的数据类型名,使用这一批数据类型来代替 int/long,能确保我们的数字一定会用指定二进制位数来存放。

这一批数据类型和上文提到的 szie_t/sszie_t 一样,都是在不同操作系统环境下对已有的 int/long/short 的重命名,也就是说,底层会根据当前操作系统的不同,来自己帮我们重名这些带具体位数的整形类型,只要我们用了这个数据类型,那么代码不管在任何操作系统上,只要这个操作系统支持 C99 标准,就一定能以符合我们预期的数据长度来存放对应的整形数字。

比如我们在需要 4 个字节(32 位)来存放一个有符号整数数据时,可以用 int32_t 来替代 int/long,这样就能从语言层面彻底确保我们的数字会用 32 个二进制位来存储。

更多信息可以参考博客:C 语言 —— int32_t uint32_t 及 size_t

2.3 浮点型

所谓浮点型,即 C 语言中的小数。

下表中的 E 代表是科学计数法,E+38 = 1038,E-38 = 10-38

类型存储大小值范围精度
float4 字节 1.2E-38 到 3.4E+386 位有效位
double8 字节 2.3E-308 到 1.7E+30815 位有效位
long double16 字节 3.4E-4932 到 1.1E+493219 位有效位

在库函数头文件 <float.h> 存放了浮点数的最大值和最小值的宏。这里我们采用 %E 科学计数法的方式打印出浮点数 float 类型的最大值和最小值。

cpp
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <float.h>

int main()
{
printf("float 存储最大字节数 : %d \n", sizeof(float));
printf("float 最小值: %E\n", FLT_MIN );
printf("float 最大值: %E\n", FLT_MAX );
printf("精度值: %d\n", FLT_DIG );
return 0;
}

上述代码输出结果如下

plaintext
1
2
3
4
float 存储最大字节数 : 4
float 最小值: 1.175494E-38
float 最大值: 3.402823E+38
精度值: 6

2.4 指针类型

指针类型是 C/C++ 中比较难懂的一环,这里我们暂时只学习基础的指针变量声明。对指针的深入学习会有专门的文档。

指针的基本格式就是 *,只要在原有数据类型后加一个 *,就代表是该类型的指针。在原有的变量前面加上取地址符号 &,就代表获取该变量的地址(指针)

plaintext
1
2
3
int a = 10;
// ptr就是一个int*的指针;&a代表获取a变量的地址,赋值给ptr指针
int* ptr = &a;

要想使用指针来访问变量 a 中的数据,我们需要用到解引用,符号也是 *

plaintext
1
int b = *ptr; // 通过解引用,获取到ptr指针指向的地址中的值,赋值给b

执行完毕这个代码后,变量 b 就获取到了 ptr 指针指向的地址中的值,即变量 a 的值。

指针变量中,星号 * 的个数代表指针的等级,一个 * 就代表是一级指针,两个 * 就代表是二级指针,依此类推。不同等级的指针具体的区别,会在指针章节再谈,本文档只是让大家认识数据类型的。

2.5 bool 类型

C/C++ 中还有一个特殊的类型,布尔类型,即 bool 类型。

这个类型只有两个预定义的值,分别是 false 和 true,聪明的你肯定已经明白它的作用了。主要就是用于函数的返回值,亦或者是用做 flag 标记变量,来标定真和假的。

比如:通过函数判断一个字符串是否为一个数字,是返回 true,不是返回 false

在 C 语言中使用这个变量需要引用头文件 stdbool.h,代码示例如下

c
1
2
3
4
5
6
7
8
#include <stdbool.h>

int main()
{
bool a = true; // 真
bool b = false; // 假
return 0;
}

该变量大小为 1 个字节,也能算作整形家族的一员(底层其实就是一个宏,分别对应 0 和 1 两个数字)

头文件 stdbool.h 非常短,这里顺带将完整的内容粘贴出来。其中出现了 define 和 ifdef 这些宏定义语法,在本站后文中都会介绍到。我们只需要关注核心:可以看到,true 是 0,false 是 1,二者就是数字罢了。

#define 名字 内容 后文出现该名字的位置,全都会被替换成内容
#define true 0 引用头文件后,后文出现的所有 true 都会在预编译阶段替换成 0;

c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//
// stdbool.h
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// The C Standard Library <stdbool.h> header.
//
#ifndef _STDBOOL
#define _STDBOOL

#define __bool_true_false_are_defined 1

#ifndef __cplusplus

#define bool _Bool
#define false 0
#define true 1

#endif /* __cplusplus */

#endif /* _STDBOOL */

3.const 关键字

在继续介绍其他数据类型之前,需要先带大家认识一下 const 关键字。

这个关键字的作用是将数据类型添加常量属性,被 const 关键字修饰后的属性,将具有常量属性,即不可以被修改

c
1
const int a = 10; // 常量变量,a不可以被修改

当我们尝试修改这个变量的时候,会报错,无法通过编译。

c
1
2
const int a = 10; // 常量变量,a不可以被修改
a = 10; // 错误!修改常量会报错

后文将介绍数组类型和字符串类型,请继续阅读本专栏。