struct宏定义一些用法

typedef struct {
    int name;
    int service;
    int server;
    char buf[0];
} item;
#define OFFSET(A, B) (int)&(((A*)0)->B)
#define CONTAINER(PTR, TYPE, FIELD) (TYPE*)((char*)PTR-OFFSE    T(TYPE, FIELD))

第一个,获取变量偏移地址;
第二个,获取变量对应结构体的地址。
 

程序在内存中的分布

在现代的操作系统中,当我们说到内存,往往需要分两部分来讲:物理内存和虚拟内存。从硬件上讲,虚拟空间是CPU内部的寻址空间,位于MMU之前,物理空间是总线上的寻址空间,是经过MMU转换之后的空间。
一般我们所说的程序在内存中的分布指的就是程序在虚拟内存中的存储方式。
从低地址到高地址,可分为下面几段:
预留内存地址
(操作系统维护的内存地址,不可访问)
程序代码区(只读,存代码和一些其他的东西);
data段(存初始化的全局变量和static变量,另外还有文字常量区,常量字符串就是放在这里,程序结束后有系统释放);
bss段(存未初始化的全局变量和static变量);
(由低地址向高地址增长,一般new和malloc分配,由程序员分配释放);
共享库文件(调用的库文件,位于堆和栈之间);
(由高地址向低地址增长,和堆的增长方式相对,对不同的OS来说,栈的初始大小有规定,可以修改,目前默认一般为2M,由编译器自动分配释放);
再上面存的都是操作系统和内核调用的一些内存地址
如图所示:

C/C++ 宏

宏的一些用法:
1、#和##
#符号把一个符号直接转换为字符串,例如:
#define STRING(x) #x
const char *str = STRING( test_string ); str的内容就是”test_string”,也就是说#会把其后的符号直接加上双引号。
符号会连接两个符号,从而产生新的符号(词法层次),例如:
#define SIGN( x ) INT_##x
int SIGN( 1 ); 宏被展开后将成为:int INT_1;
2、变参宏 可以使你自定义类似的宏
#define LOG( format, … ) printf( format, __VA_ARGS__ )
LOG( “%s %d”, str, count );     __VA_ARGS__是系统预定义宏,被自动替换为参数列表。
3、宏调用自己
为了防止宏无限递归展开,当宏展开遇到自己时,就停止展开。
#define TEST(X) (X+TEST(X))
则TEST(1) 最终会展开成1+TEST(1)