指针与内存对齐到底是什么鬼?( 三 )


 

  • 而*lock = node;的含义就是:将符号node的值赋给*lock符号的值 。
 
指针与内存对齐到底是什么鬼?

文章插图
*就表示切换符号
 
  • 所以,不管多少个*都可以递归化简了 。
  • 比如:T *** t = &node;这个表达式:
 
指针与内存对齐到底是什么鬼?

文章插图
图解三重指针
看看Linux中一些指针操作——链表操作//链表头指针struct wake_q_head {struct wake_q_node *first;struct wake_q_node **lastp;struct wake_q_node {struct wake_q_node *next;//初始化链表头static inline void wake_q_init(struct wake_q_head *head)head->first = WAKE_Q_TAIL; // #define WAKE_Q_TAIL ((struct wake_q_node *) 0x01)head->lastp = &head->first;//添加新元素static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task)struct wake_q_node *node = &task->wake_q;* Atomically grab the task, if ->wake_q is !nil already it means* it's already queued (either by us or someone else) and will get the* wakeup due to that.* In order to ensure that a pending wakeup will observe our pending* state, even in the failed case, an explicit smp_mb() must be used.smp_mb__before_atomic();if (unlikely(cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL)))return false;* The head is context local, there can be no concurrency.*head->lastp = node;head->lastp = &node->next;return true;
指针与内存对齐到底是什么鬼?

文章插图
wake_q_init
指针与内存对齐到底是什么鬼?

文章插图
添加第一个元素
 
  • first指向task_struct中的成员wake_q;指向队列的第一个元素;
  • lastp指向task_struct的成员wake_q的成员next;next也是一个指针;
 
再添加一个元素:
指针与内存对齐到底是什么鬼?

文章插图
再添加一个元素
 
  • first始终指向第一个元素;
  • lastp始终指向最后一个元素的next符号 。
关于指针你只要记住
  • 看到表达式先找到符号;
  • 符号就等同于内存空间;
  • 符号有地址与值两个维度的属性,脑子中画一个上面的图来帮助理解;
  • *、->这两个操作符的本质就是从一个符号切换到另一个符号,从一块内存切换到另一块;
  • &与=这两个操作符号的本质就是获取内存值 。
理解了指针就能更进一步理解内存对齐了 
内存对齐应该叫做内存的虚拟地址对齐,讲的是如果我们为一个数据结构——抽象来讲就是一块内存——分配一个地址的时候,需要满足的规则 。那么规则有哪些?我们可以先列出来:
 
  • 基本数据类型(int,short,char,byte,long,float,double)的变量的首字节地址必须是类型字节数的整数倍;
  • 结构体(首字节地址)必须是最大成员变量数据类型的整数倍(编译器维护);
  • 结构体中每个成员变量的首字节地址,必须是成员类型的整数倍,如果不是,则编译器填充实现;
  • 结构体的总体长度必须是最大成员变量类型长度的整数倍,如果不是,编译器在结构体最后一个字节末尾填充0实现 。
 
下面具体说明下这些规则都是什么意思 。
基本数据类型的首地址必须是类型字节数的整数倍
还是这个代码片段:
#include#includetypedef struct test {short b;int a;} Test;int main(){printf("Test size is:%ldn",sizeof(Test));Test* t_ptr = (Test*)malloc(sizeof(Test));t_ptr->a = 1;t_ptr->b = 2;printf("a is:%dn",t_ptr->a);printf("b is:%dn",t_ptr->b);
为了迎合这个问题,我们调换了a,b符号在结构体中出现的顺序 。之前我们假设sizeof(Test)是6,但是真的如此吗?我们看看运行的结果:


推荐阅读