个人笔记1(C语言)

发布于:2023-01-06 ⋅ 阅读:(364) ⋅ 点赞:(0)

目录

const的用法

数据类型

整形在内存中的存储

浮点型在内存中的存储


const的用法

const修饰的常变量不可变

int main()
{
	const int num = 10;
	num = 20;
	printf("%d\n",num);
}

如果像上面这样修改变量,编译器会报错

可以通过以下方法修改变量:通过地址找到num

int main()
{
	const int num = 10;
	int* p = #
	*p = 20;
	printf("%d\n", num);
}

得到结果num=20,但破坏了const的语法规则

const可以修饰指针

int main()
{
	const int num = 10;
	const int* p = #
	*p = 20;
	printf("%d\n", num);
}

如上,const修饰*p指针后,该代码会报错,那p变量本身可不可以改呢?答案是可以的

516fe9dfcbf94a8482c12f546b26a8b1.png

得出结论,const放在*的左边(const int* p和int const *p)const修饰的是*p,表示p指向的对象不能通过p来改变,但是p变量中的地址是可以改变的

接下来对该代码进行一些改变

f689a6803e9f46949fc7c1d70c7abb2e.png

得出结论,const放在*的右边(int* const p)const修饰的是p,表示p的内容不能被改变,但是p指向的对象是可以通过p来改变的

        


数据类型

如果是有符号的数据,最高位是符号位,最高位是0表示正数

无符号数用%u(4byte)打印,%u会把补码当成原码直接打印

4026165bf2ee477eb88eb821508f4b41.png

short(2byte - 16bit) 默认为有符号的(int、long也默认为有符号的)

unsigned short  无符号的short

char 是有/无符号? 不确定,取决于编译器的实现

假设有符号(1byte - 8bit) 可表示范围 -128~127

00000000 -> 0

01111111 -> 127

10000000 -> 直接解析为 -128

11111111 -> 反11111110 -> 原10000001 -> -1

构造类型(自定义类型):

  • 数组类型
  • 结构体类型 struct
  • 枚举类型 enum
  • 联合类型 union

        


整形在内存中的存储

  • 原码

    直接将数值按照正负数的形式翻译成二进制就可以

  • 反码

    将原码的符号位不变,其他位依次按位取反就可以得到了

  • 补码

    反码+1就得到补码

正数的原、反、补码都相同

三种表示方法均有符号位和数值位两部分

整形数据存放内存中其实存放的是补码(CPU中只有加法器)

e6c08ee918044eb8a92d8603a093f24f.png

 大端字节序存储:把一个数据低位字节处的数据存放在高地址处,把高位字节处的数据存放在低地址处

 小端字节序存储:把一个数据低位字节处的数据存放在低地址处,把高位字节处的数据存放在高地址处,例(vs编译器):

69bd4ac7ebb843f2a81c0c2d4d759dba.png

 设计一个小程序来判断当前机器的字节序:

#include<stdio.h>
int main()
{
	int a = 1;
	char* p = (char*)&a;
	if (*p == 1)
		printf("小端\n");
	else
		printf("大端\n");
    return 0;
}

但这样是一次性的代码,可以封装成一个函数:

#include<stdio.h>
check_sys()
{
	int a = 1;
	char* p = (char*)&a;
	if (*p == 1)
		return 1;
	else
		return 0;
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
		printf("小端\n");
	else
		printf("大端\n");
}

对函数部分简化一下:

check_sys()
{
	int a = 1;
	return *(char*)&a;
}

整形提升:无符号数在高位补0,有符号数按符号位补高位

例1:

int main()
{
    char a = -128;
    printf("%u\n",a);
}

-128的原、反、补:

10000000000000000000000010000000

11111111111111111111111101111111

11111111111111111111111110000000

截断(char):10000000 -> a

(打印格式%u)整形提升(按char):11111111111111111111111110000000(无符号数)

结果为4294967168

如果是 char a = 128,则同上

例2:

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

结果是:死循环

char能存的最大数为255(11111111),再加1(100000000),发生截断(00000000),i变成0

        


浮点型在内存中的存储

float.h 定义了浮点数的取值范围的相关信息

limits.h 定义了整形数的取值范围的相关信息

8c7b42b7cdf247c0b59db817b7da1ec0.png

 此结果表明:整数和浮点数在内存中的存储方式是有差异的

IEEE 754规定,二进制浮点数V可以表示成下面的形式:

  • (-1)^S * M * 2^E
  • (-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数
  • M表示有效数字,大于等于1,小于2
  • 2^E表示指数位

5.5 -> 10进制的浮点数  二进制:101.1

(-1)^0 1.001 * 2^2

      S            M         E

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

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

一些特别规定:

  1. 计算机内部保存M时,舍去第一位1,读取的时候再加上去,这样可以节省1位有效数字。
  2. 对于指数E,首先,E为一个无符号整数,因为科学计数法中E可以为负,IEEE 754规定存入E的真实值必须再加上一个中间数(8位的E加127;11位的加1023。不管E为正负)。
  3. E为全0时,E等于1-127(或1-1023)即为真实值,M不再加第一位的1。这样做为了表示±0,以及接近于0的很小的数字;E为全1时,如果M全为0,表示±无穷大(正负取决于符号位S)。

浮点数在计算机中不能精确保存,所以不能用==判断(类似if(f==0.0)是不可以的),只能比较两个数差值是否在误差范围内

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到