数据类型介绍
前面我已经介绍了C语言中 常用的数据类型
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数
这些数据类型在内存中开辟的大小也在前面介绍过了,可以利用sizeof进行测试
类型的基本归类
整形家族:
char
unsigned char
signed char
short
unsigned short [ int ]
signed short [ int ]
int
unsigned int
signed int
long
unsigned long [ int ]
signed long [ int ]
注意一下,字符在内存存储的是ASCII值,ASCII值是整形,所以char归类为整形类型
我们平时写的
int a;
signed int a;
unsigned int a;
int a == signed int a
https://blog.csdn.net/m0_69984273/article/details/131998273 这里简单的介绍过了char,signed char 和unsigned char C语言没有规定,取决于编译器
浮点数家族:
float
double
构造类型(自定义):
> 数组类型
> 结构体类型 struct
> 枚举类型 enum
> 联合类型 union
指针类型
int *pi;
char *pc;
float* pf;
void* pv;
空类型:
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型
如:int main(void)
整形在内存中的存储
int a = 20;
int b = 10;
会各自在内存开辟四个字节的空间进行存储
其实计算机能够处理的数据是二进制的,整形和浮点型数据在内存也都是以二进制的形式进行存储。
整数的二进制表示形式有3种:原码、反码、补码
正数的原码、反码、补码相同,
负数的反码是符号位不变,其他位取反, 补码是在反码的基础上加1
#include<stdio.h> int main() { int a = -10; //10000000 00000000 00000000 00001010 原码 //11111111 11111111 11111111 11110101 反码 //1111 1111 1111 1111 1111 1111 1111 0110 补码 // f f f f f f f 6 //0xfffffff6 unsigned int b = -10;// 全部位都是有效位, //11111111 11111111 11111111 11110110 补码 return 0; }
4个二进制位表示一个十六进制位
对于整形来说:数据存放内存中其实存放的是补码。
为什么呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统
一处理;
同时,加法和减法也可以统一处理( CPU 只有加法器 )此外,补码与原码相互转换,其运算过程
是相同的,不需要额外的硬件电路。
假设我们利用原码进行加减 如1 +(-1)
00000000 00000000 00000000 00000001
10000000 00000000 00000000 00000001
这里就会无法确定符号位是否相加
如果使用补码相加
00000000 00000000 00000000 00000001
111111111 111111111 111111111 111111111
不管符号位是否相加都不影响结果
大小端介绍(字节大于等于2的数据)
在内存窗口中就会发现存储的是补码。但是我们发现顺序有点不对劲。
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位 , ,保存在内存的高地
址中。
例如存储0x11223344
四个比特位 表示一个十六进制位, 两个十六进制位表示一个字节
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元
都对应着一个字节,一个字节为8 bit。
练习1
设计一个小程序来判断当前机器的字节序
#include <stdio.h> int check_sys() { int i = 1; return (*(char *)&i); } int main() { int ret = check_sys(); if(ret == 1) { printf("小端\n"); } else { printf("大端\n"); } return 0; }
#include <math.h> int my_end(int a) { int i = 0; int sum = 0; for (i = 0; i < 8; i++) { //计算a补码最右端的8位二进制之和 int b = (a >> i) & 1; sum = sum + b * pow(2, i); } return sum; } int main() { int a = 0; scanf("%d", &a); char* p = (char*)&a; //返回*p开始地址指向的那个字节的大小 int num = my_end(a); if (*p = num) { printf("小端存储"); } else { printf("大端存储"); } return 0; }