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

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

1.定义变量

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

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

下面给出对应的示例

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字符之间的转换,将该表粘贴如下

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

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类型的最大值和最小值。

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;
}

上述代码输出结果如下

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

2.4 指针类型

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

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

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

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

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

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

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

2.5 bool类型

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

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

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

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

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;

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关键字修饰后的属性,将具有常量属性,即不可以被修改

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

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

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

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