栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言内功修炼【整型在内存中的存储】

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言内功修炼【整型在内存中的存储】

 

目录

✂️ 一类型的基本归类

☝️ 1.整型家族

✋ 2.浮点型家族

✋ 3.构造类型 - 自定义类型

✌️ 4.指针类型

✊ 5.空类型

✒️ 二、整型在内存中的存储

✏️ 三、大小端介绍

⚽ 四、百度2015年系统工程师笔试题

 ⚾️五、练习题

1.⛳

2.⛳⛳

3.⛳⛳⛳

4.⛳⛳⛳⛳

5.⛳⛳⛳⛳⛳

6.⛳⛳⛳⛳⛳⛳

7.⛳⛳⛳⛳⛳⛳⛳


✂️ 一类型的基本归类

☝️ 1.整型家族
char
    unsigned char
    signed char
short
    unsigned short[int]
    signed short[int]
int
    unsigned int
    signed int
long
    unsigned long[int]
    signed long[int]

⚠️

注意:unsigned char 是无符号的char;signed char 是有符号的char

若以后创建的变量只会存正数,就可以使用 unsigned ,对于用 short 、int 还是 long long 要考虑数值的大小

✋ 2.浮点型家族
float
double

✋ 3.构造类型 - 自定义类型

数组

struct 结构体类型

enum 枚举

union 联合体

✌️ 4.指针类型
int* pi;
char* pc;
float* pf;
void* pv;

✊ 5.空类型

void 表示空类型(无类型)

通常应用于函数的返回类型、函数的参数、指针类型。

✒️ 二、整型在内存中的存储

数据在内存中是以 二进制 的形式存储

对于整数来说:

整数二进制有3中表示形式:原码、反码、补码

正整数:原码、反码、补码相同

负整数:原码、反码、补码是要进行计算的

计算方法:

按照数据的数值直接写出的就是原码

原码的符号位不变,其它位按位取反,得到的就是反码

反码 +1 得到的就是补码

⚠️

注意:整数在内存中存储的是补码。

例子:

#include

int main()
{
	int a = -10;
	//10000000000000000000000000001010 - 原码
	//11111111111111111111111111110101 - 反码
	//11111111111111111111111111110110 - 补码
	return 0;
}

       内存中是以十六进制展示的,而我们写出的是二进制,如果把二进制转化成十六进制,再进行比较就可以看出内存中存的是原码、反码、还是补码。

       二进制的四个位可以换一个十六进制位,前面28个比特位可以换7个F,0110可以换成6,也就是FFFFFFF6,根据前面的图片可以发现在内存中是倒着存的,这也说明了整数在内存中存的是补码。那么为什么会倒着存?以及为什么存的是补码?将在后面进行解释。。

为什么在内存中存的是补码,而不是原码或反码呢?

       原因:在计算机系统中,数值一履用补码表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码和原码相互相互转换,其运算过程是相同的,不需要额外的硬件电路。

例子:

#include

int main()
{
    //1 - 1;
    //由于CPU只有加法器,所以使用加负1来代替减1
    //1 + (-1);
    //假设使用原码来计算:
    //1的原码: 00000000000000000000000000000001
    //-1的原码:10000000000000000000000000000001
    //1 + (-1)的结果是:1000000000000000000000000000010
    //转化为十进制是-2,发现并不是我们想要的值
    return 0;
}

结论:使用原码计算,无法得到我们预期想得到的值。 

若使用补码计算:

#include

int main()
{
    //1 - 1;
    //由于CPU只有加法器,所以使用加负1来代替减1
    //1 + (-1);
    //假设使用原码来计算:
    //1的补码: 00000000000000000000000000000001

    //-1的原码:10000000000000000000000000000001
    //-1的反码:11111111111111111111111111111110
    //-1的补码:11111111111111111111111111111111

    //1的补码: 00000000000000000000000000000001
    //-1的补码:11111111111111111111111111111111
    //1 + (-1)的结果是:00000000000000000000000000000000
    //转化为十进制是0,是我们想要的值
    return 0;
}

结论:使用补码计算,可以得到我们预期想得到的值,所以要使用补码计算。

✏️ 三、大小端介绍

为什么整数里的正数和负数在内存中是倒着存储的?

解决这个问题要先介绍大端和小端的。那么什么是大端小端?

什么是大端小端:

大端(存储)模式:是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。

小端(存储)模式:是指数据的高位保存在内存的低地址中,而数据的低位,保存在内存的高地址中。

为什么会有大端和小端:

       这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或是32位的处理器,由于寄存器的宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端模式和小端存储模式。

例子:

这里展示用的是16进制,但内存中存的是二进制

正着存倒着存都可以,但是要怎么存进去的,怎么拿出来。

后面两种的存储顺序太复杂了,可以这样存,但是使用起来太复杂了。所以也就保留了前面两种较为简单的顺序。

这四个字节是按照什么样的顺序存在内存中的,我们讨论的是存储在内存中字节的顺序,所以就叫字节序。

字节序分两种:大端字节序,小端字节序。 

⚽ 四、百度2015年系统工程师笔试题

请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序

#include

int main()
{
	int a = 1;
	char* p = (char*)&a;
	if (*p == 1)
	{
		printf("小端n");
	}
	else
	{
		printf("大端n");
	}
	return 0;
}

函数写法:

#include

int check()
{
	int a = 1;
	char* p = (char*)&a;
	if (*p == 1)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int main()
{
	int ret = check();
	if (1 == ret)
	{
		printf("小端n");
	}
	else
	{
		printf("大端n");
	}
	return 0;
}

 函数写法的优化版本:

#include

int check()
{
	int a = 1;
	char* p = (char*)&a;
	return *p;
}

int main()
{
	int ret = check();
	if (ret == 1)
	{
		printf("小端n");
	}
	else
	{
		printf("大端n");
	}
	return 0;
}

 ⚾️五、练习题

1.⛳
#include

int main()
{
	char a = -1;
	//-1的原码:10000000000000000000000000000001
	//-1的反码:11111111111111111111111111111110
	//-1的补码:11111111111111111111111111111111
	signed char b = -1;
	//b的补码与a相同
	unsigned char c = -1;
	//c也是与a相同
	printf("a = %d,b = %d,c = %d", a, b, c);
	return 0;
}

 解析:

内存中存的是补码
char 有一个字节,等于 8 个比特位,-1是有 32 个比特位,将 -1 存到 a 中,a 是 char 类型,a 里面只能存 -1 补码的低 8 位。
11111111

signed char 是一个有符号的 char ,所以和 a 一样,b 里面只能存 11111111
unsigned char 是一个无符号的 char ,但它也是个 char ,c 也只能存 11111111。
要通过 %d 打印一个整型,这里会发生整型提升,因为是有符号位,所以高位要补符号位
11111111111111111111111111111111

这 32 个 1 是补码, %d 打印的是原码,也就是打印 -1 , a 也就等于 -1 , b 与 a 相同。
unsigned char 是无符号的 char ,高位补的是 0
00000000000000000000000011111111
高位是 0 表示它是整数,整数原反补相同
转化为十进制打印也就是 255 

补充:

char 到底是 signed char 还是 unsigned char ?
''C语言标准并没有规定,取决于编译器
int 是 signed int
short 是 signed short

结果:

a=-1,b=-1,c=255

2.⛳⛳
#include

int main()
{
	char a = -128;
	//-128的原码:1000000000000000000000010000000
	//-128的反码:1111111111111111111111101111111
	//-128的补码:1000000000000000000000010000000
	printf("%u", a);
	return 0;
}

解析:

a是一个 char 类型,只能存8个比特位。
10000000

%u 打印要发生整型提升,因为是有符号的 char,高位补符号位。
11111111111111111111111110000000
%u 打印一个无符号整型,无符号表示是整数,原反补相同,此时的补码就是原码,转化为十进制后输出结果

如果是以 %d 打印,%d 是打印有符号整数,回通过计算得到原码,最后输出 -128 。

结果:

4294967168

3.⛳⛳⛳
#include

int main()
{
	char a = 128;
	//128的原码:1000000000000000000000010000000
	//因为是正数。原反补相同
	printf("%u", a);
	return 0;
}

解析:

char 类型只能存8个比特位
10000000

因为是有符号的 char,%u 打印,整型提升,高位补符号位
11111111111111111111111110000000
%u 打印无符号整数,原反补相同,转化为十进制

补充:
char 类型变量的取值范围

结果:

 4294967168

4.⛳⛳⛳⛳
#include

int main()
{
	int i = -20;
	//-20的原码:10000000000000000000000000010100
	//-20的反码:11111111111111111111111111101010
	//-20的补码:11111111111111111111111111101100
	unsigned int j = 10;
	printf("%dn", i + j);
	return 0;
}

解析:

10是整数,原反补相同
00000000000000000000000000001010

i的补码 + j的补码:
i:11111111111111111111111111101100
j:00000000000000000000000000001010
i + j 的补码:11111111111111111111111111110110

因为以 %d 打印,转化为原码后为
10000000000000000000000000001010
转化为十进制输出结果

结果:

-10

5.⛳⛳⛳⛳⛳
#include

int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%un", i);
	}
	return 0;
}

解析:

       i是一个无符号整型,不可能为负数,最小是0,%u 打印一个无符号数,判断条件是大于等于0,i的值一直减小到0就不会继续减小了,也就无法跳出循环。

结果:

死循环

6.⛳⛳⛳⛳⛳⛳
#include

int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	return 0;
}

解析:

a[i]的值依次为-1 -2 -3......-127 -128 127 126 125......3 2 1 0 -1 -2 ...... -127 -128 127......

因为是char类型,能存的最大负数和最大整数依次是
-128和127

第3题有做详细介绍

结果:

255

7.⛳⛳⛳⛳⛳⛳⛳
#include

unsigned char i = 0;
int main()
{
    for (i = 0; i <= 255; i++)
    {
        printf("hello worldn");    
    }
    return 0;
}

解析:

unsigned char 是无符号的 char,i 的范围只能是0~255,而判断条件是小于等于255,无法跳出。

结果:

死循环

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/942336.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号