数据类型和变量(上)
前言:
本篇博客,是在《初识 C 语言》的内容的基础上迭代的,由于本篇章节内容较多,因此相关内容,笔者将分篇章逐步更新,后续将持续补充完善 C 语言基础语法的核心知识点
一.数据类型的介绍
C语言提供了丰富的数据类型来描述生活中的各种数据
使用整型类型来描述整数,使用字符类型来描述字符,使用浮点型类型来描述小数
数据类型分为内置类型和自定义类型两类

1.1 字符型
char //character
signed char //有符号的
unsigned char //无符号的
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.3 浮点型
float //单精度浮点数
double //双精度浮点数
long double //C99中引入的类型
1.4 布尔类型
C语言原来并未给布尔值单独设置一个类型,而是使用0表示假,非0表示真
在C99中引入了布尔类型,是专门用来表示真/假的变量
_Bool
布尔类型的使用得包含头文件
布尔类型变量的取值是:true或者false
#include
#include
int main(void)
{
_Bool flag = true;
if (flag)
{
printf("Hello C");
}
return 0;
}
#include
#include
int main(void)
{
_Bool flag = false;
if (flag)
{
printf("Hello C");
}
return 0;
}
_Bool也可写成bool
1.5 各种数据类型的长度
每一种数据类型都有自己的长度,使用不同的数据类型,能够创建出长度不同的变量,变量长度的不同,存储的数据范围就有所差异
1.5.1 sizeof操作符
sizeof是一个关键字,也是操作符,是专门用来计算sizeof的操作符数的类型长度,单位是字节(Byte)
1Byte=8bit(1字节=8比特位)
sizeof操作符的操作数既可以是类型,也可以是变量或者表达式
#include
int main(void)
{
int x = 12;
printf("%zd
", sizeof(int));
printf("%zd
", sizeof(x));
printf("%zd
", sizeof x);
return 0;
}
观察代码,可以发现sizeof的操作数如果不是类型(int),是变量(x)或者表达式的时候,可以省略掉后边的括号
sizeof后边的表达式是不真实参与运算的,根据表达式的类型来得出大小
sizeof的计算结果是size_t类型的
sizeof运算符的返回值,C 语言只规定是无符号整数,并没有规定具体的类型,而是留给系统自己去决定,sizeof到底返回什么类型。不同的系统中,返回值的类型有可能是unsigned int,也有可能是unsigned long,甚至是unsigned long long,对应的printf()占位符分别是%u、%lu和%llu。这样不利于程序的可移植性。C 语言提供了一个解决方法,创造了一个类型别名
size_t,用来统一表示sizeof的返回值类型。对应当前系统的sizeof的返回值类型,可能是unsigned int,也可能是unsigned long long,占位符%zd,就是用来专门打印sizeof的返回类型的
1.5.2 数据类型长度
#include
int main(void)
{
printf("%zd
", sizeof(_Bool));
printf("%zd
", sizeof(char));
printf("%zd
", sizeof(short));
printf("%zd
", sizeof(int));
printf("%zd
", sizeof(long));
printf("%zd
", sizeof(long long));
printf("%zd
", sizeof(float));
printf("%zd
", sizeof(double));
printf("%zd
", sizeof(long double));
return 0;
}
_Bool 1字节
char 1字节
short 2字节
int 4字节
long 4字节/8字节 不同的编译器/系统存在差异
long long 8字节
float 4字节
double 8字节
long double 8字节/16字节 不同的编译器/系统存在差异
1.5.3 sizeof表达式不计算
为了更清晰地显示出sizeof并不参与表达式的运算,而是根据表达式的类型来得出大小,下面我将以代码形式呈现
#include
int main()
{
int n = 10;
short a = 0;
printf("%zd
", sizeof(n = a + 8));
printf("%zd
", sizeof(a = n - 6));
return 0;
}
第一个表达式输出的结果为4,第二个表达式输出的结果是2;因为sizeof并不计算n=a+8表达式的值,它计算的是n的类型int,而int占用 4 字节,同理,第二个表达式也是如此,并不计算a=n-6的表达式,计算的是a的类型short,而short占用 2 字节
#include
int main()
{
int n = 10;
short a = 0;
printf("%zd
", sizeof(n = a + 8));
printf("%zd
", sizeof(a = n - 6));
//验证表达式并未被执行
printf("%d
", n);
printf("%d
", a);
return 0;
}
二.signed和unsigned
C语言中使用signed和unsigned关键字修饰字符型和整型
signed关键字,表示一个类型带有正负号,包括0和负值;unsigned关键字,表示该类型不带有正负号,只能表示零和正整数
对于int类型,默认是带有正负号的,所以int等同于signed int,由于这属于默认情况,关键字signed可省略不写,占位符%d打印的是有符号的整数
int类型也可以不带有正负号,只表示非负整数,这时就必须使用关键字unsigned声明变量,占位符%u打印的是无符号的整数
unsigned int a;//这里的int可省略
//所以可写成
unsigned a;
对于char类型,也可以设置signed和unsigned
signed char c;
unsigned char c;
在修饰char的时候,无法辨别char是signed char,还是unsigned char,它取决于编译器,这与int不同,int是等同于signed int
三.数据类型的取值范围
每一种数据类型都有自己的取值范围,有了丰富的类型,我们就可以在适当的场景下去选择适合的类型,如果要查看当前系统上不同数据类型的极限值:
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 的最大值。
四.变量
C语言中把经常变化的值称为变量,不变的值称为常量
变量创建的语法形式:
data_type name ;
| | | |
数据类型 变量名
示例:
int score;//整型变量
char name;//字符变量
double weight;//浮点型变量
变量名在创建的时候给定初始值,就叫初始化:
int score=92;
int name="lj";
double weight=48.2;
在创建变量的时候,建议变量都显式初始化,因为局部变量是不初始化的,默认是随机值;而一个全局变量也是不初始化的,默认是0
4.2 变量的分类
全局变量:在大括号外部定义的变量
局部变量:在大括号内部定义的变量
两者的区别:
全局变量的使用范围更广,可在整个工程中使用
局部变量的使用范围比较局限,只能在自己所处的局部范围内使用,下面我将用代码示例:
#include
int month = 3;//全局变量
int main(void)
{
{
int age = 12;//局部变量
printf("%d
", age);
printf("%d
", month);
}
printf("%d
", month);
return 0;
}
从代码中我们可看出,全局变量可作用在定义它的整个程序范围内,无论是 main 函数内的内层代码块 {} 中,还是代码块外的 main 函数区域,都能通过 printf 函数访问并打印它的值;而局部变量只可作用在定义它的代码块(函数/大括号)范围内,只有在该代码块内才能通过 printf 函数访问并打印它的值,代码块外无法访问
当局部变量和全局变量同名时,局部变量优先
#include
int month = 3;//全局变量
int main(void)
{
{
int month = 12;//局部变量
printf("%d
", month);
}
return 0;
}
4.3 全局变量和局部变量在内存中存储的位置
局部变量是放在内存的栈区
全局变量是放在内存的静态区
堆区是用来动态内存管理的(如malloc/calloc/realloc/free)








