open-courses
  • 公开课笔记
  • CMU 15-445/645 Database Systems
    • Relational Data Model
    • Advanced SQL
    • Database Storage
    • Buffer Pools
    • Hash Tables
    • Tree Indexes
    • Index Concurrency Control
    • Query Processing
    • Sorting&Aggregations
    • Join Algorithms
    • Query Optimization
    • Parallel Execution
    • Embedded Database Logic
    • Concurrency Control Theory
    • Two Phase Locking
    • Timestamp Ordering Concurrency Control
    • Multi-Version Concurrency Control
    • Logging Schemes
    • Database Recovery
    • Introduction to Distributed Databases
    • Distributed OLTP Databases
    • Distributed OLAP Databases
  • UCB - CS162
    • OS intro
    • Introduction to the Process
    • Processes, Fork, I/O, Files
    • I/O Continued, Sockets, Networking
    • Concurrency: Processes & Threads
    • Cooperating Threads, Synchronization
    • Semaphores, Condition Variables, Readers/Writers
    • Scheduling
    • Resource Contention & Deadlock
    • Address Translation, Caching
    • File System (18,19,20)
    • Distributed Systems, Networking, TCP/IP, RPC (21,22)
    • Distributed Storage, Key-Value Stores, Security (23)
    • Security & Cloud Computing (24)
    • Topic: Ensuring Data Reaches Disk
  • MIT - 6.006
    • Sequence and Set Interface
    • Data Structure for Dynamic Sequence Interface
    • Computation Complexity
    • Algorithms and Computation
    • Structure Of Computation
    • Graph & Search
    • Tree & Search
    • Weighted Shortest Paths
    • String Matching, Karp-Rabin
    • Priority Queue Interface & Implementation
    • Dictionary Problem & Implementation
    • Sorting
    • Dynamic Programming
    • Backtracking
    • Self-Balancing Tree
  • MIT - 6.824
    • 2PC & 3PC
    • Introduction and MapReduce
    • RPC and Threads
    • Primary/Backup Replication
    • Lab: Primary/Backup Key/Value Service
    • Google File System (GFS)
    • Raft
    • Lab: Raft - Leader Election
    • Lab: Raft - Log Replication
  • Stanford-CS107
    • 原始数据类型及相互转化
    • 指鹿为马
    • 泛型函数
    • 泛型栈
    • 运行时内存结构
    • 从 C 到汇编
    • 函数的活动记录
    • C 与 C++ 代码生成
    • 编译的预处理过程
    • 编译的链接过程
    • 函数的活动记录续、并发
    • 从顺序到并发和并行
    • 信号量与多线程 1
    • 信号量与多线程 2
    • 复杂多线程问题
    • 函数式编程 - Scheme 1
    • 函数式编程 - Scheme 2
    • 函数式编程 - Scheme 3
    • 函数式编程 - Scheme 4
    • 函数式编程 - Scheme 5
    • Python 基础
  • MIT - 6.001 - SICP
    • 什么是程序
    • 程序抽象
    • 替代模型
    • 时间/空间复杂度
    • 数据抽象
    • 高阶函数
    • Symbol
    • 数据驱动编程与防御式编程
    • 数据抽象中的效率与可读性
    • 数据修改
    • 环境模型
    • 面向对象-消息传递
    • 面向对象 - Scheme 实现
    • 构建 Scheme 解释器
    • Eval-Apply Loop
    • Normal Order (Lazy) Evaluation
    • 通用机
    • 寄存器机器
    • 子程序、栈与递归
    • 在寄存器机器中执行
    • 内存管理
  • MIT - 6.046
    • Randomized Algorithms
    • Skip Lists
  • System Design
    • Twitter
    • Cache Consistency & Coherence
  • DDIA 笔记
    • Replication
    • Transactions
    • The Trouble with Distributed Systems
    • Consistency & Consensus
  • Papers We Love
    • Consistent Hashing and Random Trees (1997)
    • Dynamic Hash Tables (1988)
    • LFU Implementation With O(1) Complexity (2010)
    • Time, Clocks, and the Ordering of Events in a Distributed System (1978)
    • Dapper, a Large-Scale Distributed Systems Tracing Infrastructure (2010)
    • Gorilla: A Fast, Scalable, In-Memory Time Series Database (2015)
  • Release It 笔记
    • Anti-patterns & Patterns in Microservice Architecture
  • Database Design
    • Log Structured Merge (LSM) Tree & Usages in KV Stores
    • Prometheus
Powered by GitBook
On this page
  1. Stanford-CS107

指鹿为马

第三课

只要敢玩,理论上你可以随意指定指针类型愚弄 C 编译器,让它相信你所说的都是真的,你说鹿是马,C 编译器便对此坚信不疑,我们来看看这门 “指鹿为马” 的艺术:

指 int 为 float

int i = 37;
float f = *(float *)&i;
// &i            => 取 i 的地址,类型为 int *
// (float *)&i    => 指鹿为马 -- 假装它是个 float *
// *(float *)&i    => 取出 float* 所指的值,类型为 float
// 以上实现了指 int 为 float,因为本质上它们都是 4 个字节排列在一起

printf("%f \n", f); // 0.000000 

// i: 00000000 00000000 00000000 00100101
// f: 00000000 00000000 00000000 00100101

// 1.00000000xxxxxx * 2^(-127) 约等于 0

指 float 为 short

float f = 7.0;
short s = *(short *)&f;
// &f             => 取 f 的地址,类型为 float *
// (short *)&f     => 指鹿为马 -- 假装它是个 short *
// *(short *)&f => 取出 short * 所指的值,类型为 short

printf("%s \n", s); // 输出结果视 endianness 而定

// Big Endian:
// f: 01000000 11100000 00000000 00000000
// s: 01000000 11100000                 

// Little Endian:
// f: 01000000 11100000 00000000 00000000
// s:                   00000000 00000000

指 double 为 char

double d = 3.1416;
char ch = *(char *)&d;
// &d             => 取 d 的地址,类型为 double *
// (char *)&d    => 指鹿为马 -- 假装它是个 char *
// *(char *)&d     => 取出 char * 所指的值,类型为 char

printf("%c \n", ch); // 输出结果视 endianness 而定

// Big Endian:
// d:  01000000 | 00001001 | 00100001 | 11111111 | 01001000 | 11101000 | 10100111
// ch: 01000000

// Little Endian:
// d:  01000000 | 00001001 | 00100001 | 11111111 | 01001000 | 11101000 | 10100111
// ch:                                                                   10100111

数组与指针算术(pointer arithmetic)

int array[10];
// array 等价于第一个元素的地址
array === &array[0]
array + k === &array[k]
*array === array[0]
*(array + k) === array[k]

// 指针算术是指,对指针做加减法时,会自动乘上指针所指数据类型所占的字节数

int array[5]; array[3] = 128;
((short *)array)[6] = 2;
// array             => 数组起始地址,类型为 int *
// (short *)array     => 指鹿为马 -- 假装它是个 short *,即 array 中的元素为 short 类型
// (short *)array[6]=> 将 short array 的第六个元素改成 2

// Big Endian:
// array:              => [][][][00000000 00000000 00000001 00000000][]
// (short *)array[6]=2 => [][][][00000000 00000010 00000001 00000000][]
// 输出 768

// Little Endian:
// array:              => [][][][00000000 00000000 00000001 00000000][]
// (short *)array[6]=2 => [][][][00000000 00000000 00000000 00000010][]
// 输出 2

结构体

struct student {
    char *name;
    char suid[8];
    int numUnits;
};

int main(int argc, char **argv) {
    struct student pupils[4];           // 初始化了长度为 4 的 student 结构体数组
    pupils[0].numUnits = 21;            // 赋予第一个 student 的 numUnits 字段
    pupils[2].name = strdup("Adam");    // 将第三个 student 的 name 指向 heap 中初始化的一个字符串 "Adam\0"
    pupils[3].name = pupils[0].suid + 6;// 将第四个 student 的 name 指向第一个 student 的 suid 往后移 6 位之处
    strcpy(pupils[1].suid, "40415xx");  // 将字符串 "40415xx" 放入第一个 student 的 suid 中
    strcpy(pupils[3].name, "123456");   // 将字符串 "123456" 放入第四个 student 的 name, 即第一个 student 的 suid 往后移 6 位之处
}

如下图所示:

参考资料

Previous原始数据类型及相互转化Next泛型函数

Last updated 6 years ago

Stanford CS107: lecure 3
Github: ZhengHe-MD - lecture codes