C语言 - 数据类型及存储

数据类型

1.整型家族

整型家族有字符型char短整型short整型int 长整型long和长长整型long long

类型范围
char0 ~ 255
signed char-128 ~127
unsigned char0 ~ 255
[signed] short [int]-32768 ~ 32767
unsigned short [int]0 ~ 65535
[signed] int-2147483648 ~ 2147483647
unsigned int0 ~ 42949672
[signed] long-2147483647 ~ 2147483647

unsigned long

0 ~ 42949672
[signed] long long-9223372036854775808 ~ 9223372036854775807
unsigned long long0 ~ 18446744073709551615

规定:sizeof(long long) >= sizeof(long) >= sizeof(int) >= sizeof(short)

其中,short,int,long在不显示声明为signed或unsigned时,它就是signed型

但char类型若不显示声明,那么它属于signed或unsigned,则取决于编译器

2.浮点数家族

float

double
long double

3.指针类型

char *p1

int *p2
float *p3
void *p4

4.构造类型

数组类型int  [n]
结构体类型struct
枚举类型enum
联合体类型

union

5.空类型

void

空类型可用于函数的返回类型,函数的参数,指针类型

空类型指针可作为形参接受任意类型的指针,但空类型指针无法直接解引用

数据存储

整型在内存中的存储

原码,反码,补码

计算机中数据有三种表示形式,原码,反码,补码,对于整型数据来说,数据在内存中存放的是其补码

对于有符号数,最高位是符号位

对于无符号数,最高位也是数据位

对于正数:

原码,反码,补码都相同

对于负数:

原码:直接将数据转换为对应的二进制形式,其中最高位为符号位,正数的符号位为0,负数的符号位为1

反码:符号位不变,其它位按位取反

补码:反码加1

类型的意义

计算机看待内存空间的视角

#include<stdio.h>
int main()
{
	unsigned int n = -10;

	//原码:10000000 00000000 00000000 00001010
	//反码:11111111 11111111 11111111 11110101
	//补码:11111111 11111111 11111111 11110110

	//%u打印无符号数,将要打印的数据看为无符号数,即使不是无符号数,也看作无符号数
	printf("%u\n", n);	//4294967286

	//%d打印有符号数,将要打印的数据看为有符号数,即使不是有符号数,也看作有符号数
	printf("%d\n", n);	//-10

	return 0;
}

当成无符号数时最高位也是数据位,因此打印出了一个很大的数

当成有符号数时最高位就是符号位,1代表负数,因此打印 -10

大小端存储

大端存储:指数据的低位保存在内存的高地址中,数据的高位保存在内存的低地址中

小端存储:指数据的低位保存在内存的低地址中,数据的高位保存在内存的高地址中

事实上大小端字节序指的是数据在电脑上存储的字节顺序

大小端字节序的测试方法:

方法1

#include <stdio.h>
int check()
{
	//1在内存中的二进制序列
	//00000000 00000000 00000000 00000001
	//大端存储
	//低地址 00 00 00 01 高地址
	//小端存储
	//低地址 01 00 00 00 高地址
	int i = 1;

	return (*(char*)&i);
}

int main()
{
	int ret = check();
	if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

方法2

#include <stdio.h>
int check()
{
	union Un
	{
		char c;
		int i;
	}u;

	u.i = 1;

	return u.c;
}

int main()
{
	int ret = check();
	if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

 

关于char的一道习题

#include<stdio.h>
#include<string.h>

int main()
{
    char a[1000];
    int i;
    for (i = 0; i < 1000; i++)
    {
        a[i] = -1 - i;
    }
    //strlen求字符串长度,找'\0'位置,统计'\0'之前的字符个数
    //'\0'的ASCII码值是0

    printf("%d", strlen(a));
    return 0;
}

循环中将-1赋给数组首元素,-2赋给数组下标为1的元素,一直往下赋值,当有一个数组元素被赋0时,此元素前应有255个元素被赋予非0值,因此当strlen函数找'\0'时,应输出255

浮点型存储

根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以写成如下形式

(-1)^S * M * 2^E

(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数

M表示有效数字,大于等于1,小于2

2^E表示指数位

例:

用红色代表S,绿色代表M,蓝色代表E

对于32位浮点数:1位S,8位E,23位M

对于32位浮点数:1位S,11位E,52位M

特别规定:

对于M:由于1≤M<2,M可以写成1.xxxxxx的形式,xxxxxx表示小数部分,因此计算机在保存M时,总是默认这个数的第一位是1,因此可以舍去,只保留小数部分。如1.011×2^2,在保存时只保存011,而舍掉第一位可以提高精度

对于E:E是一个无符号整数,而科学计数法中E可能为负数,因此,在存入E时,必须先加上一个中间数,对于8位E,中间数为127,对于11位E,中间数为1023。如1.011×2^2,E为2,但存入内存时若保存为32位浮点数,则以129存入;若保存为64位浮点数,则以1025存入

从内存中取出

E不全为0或不全为1:指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1

E全为0:那么这个浮点数一定是一个接近0的很小的数,因为它的指数加了127(或1023)还是全0,此时有效数字M不再加上第一位的1,而是还原为 0.xxxxxx的小数

E全为1:此时,若M全为0,则表示正负无穷大

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值