## 动力学知识库

`int main(void){ 834c: e24dd020 sub sp, sp, #32 ; 0x20 //sp指针指向地址最低位，栈增长的最大界限位置 union { struct thread_info thread_info; unsigned long stack[8]; }uni_x; uni_x.thread_info.a = 1; 8350: e3a03001 mov r3, #1 ; 0x1 8354: e58d3000 str r3, [sp] //这里thread_info.a处在地址最低位 uni_x.thread_info.b = 2; 8358: e3a03002 mov r3, #2 ; 0x2 835c: e58d3004 str r3, [sp, #4] //thead.b的位置 uni_x.stack[7] = 7; //将stack数组的index由高到底操作，实现向低地址方向的栈增长 8360: e3a03008 mov r3, #7 ; 0x7 8364: e58d3020 str r3, [sp, #28] uni_x.stack[6] = 6; //7,6...1,0，当然这里要考虑thread_info的大小，至少uni_x.stack[0]会覆盖thread_info 8368: e3a03007 mov r3, #6 ; 0x6 836c: e58d301c str r3, [sp, #24] return 0; 8370: e3a03000 mov r3, #0 ; 0x0}`
“一个结构，两种用法”，重要的是思想，细细咀嚼，回味无穷。

`#define mem_to_obj(ptr, type, member) / ( (char*)ptr - (char*)(&((type*)0)->member) )int main(void){ struct test_struct { int a; int b; }; struct test_struct test; test.a = 1; test.b = 2; int *bp = &test.b; struct test_struct *p = &test; struct test_struct *q = NULL; q = mem_to_obj(&test.b, struct test_struct, b); //通过结构体中b地址，找到该结构体的地址 return 0;}`

` q = mem_to_obj(&test.b, struct test_struct, b);  q = ( (char*)&test.b - (char*)(&((struct test_struct*)0)->b) );`
瞧一下汇编：
`int main(void){ 834c: e24dd018 sub sp, sp, #24 ; 0x18 int a; int b; }; struct test_struct test; test.a = 1; 8350: e3a03001 mov r3, #1 ; 0x1 8354: e58d3004 str r3, [sp, #4] test.b = 2; 8358: e3a03002 mov r3, #2 ; 0x2 835c: e58d3008 str r3, [sp, #8] int *bp = &test.b; 8360: e28d3004 add r3, sp, #4 ; 0x4 8364: e2833004 add r3, r3, #4 ; 0x4 8368: e58d300c str r3, [sp, #12] struct test_struct *p = &test; 836c: e28d3004 add r3, sp, #4 ; 0x4 8370: e58d3010 str r3, [sp, #16] struct test_struct *q = NULL; 8374: e3a03000 mov r3, #0 ; 0x0 8378: e58d3014 str r3, [sp, #20] q = mem_to_obj(&test.b, struct test_struct, b); 837c: e28d3004 add r3, sp, #4 ; 0x4 //r3已经是test_struct的地址，但之后的两条汇编，感觉无厘头 8380: e2833004 add r3, r3, #4 ; 0x4 //在试着增加test_struct中的变量后发现，仍然是add x，再sub x 8384: e2433004 sub r3, r3, #4 ; 0x4 //可能编译器不是万能的缘故，何况mem_to_obj也得浪费你1s的理解时间 8388: e58d3014 str r3, [sp, #20] return 0; 838c: e3a03000 mov r3, #0 ; 0x0}`

arr[0]是什么？到底有还是没有？

`int main(void){ 8380: e52de004 push {lr} ; (str lr, [sp, #-4]!) 8384: e24dd014 sub sp, sp, #20 ; 0x14 struct test_struct { int a; int b; int c[0]; // c是个指针，准确的说是半个指针，或者就是个int * const c，你懂de }test; int d = 8; // 根据编译器对变量的分配规则，int d自然排在了test_struct结构体之后，而且是紧挨着 8388: e3a03008 mov r3, #8 ; 0x8 838c: e58d300c str r3, [sp, #12] printf("1: d = %d/n", d); // 这里d当然等于8 8390: e59f003c ldr r0, [pc, #60] ; 83d4 <main+0x54> 8394: e59d100c ldr r1, [sp, #12] 8398: ebffffc8 bl 82c0 <_init+0x48> test.a = 1; 839c: e3a03001 mov r3, #1 ; 0x1 83a0: e58d3004 str r3, [sp, #4] test.b = 2; 83a4: e3a03002 mov r3, #2 ; 0x2 83a8: e58d3008 str r3, [sp, #8] //test.c = NULL; /*作为半个指针，当然也就是不能被赋值了，若赋值，就如下报错*/`
` /*main.c:14:12: error: incompatible types when assigning to type ‘int[]’ from type ‘void *’*/`
` test.c[0] = 10; // 虽不能被赋值，但却能指引其他地儿赋值：给紧挨着test_struct的PP的地方赋值10 83ac: e3a0300a mov r3, #10 ; 0xa 83b0: e58d300c str r3, [sp, #12] printf("2: d = %d/n", d); // 很不幸，d就在test_struct的PP的地方，d被间接改变 83b4: e59f001c ldr r0, [pc, #28] ; 83d8 <main+0x58> 83b8: e59d100c ldr r1, [sp, #12] 83bc: ebffffbf bl 82c0 <_init+0x48> return 0; 83c0: e3a03000 mov r3, #0 ; 0x0}`