C语言----数据在内存中的存储(2)

简介: C语言----数据在内存中的存储

C语言----数据在内存中的存储(1)https://developer.aliyun.com/article/1544437

#include <stdio.h>
int main()
{
    char a[1000];
    int i;
    for (i = 0; i < 1000; i++)
    {
        a[i] = -1 - i;
    }
    printf("%d", strlen(a));//255
    return 0;
}
/*
因为这是一个char类型的数组,取值范围是-128~127的
-1 -2 -3 -4 ……………………-128 127 ……3 2 1 0 -1 -2 -3
-1到128是128个人元素,127到1是127个元素
那么总共就是255个元素了
 
 
因为strlen统计的是字符串中元素的个数,
并且检查的是'\0'之前的数
所以这个字符串数组内存在255个元素
*/
#include <stdio.h>
unsigned char i = 0;//全局变量
//因为这个char是unsigned char,无符号的char类型
int main()
{
    for (i = 0; i <= 255; i++)
    {
        printf("hello world\n");//打印无限个
    }
    return 0;
}
//因为前面有一个全局变量范围是0~255
//而循环的范围是i<=255,那么这个循环的条件恒成立,可以一直循环
//那么对于打印来说就是无限进行打印操作
//无限循环
#include <stdio.h>
int main()
{
    unsigned int i;//无符号整型,最小值是0
    //对于这个循环来说,i>=0就恒成立了,这个循环就一直进行
    for (i = 9; i >= 0; i--)
    {
        printf("%u\n", i);
        Sleep(100);
    }
    return 0;
}
 
/*
9
8
7
6
5
4
3
2
1
0
----------
0-1就变成-1了,-1被%u打印的时候将是一个非常大的数字
4294967295
 
…………………………下面就是非常大的数字了
 
*/
#include <stdio.h>
//X86环境 ⼩端字节序
int main()
{
    int a[4] = { 1, 2, 3, 4 };
    int* ptr1 = (int*)(&a + 1);
    //&a+1就是跳过一整个数组,指向这个数组的末尾
    //
    // 将这个地址强制类型转换为int*赋值给ptr1,那么ptr1指向的就是这个数组的末尾
    // ptr1[-1]---->*(ptr1-1)
    // 因为ptr1是整型指针,那么-1就是指向了4的位置,那么解引用得到的就是4
    // 
    // 那么4用16进制打印得到的还是4
    //
 
    int* ptr2 = (int*)((int)a + 1);
    /*
    这里的a是数组首元素的地址,那么被强制类型转换为整数类型,
    那么(int)a+1就是+1
    a是占4个字节的,但是被转换为整型了并且+1,那么现在就离开始的位置相差1个字节了
    所以ptr2指向就是离首元素地址差1个字节的地址的位置
    因为ptr2是整型指针,那么就是4个字节,从那个位置开始向后访问4个字节
 
    01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
 
    所以就是从第2个00开始访问到02
    00 00 00 02--因为这个地址在内存中是小端存在的,
    所以原始的就是02 00 00 00
    换成16进制的就是0x02 00 00 00
    所以打印出来的就是2000000,最前面的0x0是不打印的
    */
 
 
    printf("%x,%x", ptr1[-1], *ptr2);//4,2000000
 
    //%x是16进制的形式打印的
 
    return 0;
}

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

#include <stdio.h>
int main()
{
    int n = 9;//原反补相同
    //00000000  00000000  00000000  00001001-----9
    //
    //
    float* pFloat = (float*)&n;
    //取出n的地址并强制类型转换为float*类型的指针
    //再赋值给pFloat,那么pFloat指向的就是二进制的起始位置
 
 
 
    printf("n的值为:%d\n", n);//9
 
 
 
    printf("*pFloat的值为:%f\n", *pFloat);//0.000000
    //这个pFloat是浮点型指针,
    //站在*pFloat的角度上看,他会认为内存中存的是浮点数
    // 那么这次就是以浮点数的形式取出这个值
    // 因为整数和浮点数在内存中的存储形式不同
    // 所以我们将二进制转换为S M E类型的进行读
    // 0   00000000    00000000000000000001001
//    S      E            M     
//  他会认为这个数是以S E M类型存在的  
    //E为全0的时候,那么是E+127=0,所以E就是-127
    //那么这个数最后算出来就是一个正负无穷接近于0的数字
 
    //那么打印出来的数是0.000000 
 
    *pFloat = 9.0;
    //1001.0---小数点向左移动3位,所以下面的科学计数法就是乘2的3次方
    // 加上正负的处理的话(-1)^0
    //科学计数法的形式:(-1)^0 * 1.001 * 2^3
    //
    // S=0
    // M=1.001
    // E=3
    // S=0    E=127+3=130    M--小数点后面的是001,还要满23个比特位,所以补上20个0
    // 0      10000010       00100000000000000000000
// 所以9.0在内存中的二进制序列是01000001000100000000000000000000
    // 其实是放到n的位置空间内了,因为pFloat指向的是n的起始位置
    //
 
    /*
    站在n的角度上,我们得到的科学计数法的数是补码
    那么我们就要把原码算出来 
    因为高位是0,所以是正数,正数的原码补码反码相同
 
    所以这个二进制换算的十进制的数就是1091567616
    */
    printf("num的值为:%d\n", n);//1091567616
    printf("*pFloat的值为:%f\n", *pFloat);//9.000000
    return 0;
}
 
 
/*
我们要清楚我们是以什么形式放进去的,怎么形式取出来的,
 
我以整数的形式放进去的,我以整数的视角取出来,那么就按照整数的视角计算原反补
我以浮点数的形式放进去的,我以浮点数的视角取出来,那么我们就按S M E相关的东西进行计算
 
不理解就看代码
*/
 
/*
总之,就是浮点数和整数在内存中的存储方式是不同的
 
浮点数是S M E 
我们可以利用二进制序列来得到这三个数据,进而得到我们浮点数在内存中的存储形式
 
 
*/

常见的浮点数:3.14159、1E10--科学计数法

浮点数家族包括:float、double、long 、double类型

浮点数表示的范围:float.h中定义

整数和浮点数在内存中的存储方式是有区别的

10进制:5.5

2进制:101.1

5.5=(-1)^011.011*2^2

S=0

M=1.011

E=2

E是无符号的数

小数点后面的1就是表示2的负几次方,从-1开始

浮点数的存储,存储的就是S、M、E相关的值

对于32位的浮点数,最高的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M

对于64位的浮点数,最高的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M

1<M<2

在计算机内部保存M的时候,默认这个数的第一位总是1,因此可以被舍去,只保留后面的xxxx部分,xxxx部分表示小数部分

所以我们在存M的时候,一般存的都是小数点后面的位

10进制的0.5

2进制的0.1

科学计数法:1.0*2^-1

在存储E的时候还会添加中间值.float添加127

double添加1023

再将得到的值存在E的内存中

之前已经说过浮点数的存储,存储的就是S、M、E相关的值

取出来的三种情况:

1.正常存E的时候是E+中间值(127/1023),那么将这个取出来减去中间值就得到了E,对于M,将M取出+1就是我们要的M----这里的E不全为0或者不全为1

2.E为全0,那么取出来的E为-127,表示的就是正负无穷接近于0的数字

3.E为全1,如果全是1的话,那么刚好8个比特位,就是8个1,就是255

E+中间值(127)=255,那么E就是128

那么这个数也是一个正负无穷大的数字

int main()
{
    float f = 5.5f;
    //S=0;
    //E=2
    //M=1.011
    //0    10000001            01100000000000000000000
    //S   E--129=(127+2)       M--存的是小数点后面的-总共有23个比特位,那么剩下的20位补0
    //0100  0000  1011  0000  0000  0000  0000  0000
    //              11在16进制就是b
    // 4      0     b    0     0      0    0      0
    // 0x40b00000--最后得到的数据--浮点数5.5在内存中得到的形式
    //得到的二进制数每4个二进制位就能换一个16进制数
 
 
 
    return 0;
}
相关文章
|
8天前
|
存储 缓存 中间件
|
3天前
|
存储 Java 程序员
Java面试题:方法区在JVM中存储什么内容?它与堆内存有何不同?
Java面试题:方法区在JVM中存储什么内容?它与堆内存有何不同?
26 10
|
10天前
|
语音技术 C语言 Windows
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
语音识别------ffmpeg的使用01,ffmpeg的安装,会做PPT很好,ffmpeg不具备直接使用,只可以操作解码数据,ffmpeg用C语言写的,得学C语言,ffmpeg的安装
|
3天前
|
存储 设计模式 监控
Java面试题:如何在不牺牲性能的前提下,实现一个线程安全的单例模式?如何在生产者-消费者模式中平衡生产和消费的速度?Java内存模型规定了变量在内存中的存储和线程间的交互规则
Java面试题:如何在不牺牲性能的前提下,实现一个线程安全的单例模式?如何在生产者-消费者模式中平衡生产和消费的速度?Java内存模型规定了变量在内存中的存储和线程间的交互规则
14 0
|
3天前
|
存储 安全 Java
Java面试题:如何在Java应用中实现有效的内存优化?在多线程环境下,如何确保数据的线程安全?如何设计并实现一个基于ExecutorService的任务处理流程?
Java面试题:如何在Java应用中实现有效的内存优化?在多线程环境下,如何确保数据的线程安全?如何设计并实现一个基于ExecutorService的任务处理流程?
8 0
|
3天前
|
安全 Java 调度
Java面试题:Java内存优化、多线程安全与并发框架实战,如何在Java应用中实现内存优化?在多线程环境下,如何保证数据的线程安全?使用Java并发工具包中的哪些工具可以帮助解决并发问题?
Java面试题:Java内存优化、多线程安全与并发框架实战,如何在Java应用中实现内存优化?在多线程环境下,如何保证数据的线程安全?使用Java并发工具包中的哪些工具可以帮助解决并发问题?
5 0
|
3天前
|
安全 算法 编译器
C++一分钟之-内存模型与数据竞争
【7月更文挑战第10天】了解C++11内存模型对多线程编程至关重要。它定义了线程间同步规则,包括顺序一致性、原子操作和内存屏障。数据竞争可能导致不确定行为,如脏读和丢失更新。可通过互斥量、原子操作和无锁编程避免竞争。示例展示了`std::mutex`和`std::atomic`的使用。掌握内存模型规则,有效防止数据竞争,确保多线程安全和性能。
10 0
|
8天前
|
Linux C语言
【编程小实验】C语言实现:无限循环写入文本文件,支持Ctrl+C中断与数据追加(附完整源码)
在Linux中,文件I/O(输入/输出)是程序与文件进行交互的基本方式,包括读取文件内容和向文件写入数据。这通常通过标准的C库函数来实现,下面是一些基本的文件读写操作和代码示例。
|
10天前
|
存储 编解码 程序员
C语言17---计算机的存储规则
C语言17---计算机的存储规则