6

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

 7 months ago
source link: https://www.cnblogs.com/bett/p/18007132
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
pFp8UCq.jpg

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

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

所属专栏: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;
}

输出结果:

3371071-20240204222658583-1888716203.png

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

  1. 二进制转十进制,按权重直接转换,假设二进制的1001,转换如图
3371071-20240204222659190-1692899947.png
  1. 二进制转八进制,从右往左每三个二进制转换为一个八进制位,最后不够直接转为八进制。以二进制11010111为例

3371071-20240204222659774-1245128202.png

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

3371071-20240204222700335-1449472548.png

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

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

输出结果:

3371071-20240204222701519-994671587.png

2. 数据类型

2.1 介绍

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

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

3371071-20240204222702158-1467731747.png
  • 顾名思义整型是用来描述整数的,浮点型是用来描述小数的,具体细分与其表示的精度有关。
  • 每次声明一个变量时都需要声明其类型。
  • 其中因为字符在内存中存储是以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

3371071-20240204222702967-330163038.png

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

3371071-20240204222703519-373070938.png

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

输出结果:

3371071-20240204222704069-1761220403.png

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

输出结果:

3371071-20240204222704589-13709596.png

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

输出结果:

3371071-20240204222705291-595192382.png

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

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

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

输出结果:

3371071-20240204222705999-639605067.png

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

3371071-20240204222706625-1591250940.png

  • 前置与后置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;
}
3371071-20240204222707377-302213305.png

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

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

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK