探索C语言的数据类型:解密编程世界的核心秘密

✨✨ 欢迎大家来到贝蒂大讲堂✨✨

🎈🎈养成好习惯,先赞后看哦~🎈🎈

所属专栏:C语言学习
贝蒂的主页:Betty‘s blog

1. 常量与变量

1.1 常量

(1) 常量的概念

常量顾名思义就是无法改变的量,比如一周有7天,一天有24小时,这些都是无法改变的量。

(2) 常量的分类

  1. 整数常量:1,2,3,-1,-2等
  2. 小数常量:小数在C语言中有两种表示形式,一种是直接表示如:1.1,1.3,3.14,200.2 还有一种便是科学表示法如2.1433×102,用C语言表示就是2.1433e2或者2.1433E2。
  3. 字符常量:因为字符在内存中是以ASCII码值存储,所以字符也是常量,如'a','b','\n','\111'等。
  4. 标识常量:也就是用宏定义的常量,它常常大写放在开头,语法形式也特别简单

#define 标识符号名 常量数据

#include <stdio.h>
#define MAX 10
//后续代码会将MAX替换为10
int main()
{
	int a = MAX;
	return 0;
}
  1. 枚举常量:是由枚举类型代表的常量,这个会在之后的章节详细为大家讲解。

(3) 二进制,八进制,十六进制

  • 二进制:二进制在计算领域应用广泛,它的数字每⼀位都是0~1的数字组成,并且满2进1
  • 八进制,与二进制类似,由数字0~7组成,并且满8进1
  • 十六进制,由0~9,a~f代表10~15组成,并且满16进1.

在C语言中,八进制是以0开头表示,十六进制以0x开头,输出占位符分别为%o,%x。

int main()
{
	int a = 0111;//八进制
	int b = 0x43a;//十六进制
	printf("八进制输出%o 十进制输出%d\n", a, a);
	printf("十六进制输出%x 十进制输出%d\n", b, b);
	return 0;
}

输出结果:

(4) 二进制与其他进制之间的转换

  1. 二进制转十进制,按权重直接转换,假设二进制的1001,转换如图

  1. 二进制转八进制,从右往左每三个二进制转换为一个八进制位,最后不够直接转为八进制。以二进制11010111为例

  1. 二进制转十六进制与转八进制类似,从右往左每四个二进制转换为一个十六进制位,最后不够直接转为十六进制进制。以二进制11010111为例

  1. 十进制转换为二进制,可以利用除法取余。如图为63转换为二进制的过程

1.2 变量

(1) 变量的概念

变量顾名思义就是不断改变的量,如我们的年龄,体重,身高等都可以称之为变量

(2) 变量的命名规则

在C语言中有一套严格的命名规则,如下

  1. 变量名的开头必须是字母或下划线,不能是数字。
  2. 变量名中的字母是区分大小写的。
  3. 变量名绝对不可以是C语言关键字。
  4. 变量名中不能有空格。这个可以这样理解:因为上面我们说过,变量名是字母、数字、下划线的组合,没有空格这一项。

(3) 局部变量和全局变量

​ 全局变量简单来说就是可以作用于全局的变量,在整个编程中都可以使用。而局部变量就是只能在特定区域使用的变量。

#include <stdio.h>
int a = 1;
//全局变量,任何地方都能使用
int main()
{
	int b = 2;
       //局部变量,只能在main函数中使用
	return 0;
}

(4) 局部优先原则

当局部变量和全局变量同名的时候,局部变量优先使⽤!

我们可以看看这段代码

#include <stdio.h>
int a = 1;//全局变量
int main()
{
	int a = 2;//局部变量
	printf("%d ", a);//输出什么?
	return 0;
}

输出结果:

2. 数据类型

2.1 介绍

在我们日常生活中我们描述物品可以描述它的形状,大小,颜色,气味……,但是对于计算机而言,存储的数据都是以二进制的形式,那么它又该区别这些数据呢?因此,C语言就为大家提供了丰富的数据类型,方便大家描述不同的数据,比如说描述整数的short,int……,描述字符的char,小数的float,double等等,而在数据类型主要分为两种:一种是系统自带的内置类型,另一种就是可以自定义的自定义类型,本章就重点围绕数据类型中的内置类型来为大家详细谈谈。

以下是常见的一些数据类型:

  • 顾名思义整型是用来描述整数的,浮点型是用来描述小数的,具体细分与其表示的精度有关。
  • 每次声明一个变量时都需要声明其类型。
  • 其中因为字符在内存中存储是以ASCII码的形式,所以也算作整型。
  • C99中还新增了一种数据类型用来表示正(true)误(false)的布尔类型(_Bool),使用它必须包含头文件<stdbool.h>。

2.2 举例使用

#include<stdbool.h>
int main()
{
	char ch = 'a';//字符型
	int a = 1;//整形
	float b = 1.0f;//单精度浮点型
	double c = 2.1;//双精度浮点型
	bool m = false;//布尔类型
	return 0;
}

2.3 signed和unsigned

在C语⾔中使⽤ signed(有符号) 和 unsigned(无符号) 关键字修饰字符型整型类型。signed表示被修饰的关键字有正负之分,unsigned表示被修饰的关键字无负数,其中当关键字不经修饰时默认为有符号类型。

int main()
{
	signed int a = 10;
	//等价于int a=10
	signed char ch = 'a';
	//等价于 char ch='a';
	unsigned  int m = 1;
	unsigned  char n = 'b';
	return 0;
}

2.4 强制类型转换

在C语言中,不同类型的值是无法相互赋值的,否则可能发生意料之外的结果。比如说:“浮点型的小数无法赋值给整型。”但是C语言中有一个操作符,能把变量从一种类型转换为另一种数据类型。这就是我们的强制类型转换操作符。

语法形式很简单,形式如下:

(类型) 数据

代码示例:

#include <stdio.h>
int main()
{
	int a = 10;//正确
	int b = 3.1;
	//b是整型,3.1是浮点型,错误
	int c = (int)3.1;//强制类型转换后正确
	printf("%d ", c);
	return 0;
}

2.5 数据类型的大小

(1) sizeof操作符

sizeof 是⼀个关键字,也是操作符,专⻔是⽤来计算sizeof的操作符数的类型⻓度的,单位是字节。sizeof 操作符的操作数可以是类型,也可是变量或者表达式。

sizeof( 类型 )
sizeof 表达式

  • sizeof 的操作数如果不是类型,是表达式或变量的时候,可以省略掉后边的括号的。
  • sizeof 后边的表达式是不真实参与运算的,根据表达式的类型来得出⼤⼩。
  • sizeof 的计算结果是 size_t 类型的。
#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 + 1));
	printf("%zd\n", sizeof 3 + 1);//表达式可以省略
	return 0;
}
  • size_t的占位符为%zd,写成%d也是可以的

特别注意:

sizeof 运算符的返回值,C语⾔只规定是⽆符号整数,并没有规定具体的类型,⽽是留给系统⾃⼰去决定, sizeof 到底返回什么类型。不同的系统中,返回值的类型有可能是unsigned int ,也有可能是 unsigned long ,甚⾄是 unsigned long long ,对应的 printf() 占位符分别是 %u 、 %lu 和 %llu 。这样不利于程序的可移植性。C语⾔提供了⼀个解决⽅法,创造了⼀个类型别名 size_t ,⽤来统⼀表⽰ sizeof 的返回值类型。对应当前系统的 sizeof 的返回值类型,可能是 unsigned int ,也可能是unsigned long long 。

其中在VS2022 ×86 环境中是unsigned int

其中在VS2022 ×64 环境中是unsigned long long

(2) 计算大小

在我们知道sizeof的用法之后,我们就可以计算不能数据类型的大小,单位为字节(byte)。

#include <stdio.h>
int main()

{
	printf("%zd\n", sizeof(char));
	printf("%zd\n", sizeof(_Bool));
	printf("%zd\n", sizeof(short));
	printf("%zd\n", sizeof(int));
	printf("%zd\n", sizeof(long));
	printf("%zd\n", sizeof(long long));
	printf("%zd\n", sizeof(float));
	printf("%zd\n", sizeof(double));
	printf("%zd\n", sizeof(long double));
	return 0;
}

输出结果:

(3) 表达式不计算

#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处理掉了,所以在运⾏期间就不会执⾏表达式

2.6 数据类型的范围

因为不同的数据表示范围,整型短整型,整型,长整型......,浮点数分为单精度浮点型,双精度浮点型。为了方便大家熟练掌握每个数据类型的应用,下表展现了常见数据类型的范围

数据类型 大小(byte) 范围
char(signed char) 1 -128~127
unsigned char 1 0~255
short int(signed short int) 2 -32,768~32,767
unsigned short int 2 0~65,535
int(signed int) 4 -2,147,483,648~2,147,483,647(-231 ~ 231-1)
unsigned int 4 0~4,294,967,295
long int(signed long int) 4 -2,147,483,648~2,147,483,647(-231 ~ 231-1)
unsigned long int 4 0~4,294,967,295
float 4 -3.4x10-38 ~ 3.4x1038
double 8 -1.7x10-308 ~ 1.7x10308

3. 基本运算符

3.1 赋值

在变量创建的时候给⼀个初始值叫初始化,在变量创建好后,再给⼀个值,这叫赋值。而=就是一种简单赋值运算符

int main()
{
	int a = 1;//给a赋值为1
         int t = m=1;//C语言可以这样连续赋值
	char b = 'a';//为b赋值字符a
	float c = 1.0f;//1.0为double类型
	//加f转换为float型
	return 0;
}

3.2 加(+)减(-)乘(*)

C语言中的加减乘与数学中的加减乘类似,直接类比使用就行。

int main()
{
	int a = 1;
	int b = 2;
	int c = 1 + 2;//加法
	int m = 1 - 2;//减法
	int n = 1 * 2;//乘法
	printf("1+2=%d\n1-2=%d\n1*2=%d\n", c, m, n);
	return 0;
}

输出结果:

3.3 除号(/)和取模(%)

除号的两端如果是整数,执⾏的是整数除法,得到的结果也是整数(舍去余数)。

如果两端有一个是小数,执行的小数除法,得到小数。

int main()
{
	int a = 1;
	int b = 2;
	int c = 1 / 2;
	double d = 1.0 / 2;
	printf("%d %lf\n", c, d);
	return 0;
}

输出结果:

运算符 % 表⽰求模运算,即返回两个整数相除的余值。这个运算符只能⽤于整数,不能⽤于浮点数。

负数求模的规则是,结果的正负号由第⼀个运算数的正负号决定。

int main()
{
	int a = 1;
	int b = 2;
	int m = 1 % 2;
	int n = -1 % 2;//负数在前
	int t = 1 % 2;//负数在后
	printf("%d %d %d\n",m,n,t);
	return 0;
}

输出结果:

3.4 自增与自减

++是⼀种⾃增的操作符,⼜分为前置++和后置++,--是⼀种⾃减的操作符,也分为前置--和后置--。

int main()
{
	int a = 1;
	a++;
	printf("a=%d\n", a);
	++a;
	printf("a=%d\n", a);
	a--;
	printf("a=%d\n", a);
	--a;
	printf("a=%d\n", a);
	return 0;
}

  • 前置与后置a++都相当于a=a+1,前置与后置--都相当于a=a-1

那前置与后置之间有什么区别呢·?请看下面这段代码。

int main()
{
	int a = 1;
	int b = a++;//后置++
	printf("a=%d b=%d\n", a, b);
	int c = ++a;//前置++
	printf("a=%d c=%d\n", a, c);
	int m = a--;//后置
	printf("a=%d m=%d\n", a, m);
	int n = --a;//前置--
	printf("a=%d n=%d\n", a, n);
	return 0;
}

通过上述代码,我们可以总结以下结论:

  1. 前置++,--,先执行++或--,然后对等式左边进行赋值
  2. 后置++,--,恰好相反,先对等式左边进行赋值,然后再++或--

热门相关:楚汉争鼎   北宋大表哥   娇妻如云   锦桐   明朝败家子