C语言_数据类型+整型与浮点数的存储+无符号数与有符号数区别+(例分析子+讲解)_NUC_Dodamce的博客-程序员信息网_无符号浮点数

技术标签: # C语言  

数据类型

1,整形:(默认有符号数)

在内存中存的是其对应二进制补码

char(存在内存中是其ASCLL码)

short(短整型)

int(整形)

long(长整形)

2,浮点型:

float

double

long double(不是所有编译器都支持)

3,构造类型(自定义类型)

数组

结构体(struct)

枚举(enum)

联合体(union)

4,指针类型

void*

float*

short*

char*

5,空类型

void


一.整型在内存的存储

首先我们要知道

整数在计算机中存的是它的补码

原码——>反码——>补码

三者的运算规则为

原码按位取反(符号位不变)——>反码。

反码+1——>补码。

在32位计算机中首位是符号位
表示正负不表示大小。

首位为1表示负数,首位为0表示正数。

eg(都是32位)

10000000000000000000000000000001表示-1

00000000000000000000000000000001表示1

对于正整数规定,它的原码,反码,补码都相同可以直接用。

对于负数计算机存的补码不等,要转成原码才可以直到其大小。

eg:
1 1 1 1 1…1 1(32位)(符号位1说明是负数)补码

1 1 1 1 1…1 0(32位)(补码-1到反码)

1 0 0 0 0…0 1(32位)(符号位不变其余位按位取反到原码)

原码首位为1说明是负数,发现值数字-1。

-----------------------------------------------------------------

整形在内存中存储补码的原因:

使用补码可以将符号位和数值域统一处理,原反补的转化运算过程相同,不用增添其他的计算原件。

eg:
计算10-1的值

10的二进制位原码与反码,补码相同
0 0 0 0 0 0… 1 0 1 0

-1在内存中存储的二进制位为
1 1 1 1 1 1… 1 1 1 1

相加为补码与补码相加

0 0 0 0 0 0…0 1 0 1 0
1 1 1 1 1 1…1 1 1 1 1

在这里插入图片描述
观察i在内存中的储存方式

#include<stdio.h>
int main()
{
    
	int i = 1;
	return 0;
}

在这里插入图片描述
而1的16进制为
00 00 00 01
发现这里是“倒着存数据”

整形存储方式有多种,常见的有

大端字节序储存与小端字节序储存

1.大端字节序储存:
(把一个数据的低位字节内容存在高地址处)

2.小端字节序储存:
(把一个数据的低位字节内容存在低字节处)

eg:

设 int a变量的地址为:0x 12 34 56 78(四个字节)

在这里插入图片描述

在这里插入图片描述

应用:
1,判断机器的存储方式

#include<stdio.h>
int main()
{
    
	int i = 1;
	char* p =(char*) &i;
	if (*p == 1)
	{
    
		printf("该计算机是小端存储");
	}
	else
	{
    
		printf("该计算机是大端存储");
	}
	return 0;
}

这里i=1的16进制位为:
0x 00 00 00 01(四个字节)

char*的访问权限只有一个字节

如果p为1,说明先储存的是二进制的低字节位,为小端字节序储存
如果
p为0,说明先储存的是二进制的高字节位,为大端字节序储存

整形提升

eg:

#include<stdio.h>
int main()
{
    
	char a = 3;
	char b = 137;
	char c = a + b;
	printf("%d",c);
	return 0;
}

在这里插入图片描述
发现这里并不是我们想的140,

这是因为char类型大小是一个字节,而一个整形是4个字节

char—8个比特位,

int—32个比特位,

整型提升是按照符号位进行提升的符号位就是二进制位的首位

+号操作符操作的是int型,所以char类型先补到32位

a=0 0 0 0 0 0 1 1(补位,符号位为0)

a=0000…0 1 1(32位)

b= 1 1 1 1 1 1 1 1(补位)

b=0 0 0 0 0 0 1 1 1 1 1 1 1(32位)

a+b=0 0…1 0 0 0 0 0 1 0(32位)

c=a+b(c是字符类型,只能存8位,所以会发生截断)

c=1 0 0 0 0 0 1 0

printf("%d")所以c还要进行整形提升

c的符号位是1,所以补1到32位

c整型提升后

1 1 1 1 1 1…1 0 0 0 0 0 1 0(32位)(补码)
1 1 1 1 1 1…1 0 0 0 0 0 0 1(32位)(补码)
1 0 0 0 0 0…0 1 1 1 1 1 1 0(32位)(原码)

符号位为1说明是负数
翻译原码得-116

有些数字如果是无符号位数,整形提升补零
整型提升只发生在有二进制位且大小小于int的时候

在这里插入图片描述
发生了整型提升。

当从int转换成比int大的类型时不会出现这种情况,不会截断

有符号数与无符号数

#include<stdio.h>
int main()
{
    
	char a = -1;
	unsigned char b = -1;
	printf("a=%d b=%d",a,b);
}

输出结果:在这里插入图片描述

a发生了截断又发生了整形提升不在赘述。

b的类型是unsigned char,二进制位为
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0…1 1 1 1 1 1 1 1(32位)=255
无符号数整形提升补0

有符号char:
在这里插入图片描述
范围为-128~127。

当超过取值范围时

在这里插入图片描述
(无符号)char:
最大值为:1 1 1 1 1 1 1 1=255
最小值为:0
超过范围时:
255+1=0

eg:

#include<stdio.h>
#include<string.h>
int main()
{
    
	char arr[1000];
	for (int i = 0; i < 1000; i++)
	{
    
		arr[i] = -1 - i;
	}
	printf("%d",strlen(arr));
	return 0;
}

在这里插入图片描述
strlen读取到0会停止
127+128=255

其他无符号整形类似


二.浮点数在内存中的存储

在讨论这个问题前先看一个经典题目

#include<stdio.h>
int main()
{
    
	int n = 9;
	float* p = (float*)&n;
	printf("%d\n",n);
	printf("%f\n",*p);
	*p = 9.0;
	printf("%d\n",n);
	printf("%f\n",*p);
}

输出结果:
在这里插入图片描述
当n是整形时,以浮点数打印和以整形打印的数字不同。当n是浮点型时,以整形打印的和以浮点数打印的数字不同。

说明整形与浮点型的存储方式不同。

浮点数的储存这里以10.5为例

10的二进制有效位为1 0 1 0。

0.5所在的二进制位的权重为2^-1

综上10.5=1 0 1 0 . 1=(-1) ^ 0 * 1 . 0 1 0 1 * 2 ^ 3;

规定:
1,任意的二进制浮点数可以表示为:
(-1)^ S * M
2 ^ E
*

其中
S是符号位,正浮点数为0;负浮点数为1。

M为有效数字,范围为1~2。

E为指位数。

2,对于单精度浮点型float:

S 占 1bit, E 占 8bit,M占23bit

其中M一定为1.XXXXXX,所以1不存在内存中
23bit全部存小数位。

对于双精度浮点型double:

S 占 1bit,E 占 11bit,M占52bit

其中M一定为1.XXXXXX,所以1不存在内存中
23bit全部存小数位。

S _E _M放的顺序为
在这里插入图片描述

3,规定E是无符号数

对于单精度float

E=真实e+127;再化成二进制

eg: 10.5=1 0 1 0 . 1=(-1) ^ 0 * 1 . 0 1 0 1 * 2 ^ 3

E=e+127=3+127=130

对于双精度double:

E=真实e+1023;再化成二进制

(注意特殊情况

1,当E的二进制位为全0时

E=e真实+127;

e真实特别小,很接近0,这时规定有效数字

M (1.XXXXXXXXXXX)不写小数点前的1,

且规定E=1-127= -126

用来表示这个数字很小

—————————————————————

2,当E的二进制位为1时(这里只讨论单精度)

E=e真实+127=255

e真实很大,这个数字是 ± 无穷

这是如果M为全0,表示无穷大,正负看S。

这里不再更深的研究。

这时再来看例题

#include<stdio.h>
int main()
{
    
	int n = 9;
	float* p = (float*)&n;
	printf("%d\n",n);
	printf("%f\n",*p);
	*p = 9.0;
	printf("%d\n",n);
	printf("%f\n",*p);
}

9的二进制位为:
0 0 0 0 0 0 0 0…1 0 0 1(32位)

当以浮点型打印时二进制会被拆分

在这里插入图片描述

同理浮点数9.0
9.0=(-1)^0 *1.001 * 2 ^3

S=0 M=1.001 E=127+3=130

在这里插入图片描述

所以最后打印的结果为
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dodamce/article/details/113528537

智能推荐

网站开发进阶(三)Windows NAT端口映射_No Silver Bullet的博客-程序员信息网

Windows NAT端口映射由于有需求进行端口映射,又不想装乱七八糟的软件,Windows本身自带的路由远程访问配置太麻烦,还要两块网卡,坑爹啊。其实Windows本身命令行支持配置端口映射,条件是已经安装了IPV6,启不启用都无所谓,我在win7和server2008上是可以的。xp,2003装了ipv6协议也是可以的。端口映射端口映射就是将外网主机IP地址的一个端口映射到内网

spark利用scala操作hdfs_xuehuagongzi000的博客-程序员信息网

1、读取hdfs目录:hadoop dfs -ls path相当于listStatus的简写//checkpoint目录是:/user/dmspark/accumulate/checkpoint//e.g. /user/dmspark/accumulate/checkpoint/0519936a-5bff-4ecf-a6f0-3854e5952ec9/rdd-689/part-00099...

Tensorflow-gpu tf.keras.Sequential 模型建立时的错误_Freeze-hu的博客-程序员信息网_tf.keras.sequential() invalidargumenterror: assert

如下在创建模型时出现的错误model = tf.keras.Sequential()报错内容为:tensorflow.python.framework.errors_impl.InvalidArgumentError: assertion failed: [0] [Op:Assert] name: EagerVariableNameReuse经过网上查找相关处理方法,分析可能是"使用的时候应该指定未使用的GPU“。没有说具体的解决方法。我这里的处理的方法是降低Tensorflow-gp

[Vulfocus解题系列]ThinkPHP5 远程代码执行漏洞(CNVD-2018-24942)_00勇士王子的博客-程序员信息网

漏洞介绍ThinkPHP5 存在远程代码执行漏洞。该漏洞由于框架对控制器名未能进行足够的检测,攻击者利用该漏洞对目标网站进行远程命令执行攻击。影响版本ThinkPHP 5.*,&lt;5.1.31ThinkPHP &lt;=5.0.23解题过程1.开启靶场环境2.在其地址增加路径与参数即可,最后是需要执行的命令 ls /tmp/index.php/?s=index/\think\app/invokefunction&amp;function=call_user_func_array&am

springboot @Value注解大坑,赋值两次数据不一致_*宋清歌的博客-程序员信息网[email protected] 值不一样

问题:启动项目时给实体类赋值,使用@Value注解获取nacos配置数据失败。解决:断点调试发现项目启动时实体类赋值第二次时获取的数据值变了查资料源码太复杂了不想看,因为其他项目也使用过@Value,赋值是正常的,然后对比发现springboot版本不一致,原来使用4.3.8,现在的项目使用4.2.5,更换版本后赋值成功,boot更新换代这么快跟不上步伐啊。...

浅谈微信开放平台_weixin_30916125的博客-程序员信息网

其实如果对微信公众平台有一定了解,那么一定不会将微信开放平台搞混。公众/开放平台的误解有人喜欢用受众不同,把它们区分为运营者或开发者的工具,公众平台是给运营者,而开放平台是面向开发者。这种说明挺误人子弟的,难道公众平台的受众就不包括开发者吗?难道开放平台就没有运营者的使用价值?强调受众来以此做区别,是本末倒置的说法!开放平台官方介绍移动应用开发接入微信开放平台,...

随便推点

python基础07_列表_list_Young_and_Cold的博客-程序员信息网

内置数据结构(变量类型)listsetdicttuple ## list(列表)一组由顺序的数据的组合创建列表空列表In [24]:1, 创建空列表l1 = []type是内置函数,负责打印出变量的类型print(type(l1))print(l1)2. 创建带值的列表l2 = [100]print(type(l2))print(l2)3. 创建列表,带多个值...

创建最小Java8 Docker镜像_hkNaruto的博客-程序员信息网

1.  参考 http://blog.csdn.net/hknaruto/article/details/70229896 , 构建一个最小Linux Docker镜像    考虑到需要进入Docker容器查看容器内部数据、状态,因此引用一个基础的Linux镜像。如果没有此类需求也可以直接FROM scratch2.  www.oracle.com下载jdk-8u101-linux-x64

quicksearch连接oracle,无法连接到数据库orcl_Epic游戏商城的博客-程序员信息网

Windows下,关于Oracle新建数据库之后,无法通过 / as sysdba 连接到orcl 问题背景:oracle 学习阶段,是这创建了数据库,发现 oracle 的一个数据库就是一个数据库实例。之后 因为各种问题,一直无法连接到 orcl 这个数据库 其实在/@dbname 指明数据库即可。之后 把创建的 数据库删除了。问题:删除新建的数据库之后 conn / a...文章fanr_zh...

selenium模拟登录时报错 Message: element not interactable_qq_36800722的博客-程序员信息网_selenium模拟登陆时候报错

原因:一个输入框有两个input标签解决方案:先单点value提示字的input,然后显示真正要输入框的input,然后针对这个input,再次进行输入操作代码为:

Hp跟踪进程的工具tusc_cuininmi5584的博客-程序员信息网

今天在分析oracle startup 过程中hung的问题时,hp工程师使用了tusc工具,尝试后感觉很好,并作搜集如下:http://h20331.www2.hp.com/hpsub/cache/286022-0-0-2...

导入keras报错:module 'tensorflow.python.keras.backend' has no attribute 'get_graph'_处女座程序员的朋友的博客-程序员信息网

主要是因为tensorflow与keras的版本不兼容import tensorflowprint(tensorflow.__version__)Environments¶Below is the list of Deep Learning environments supported by FloydHub. Any of these can be specified...

推荐文章

热门文章

相关标签