IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言内功修炼【整型在内存中的存储】 -> 正文阅读

[C++知识库]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?,对于用 shortint 还是 long long?要考虑数值的大小

? 2.浮点型家族

float
double

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

数组

struct 结构体类型

enum 枚举

union 联合体

???4.指针类型

int* pi;
char* pc;
float* pf;
void* pv;

? 5.空类型

void 表示空类型(无类型)

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

?? 二、整型在内存中的存储

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

对于整数来说:

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

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

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

计算方法:

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

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

反码 +1 得到的就是补码

??

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

例子:

#include<stdio.h>

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

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

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

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

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

例子:

#include<stdio.h>

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

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

若使用补码计算:

#include<stdio.h>

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<stdio.h>

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

函数写法:

#include<stdio.h>

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<stdio.h>

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<stdio.h>

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<stdio.h>

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<stdio.h>

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

解析:

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

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

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

结果:

?4294967168

4.????


#include<stdio.h>

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

解析:

10是整数,原反补相同
00000000000000000000000000001010

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

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

结果:

-10

5.?????

#include<stdio.h>

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

解析:

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

结果:

死循环

6.??????

#include<stdio.h>

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<stdio.h>

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

解析:

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

结果:

死循环

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-06 17:10:30  更:2022-06-06 17:10:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:18:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码