【C语言进阶】- 数据存储

本文详细介绍了C语言中的数据存储,包括内置类型、类型分类(整型、浮点数、构造类型和指针类型),数值的表示形式(原码、反码和补码),以及大小端和字节序的概念。通过实例和练习帮助读者理解这些概念及其在编程中的应用。
摘要由CSDN通过智能技术生成

1.1 C语言中的内置类型

首先,C语言中本身存在了这几种数据类型
在这里插入图片描述
类型的意义取决了,你所定义一个变量时,需要开辟多少的空间。

1.2 C语言的类型分类

我们知道C语言中有这么多类型了,那么该如何分类呢?

整型家族
在这里插入图片描述
可以看到,整型家族的类型,有被unsigned和signed这两个关键字所修饰。

首先,我们所定义的变量默认都是有符号数的,也就是被signed所修饰。在这里插入图片描述

那么unsigned 和 signed的区别是什么呢?
signed在这里插入图片描述

一个int是4个字节,占用4B,也就是32个比特位,最高位为符号位,符号位0为正,1位负,但是符号位不参与计算。

unsigned
在这里插入图片描述

对于unsigned所修饰的变量,没有符号位,它是计入运算的

最后,生活中的一些事物,只有正数没有负数,比如身高,体重,所以这时我们使用unsigned来修饰更加贴切.

unsigned int height = 180;

浮点数家族
在这里插入图片描述

浮点数家族只有2个,double比float所表达的范围更广,更精准一些

构造类型
在这里插入图片描述

构造类型也称为自定义类型,比如数组的在定义时,
int arr[10] 的类型为 int [10]
char arr[5] 的类型为char [5]
类型是不相同的

指针类型
在这里插入图片描述

空类型

void类型为空类型,常用于函数的返回值,函数的参数,指针类型

1.3 数值的表示类型

数值有不同的表示形式
在这里插入图片描述

此外,整数二进制也有3中表示方式,它们就是原码,反码,补码

  1. 正的整数,原码、反码、补码相同
  2. 负的整数,原码、反码、补码是需要计算的
    原码:直接通过正负的形式写出的二进制序列就是原码
    反码:原码的符号位不变,其他位按位取反得到的就是反码
    补码:反码+1就是补码

那么在内存中,存储的是原码是反码还是补码呢?

#include <stdio.h>
int main()
{
	int a = 20;
	//20
	//00000000000000000000000000010100-原码
	//0x00 00 00 14
	//00000000000000000000000000010100-反码
	//00000000000000000000000000010100-补码
	//
	int b = -10;
	//10000000000000000000000000001010--原码
	//0x80 00 00 0a
	//11111111111111111111111111110101--反码
	//0xfffffff5
	//11111111111111111111111111110110--补码
	//0xfffffff6
	//
	return 0;
}

在这里插入图片描述

结论:整数在内存中存放是补码的二进制序列

疑问:问什么我们算出来的数是0xfffffff6,而在内存监视中是倒着的呢?

1.4 大小端和字节序

大端:把一个数据的低位字节序放在高地址处,高位字节序放在低地址处。
小端:把一个数据的低位字节序放在低地址处,高位字节序放在高地址处。
在这里插入图片描述

1.5 练习

练习:写一段程序,判断当前机器的字节序

思路:我们知道了,机器是按小端存储,可以定义一个
int a = 1 变量,整型占用4个字节,我们可以取它第1个字节,如果是1,那么就说明是小端,否则是大端。

实现:

#include <stdio.h>

int check_fun(int n)
{
	return *(char*)(&n);
}

int main()
{
	int a = 1;
	int r = check_fun(a);
	if (r)
	{
		printf("小端");
	}
	else {
		printf("大端");
	}
	return 0;
}

在这里插入图片描述
练习1:输出这段程序的结果

#include <stdio.h>

int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a = %d,b = %d,c = %d", a, b, c);
	
	return 0;
}

char a 的计算过程
(1)-1是int整数,先计算-1的原反补码
10000000 00000000 00000000 00000001 -1的原码
11111111 11111111 11111111 11111110 -1的反码
11111111 11111111 11111111 11111111 -1的补码
因为是char,存储一个B
11111111 (补码截断存储到char中)
(2)%d 打印的有符号的整型
11111111 11111111 11111111 11111111 (整型提升,因为是有符号数,补充的是符号位)
10000000 00000000 00000000 00000000
10000000 00000000 00000000 00000001
-1
unsigned char c 的计算过程
(1)先存储到char中
10000000 00000000 00000000 00000001 -1原码
11111111 11111111 11111111 11111111 -1补码
11111111 (截断)
(2) %d 打印的是有符号整型,unsigned char c 进行整型提示,因为是无符号类型,所以补0
00000000 00000000 00000000 11111111 -整型提升,因为是无符号数,补0
255

在这里插入图片描述

练习2:这段程序的输出结果

#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0;
}

10000000 00000000 00000000 10000000
11111111 11111111 11111111 01111111
11111111 11111111 11111111 10000000 - 截断
10000000 - a
11111111 11111111 11111111 10000000 - 先看定义的类型,是char,是有符号char的整型提升,补符号位

在这里插入图片描述

练习3:下列程序的输出结果

#include <stdio.h>
int main()
{
    char a = 128;
    printf("%u\n",a);
    return 0;
}

00000000000000000000000010000000
10000000 - a

在这里插入图片描述

练习4:下列程序的输出结果

#include <stdio.h>
int main()
{
	int i = -20;
	//10000000000000000000000000010100
	//11111111111111111111111111101011
	//11111111111111111111111111101100 - -20的补码
	//
	unsigned int j = 10;
	//00000000000000000000000000001010 - 10的补码
	printf("%d\n", i + j);
	printf("%u\n", i + j);
	//11111111111111111111111111101100
	//00000000000000000000000000001010
	//--------------------------------
	//11111111111111111111111111110110 - 因为打印%d,所以认为是有符号数的补码,是负数,要求原码
	//10000000000000000000000000001001
	//10000000000000000000000000001010 -> -10
	
	return 0;
}

-10

练习5

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

在这里插入图片描述

输出结果原因:因为是unsigned int,所以不可能为负数,经过计算后,是一个非常大的正数

在这里插入图片描述
练习6

char a[1000];
int i;
for(i=0; i<1000; i++)
{
   a[i] = -1-i;
}
printf("%d",strlen(a));

在这里插入图片描述

输出结果原因:
a[0] = -1
a[1] = -2

a[127] = -128
a[128] = 127

a[254] = 0
数组中的元素是不断减一,而char的取值范围是-128~127,所以当-128减1时,是等于127,再减一,直到0,而strlen这个函数是求’\0’之前的元素个数,它的ASCII码值等于0,所以负的数加正的数,共128+127=255个元素

在这里插入图片描述
练习7

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

输出结果是无限循环,因为unsigned char 的取值范围是0-255,当i = 255时,再加1,i=0了,所以就是无限的循环。

在这里插入图片描述

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值