【C】数据类型其实并不难

int型是一种只表示整数的数据类型,它不能表示小数部分的实数。所以我前面使用double类型来处理实数的。由此可见,数值表现都有一定的特征和范围,它们是由数据类型决定的。C语言提供了丰富的数据类型。

基本数据类型和数

算数类型和基本数据类型

我们知道可以对int型和double型的变量及常量进行加减等算术运算,这种数据类型称为算术类型。算术类型是多种数据类型的统称,大体可以分为以下两种类型。
整数类数据类型:只表示整数
浮点型:可表示具有小数部分的数值
【C】数据类型其实并不难_第1张图片

基数

比如我出生与2000年这种数据表现形式很常见,这就是以10为基数的十进制数。
在表示数值的时候,基数是进位的基准。基数为10的十进制数,每逢10或10的倍数进位。
不过,在计算机中所有的数据都是用ON/OFF信号(即1和0)来表示的。对我们来说最容易理解的就是十进制数,而对于计算机来说以2为基数的二进制数更加容易理解。虽说如此,假如我们都用二进制来表示所有的数值那可就太费神了,所以在写法上还使用了八进制和十六进制数
在十进制数中,如果以下10种数字都用完了,那就进为10。
0 1 2 3 4 5 6 7 8 9 1位十进制位
在此之后,若第2位的10~99也用完了,就会进位为100。
同样在八进制数中,用完以下8种数字之后就进位为10。
0 1 2 3 4 5 6 7 1位八进制
当然,若2位的10~77也用完了,那就进位为100。
依次类推,在十六进制数中使用以下16种数字,那么F后面的数就是10。
0 1 2 3 4 5 6 7 8 9 A B C D E F 1位十六进制数
另外,如果2位的的10~FF用完了,还会再进一位,变成100。
如下所示,将十进制0~20分别用八进制、十进制、十六进制数表示。
八进制 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24
十进制 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
十六进制 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14
二进制只能使用0和1两种数字表示数值。
0 1 1位二进制数
因此,将十进制0~13用二进制表示就是:
0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101

基数转换

下面我们来说下不同基数间的整数数值相互转换的方法。

由八进制数、十六进制数、二进制数向十进制的转换方法

十进制数的每一位都是10的指数幂。所以1997可以解释为:
1997=1X103+9X102+9X101+7X100
1000 100 10 0
将这个思路引用于八进制、十六进制和二进制数上,就能轻松地将这些数值转化为十进制数。
举例来说,将八进制数123转换为十进制数的步骤如下:
123=1X82+2X81+3X8^0
=1X64+2X8+3X1
=83
而将十六进制数1FD转化为十进制数的步骤如下:
1FD=1X162+15X161+13X16^0
=1X256+15X16+13X1
=509
将二进制数101转换为十进制数的步骤如下:
101=1X22+0X21+1X2^0
=1X4+0X2+1X1
=5

由十进制向八进制、十六进制、二进制数转换

二进制数有如下规律。
偶数的末位数字为0,
奇数的末位数字为1。
也就是说,用要转换的数除以2所得到的余数就是末位数字的值。
例如,十进制数字57除以2的余数是1,那么转换后的二进制数的末位数字就是1,这一点只要稍加计算就能
白了。
转化如下图所示:
将十进制数57转换为二进制数
所以57的二进制数是111001。
当然转换为十进制、八进制、十六进制数的步骤是完全相同的。只要将除数改为8或者16,最后排列余数就好了。
4位二进制数和1位十六进制数是相互对应的(即4位的二进制数00001111,就是1位的十六进制数0F)。
二进制数和十六进制数的对应关系图
利用这一特性,二进制转换为十六进制数、十六进制数转二进制数就很容易了。
例如,要将二进制数0111101010011100转换为十六进制数,只需每4位隔开一下,并分别转换为1位的十六进制数。
这就是转换为十六进制
另外,要将十六进制转换为二进制数,只需反过来操作即可(将十六进制数的1位转换位二进制的4位)。

整型和字符型

C语言最擅长处理的是整型和字符型。

整型和字符型

整型字符型是用来表示限定范围内连续的整数的数据类型。
假设某种数据类型表示10个连续的整数。如果只需要表示非负整数(0和正整数),那么这10个数可以是:
(a) 0 1 2 3 4 5 6 7 8 9
如果,又想使用负数,那就可以变为:
(b)-5 -4 -3 -2 -1 0 1 2 3 4
当然,这个范围也可以是-4到5。(b)虽然有能表示负数的优点,但它可表示的绝对值却几乎只有(a)的一半。
由此可知,如果事先确定要处理的数不会是负数,并且需要处理较大的数,那么使用(a)较为合适。
在C语言中处理整数时,可以根据用途和目的的灵活使用以下数据类型:
** 无符号整数 表示0和正整数的整型
有符号整数 ** 表示0和正负整数的整型
前者相当于(a),后者相当于(b)。
声明变量时,可以通过加上
类型说明符signed
或者unsigned来指定其中一种数据类型。如若不加类型说明符,则默认为有符号。例如:

int x;                    //表示x是有符号的int型
signed int y;             //表示y是有符号的int型
unsigned int z;           //表示z是无符号的int型

类型名方面存在下列规则。

  • 对于单独的short和long,可以认为是省略了int。
  • 对于单独的signed和unsigned,可以认为是(非short和long的)int。

字符型、整型的名称和简称

头文件

我们已经知道了,字符型和整型包含多种类型,而各种数据类型可表示的数值的范围是怎么样的呢?
字符型和整型能表示的数值的范围
实际上,各种数据类型具体能表示多少个数值因编译器而异。表中显示的是最低限度的范围,很多编译器还可以表示超出本表的范围。
C语言编译器在头文件中以宏定义的形式定义了字符型以及其他整型所能表示的数值的最小值和最大值。
如下所示为C中设定的的部分内容。
【C】数据类型其实并不难_第2张图片
通过调查这些宏的值,就可以判定自己使用的编译器中各种数据类型所能表示的数值范围。
代码如下:

//显示字符型和整型数据类型的表示范围
#include
#include

int main()
{
	puts("该环境下各字符型、整型数值的范围:");
	printf("char             :%d~%d\n", CHAR_MIN, CHAR_MAX);
	printf("signed char      :%d~%d\n", SCHAR_MIN, SCHAR_MAX);
	printf("unsigned char    :%d~%d\n", 0, UCHAR_MAX);

	printf("short            :%d~%d\n", SHRT_MIN, SHRT_MAX);
	printf("int              :%d~%d\n", INT_MIN, INT_MAX);
	printf("long             :%ld~%ld\n", LONG_MIN, LONG_MAX);

	printf("unsigned short   :%u~%u\n", 0, USHRT_MAX);
	printf("unsigned         :%u~%u\n", 0, UINT_MAX);
	printf("unsigned long    :%lu~%lu\n", 0, ULONG_MAX);
	return 0;
}

在vs2019环境下的结果如下所示:
【C】数据类型其实并不难_第3张图片

字符型

char用来保存“字符”的数据类型。
对于没有声明signed 和unsigned 的char型,视为有符号类型还是无符号类型,具体由编译器决定,为了弄清楚在vs2019编译器下的区别,我用如下的程序解答。

#include
#include

int main()
{
	printf("这个编译器中的char型是:");

	if (CHAR_MIN)
	{
		puts("有符号的。");
	}
	else
	{
		puts("无符号的。");
	}

	return 0;
}

image.png
char能表示的范围,是以下两者中的一个。

  1. 如果char型为有符号类型,则和signed char型的范围一样。
  2. 如果char型为无符号类型,则和unsigned char型的范围一样。

因此,采用1的编译器中,的定义如下:

#define CHAR_MIN SCHAR_MIN      //与signed char的最小值相同
#define CHAR_MAX SCHAR_MAX      //与signed char的最大值相同

另外,采用2的编译器中,的定义如下。

#define CHAR_MIN 0              //一定为0
#define CHAR_MAX UCHAR_MAX      //与unsigned char的最大值相同

因此,在这个程序中,通过对CHAR_MIN的值是否为0来判断char的类型。

位和CHAR_BIT

我们一直将变量当作保存数值的魔法盒,计算机中的所有数据都是用0和1(即“位”)的组合来表示的,所以在盒子内部也是以0和1的位序列来表示数据的。
C语言中“位”(bit)的定义如下:
“位”是具有大量内存空间的运行环境的数据存储单元,可保存具有两种取值的对象,对象中各位二进制位的地址不需要表示。
“位”可取两种值,其中一种是0,将位设为0以外的值,称为“设置位”。
根据编译器的不同,char型在内存上占据的位数不同。改位数作为对象式宏CHAR_BIT定义在中。下面式一个定义示例:

#define CHAR_BIT 8       //值因编译器而异

字符型和整型(int 型、long型等)能够表示的数值取值范围之所以因编译器而异,是因为在内存上占据的位数因编译器而异。

sizeof运算符

C语言中将表示字符的char型的长度定义为1,通过使用sizeof运算符可以判断出包括char型在内的所有数据类型的长度。如下所示:
image.png
该运算符以字节(byte)为单位。
下面是使用sizeof运算符,来显示字符型和整型的长度。代码如下:

//显示字符型和整型的长度

#include

int main()
{
	printf("sizeof(char)=%u\n", (unsigned)sizeof(char));
	printf("sizeof(short)=%u\n", (unsigned)sizeof(short));
	printf("sizeof(int)=%u\n", (unsigned)sizeof(int));
	printf("sizeof(long)=%u\n", (unsigned)sizeof(long));

	return 0;
}

代码运行结果如图所示:
【C】数据类型其实并不难_第4张图片
将sizeof运算符引用于数组,就可以得到数组整体的大小,例子如下:

int a[5];

使用sizeof(a)求int[5]型数组的大小的情况下,如果是sizeof(int)为2的编译器,则结果为10;而如果是sizeof(int)为4的编译器,则结果为20。
用数组整体的大小除以一个元素的大小,得到的就是数组元素的个数,因此,数组a的元素个数,可以通过下式求得:
sizeof(a)/sizeof(a[0]); 求数组a的元素个数的表达式
当然,即使不通过数组a的元素类型和元素类型的大小,也可以求得元素个数。代码如下:

#include

int main()
{
	int vi[10];
	double vb[25];

	printf("数组vi的元素个数=%u\n", (unsigned)(sizeof(vi) / sizeof(vi[0])));
	printf("数组vi的元素个数=%u\n", (unsigned)(sizeof(vb) / sizeof(vb[0])));

	return 0;
}

代码运行结果:
image.png

按位操作的逻辑运算

对于整数内部的位,有4种逻辑运算。这4种逻辑运算及其真值表如下:
【C】数据类型其实并不难_第5张图片
这些运算符的操作数必须为整数类数据类型或者枚举型。如果应用于浮点型等数据类型的操作数,编译时就会出错。

位移运算符

<<运算符和>>运算符的作用是求出将整数中的所有位左移或右移之后生成的值。这两个运算符统称为位移运算符。
image.png
使用<<运算符进行左移
表达式x< 使用>>运算符进行右移
表达式x< 【C】数据类型其实并不难_第6张图片

你可能感兴趣的:(c语言,开发语言,c++)