CS61C第一部分笔记(Number Representation, Floating point,C Basics)

本文详细介绍了C语言中的数值表示,包括不同进制转换、补码和浮点数的IEEE754标准,以及内存管理如栈、堆和动态内存分配,同时涵盖了大端和小端字节序以及常见的内存错误和安全实践。
摘要由CSDN通过智能技术生成

Part1 Number and C Basics

Number representation

1.几种进制

  • Decimal
  • Binary 0bxxxx (x是0或1)
  • Hex 十六进制 0xxxxx(0-F)

2.进制的转换

3.数字表示方法

最重要的还是补码(2’s complement)
其他还有 1’s complement, sign and magnitude

bias notation 移码
以一个数为base,用unsigned int为bias,表示两数之和
用于表示浮点数中的指数部分
例如 bias = -127
0b00000000 = -127
0b11111111 = 128
参考链接

4.overflow

机器中表示一个数的位有限,超过范围就会溢出
补码形式加法可能溢出的情况:正+正,负+负

5.sign extension

用更多的位数表示相同的数字
具体方式(补码形式): 用符号位填满多出来的位,符号位与原符号位相同,剩下较低的其余位不变

floating point 浮点数

用二进制的科学计数法来表示小数,小数点位置不固定,所以称为浮点数
既有范围的广度,又有位数的精度

科学计数法

在这里插入图片描述
在这里插入图片描述

IEEE 754 Standard

所有计算机通用的浮点数储存形式,保持高精度,支持实数数学运算,可以处理数学错误(除0等等),与二的补码兼容,可以让计算机无需理解浮点,即可进行大小比较
在这里插入图片描述

  • 32bit表示(单精度)
  • 1bit表示符号位(1表示负数,0表示正数)
  • 8bit表示指数(bias=-127的bias notation)
  • 23bit表示小数部分
指数

使用-127bias,则可以看做unsigned int,利于进行大小比较,一个数看上去越大(1相对更多),则实际大小越大
对于一个已知的指数,+127,再用unsigned int表示,可以得到储存的形式
指数范围是-127到128,其中128表示正无穷,-127表示0 如此处理过大的数,避免溢出

小数部分(significant)

23bits,实际表示形式是
1.significant
这样可以少储存一位

双精度 double

在这里插入图片描述

Special number representation 特殊数字

0的表示(Representing Zero)

由于隐性表示的1,32位全0实际上表示1.0*2-127
在此规定:小数部分和指数部分全0即表示0
符号位不同表示+0和-0(一个无限接近0的数字总有符号)

正负无穷 ± ∞ ± \infty ±

小数部分全0,指数部分全1,符号位表示正负
特性:在754中作为一个数表示,可以通过除0得到

Not a Number(NaN)

  • 无意义的数字 比如 0/0 sqrt(-4)
  • Op(NaN,number) = NaN
  • 可用于debug
  • 表示:指数全1 小数非0

Denorm Numbers

有意义的最小的正数为小数全0 指数为1(-126) 即 1.0 * 2-126.
第二小的是小数为 2-126 + 2-149 (1.000…01 * 2-126)
使用Denorm Number填补其和0的空隙

指数全0 小数非0 此时指数实际为-127
规定移去浮点左侧默认的1,则指数为-126,整数为0,小数部分由significant表示
最小的Denorm Number 2-149
最大的Denorm Number 2-126 - 2-149(0.111…11 * 2-126)
注意:!!此时虽然指数全0,理论上是-127,但是计算的时候要当做-126

Limitations

  • 数字过大(Overflow)
  • 数字过小(Underflow)
  • 精度不够(Rounding)
  • 无法表示范围内全部整数(Gaps and distribution of values)
  • 算术运算未必满足结合律(Associativity)(Small + Big + Small != Small + Small + Big)
    在这里插入图片描述

在这里插入图片描述

这里260 和 2-15 差了75位,但实际上significant只有23位,会发生precision loss
在这里插入图片描述
该系统中,significant为25位,2-10与222相加会发生精度丢失,其余时候不会
所以bd计算结果为精确的(2-1+2-10)
(也算是解答了个人平时编程时候遇到的问题)

Conversion

  • FP tp Decimal
  • Scientific Number to Fp
     
     
     
     
     

C Basics

  • C语言需要编译器将其编译为architecture-specific机器语言(由01组成,不同的操作系统和CPU编译出来的内容不同
  • 可以对单独文件重新编译
  • 运行速度较快(相比于java和python)
  • 同样的文件在新的系统上必须重新编译(architecture-specific)
  • 每次对项目进行edit,run之前都需重新编译

结构体

结构体内部数据的储存是对齐
例如:32位操作系统中,4bytes为一个word,而char只需要一个byte的空间

Struct foo{
int a;
char b; 
struct foo *c;
}
  • 4 bytes for a

  • 1 byte for b

  • 3 unused bytes

  • 4 bytes for c(指针需要一个word的空间)

  • sizeof(struct foo) == 12

    为结构体分配空间时,会按照变量的顺序,按照对齐的原则,进行padding,保证对齐(4bytes放在地址为4的整数倍,2bytes在2的整数倍等等),因此变量顺序不同,结构体的size可能也不同

Union

与结构体类似,但是仅用最大元素的大小的空间,union内所有元素都使用相同的空间,本质上是用同一串bits,当做不同类型的变量

数组和指针

数组在本质上是指向头元素的指针

  int foo(int array[],unsigned int size){
     return sizeof(array);
}

这种情况下,在函数内部的环境中,编译器仅仅知道array是一个指针,并不知道这个数组的大小,所以最后返回sizeof(int*)

    int main(void){
        int a[10];
        printf("%d/n",sizeof(a));
        return 0;
}

在main函数环境内声明的数组a,这时编译器知道a是大小为10的数组,所以输出10sizeof(int)
本质上是要求这个array在当前函数的stack frame中

string

在这里插入图片描述

point arithmetic

对于指针p,p+1实际是p + sizeof§

有效的指针运算:

  • 指针加整数
  • 同数组的指针相减
  • 指针的比较(>, <, ==, !=>)
  • 将指针与NULL比较

increment and dereference

  • 前缀运算符的顺序为从右往左
    *++p,先让p自增,再返回已经自减的p所指向的元素
    ++*p,让p指向的元素自增
  • 后缀运算符(p++)优先级高于前缀运算符,但是最后生效
    *p++,因为++优先级高,所以与p绑定,但是先不生效,先返回p指向的值,之后再让p自增
    (*p)++,同样返回p指向的值,但是++与*p绑定,在返回后,p指向的值自增

C’s memory layout

在这里插入图片描述

Stack

每调用一个新函数,栈向下开辟新空间作为function的frame,内部储存各种信息(location of caller function,function arguments,space for local variables)
函数调用结束,退栈,栈顶指针(SP)回到上一个frame,原先的当前函数内容没有被删除,而是成为garbage
在这里插入图片描述

在函数返回后,函数内部变量y已经变成garbage,所以不要返回函数内变量的指针

Static Data

主要是global variables和 string literal
string literal:char *str = “abc”;双引号字符串

Code

装载C程序

Heap – Dynamic Memory Allocation

malloc(n)

在heap上开辟一个n bytes的空间(garbage 未初始化),返回头部位置的指针

  int *p = (int*) malloc(n*sizeof(int));//一个长度为n的int数组
free§

释放heap上p指针为头部的block空间

calloc

开辟空间,指定元素个数和大小

Realloc§

重新分配p指针的空间,改变空间大小
返回的是新空间头部的指针,未必是原来的p

Endian

大端和小端,对于含有多个bytes的数据在内存的存储方式

C Memory Errors

  • 使用未初始化的变量
  • 使用并未拥有的Memory(访问空指针的成员,return函数内定义的栈上的变量,为string分配内存时未考虑terminator)
  • 使用未分配的内存(下标越界,strcpy时src长度大于dest分配的长度)
  • 释放不合法的内存(释放内存未释放block head内存,比如free(p+1),或者二次释放内存)
  • 内存泄漏(申请的内存未释放)
  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Sure, I can help you with that. To convert 1.75 to floating point representation IEEE 1958, we need to follow certain steps: Step 1: Convert the decimal number 1.75 to binary. 1. Convert the integer part 1 to binary -> 1 2. Convert the fraction part 0.75 to binary: 0.75 x 2 = 1.5 (1 goes to the bit after the comma) 0.5 x 2 = 1 (1 goes to the next bit) 0 So 1.75 in binary is represented as 1.11 Step 2: Normalize the binary number The binary number is normalized by moving the decimal point to the left so that there is only one non-zero digit before the decimal point. In this case, the binary number is already normalized. Step 3: Determine the sign, exponent, and mantissa Sign: Since the number is positive, the sign bit is 0. Exponent: The exponent can be calculated using the formula: exponent = (number of bits for exponent - 1) + bias For IEEE 1958 floating point representation, the bias value is 127, and the number of bits for the exponent is 8. In this case, the exponent is 0 + 127 = 127 Mantissa: The mantissa is the fractional part of the normalized binary number. In this case, the mantissa is 1.11, which can be represented as: 1.11 = 1 + 1/2 + 1/4 = 1.5 The mantissa is then represented in binary as: 1.5 = 1.1000... So the sign bit is 0, the exponent in binary is 01111111, and the mantissa in binary is 10000000000000000000000. Putting it all together, 1.75 in floating point representation IEEE 1958 is: 0 11111111 10000000000000000000000 I hope this helps! Is there anything else I can assist you with?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值