“->”是一个整体,它是用于指向结构体子数据的指针,用来取子数据。

p=p->next ,意思是将p指向的一个结构体实例中的自数据next赋值给p


指针是一个地址,而指针变量是存放地址的变量

&a,返回a指向的内存的地址

int *p声明p为一级指针变量

另外*的用法:取值操作,即*p指针p保存的地址所对应的值

int **p声明p为二级指针变量,二级指针存储一级指针的地址


int &是定义引用,而int *是定义指针

引用本质上是常量指针

int a = 1

int *p = &b

int &b = a


变量名不占用内存,编译时


结构体:一种数据类型

struct tag {

    int a;

    char b;

} ;

struct tag t1,t2;   //不要忘记struct


struct tag{

}t1,t2;              //与上面效果相同

tag为结构体标签,abc为结构体变量,这两个都可有,也可以没有

结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针

typedef struct tag{

    …

}abc;

加上typedef后,abc就不是一个对象,abc=struct tag,表示一个类型,即abc t1,t2;

即:typedef为现有类型创建别名

也可以直接定义typedef struct _dictobject PyDictObject,将_dictobject起别名为PyDictObject


条件编译

#ifdef              判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef            与#ifdef相反,判断某个宏是否未被定义
#elif                相当于C语法中的else-if
#else              相当于C语法中的else
#endif             #if, #ifdef, #ifndef这些条件命令的结束标志

带参数的宏:#define 标识符(x1,x2,……,xn)

#define add(x1,x2)  (x1+x2)

add(1,2)

类似于lamda函数,但有函数名,可调用

宏的与函数对比的优点:宏是在预处理阶段执行,函数调用则会带来额外的开销,它需要开辟一片栈空间,记录返回地址,将形参压栈,从函数返回还要释放堆栈。其次,函数的参数必须被声明为一种特定的类型,而宏是与类型无关的


register:这个关键字请求编译器尽可能的将变量存在CPU内部寄存器中,而不是通过内存寻址访问,以提高效率。


size_t它是一种“整型”类型,里面保存的是一个整数

size_t的全称应该是size type,是“一种用来记录大小的数据类型”

size_t size=sizeof(i);//用sizeof操作得到变量i的类型的大小


sizeof()返回内存大小(对应python源码中的allocate)

strlen()返回长度,个数(对应python源码中的ob_size)


void *memset(void *s, int c, unsigned long n);

memset函数:将指针变量 s 所指向的前 n 字节的内存单元用一个“整数” c 替换,注意 c 是 int 型。s 是 void* 型的指针变量,所以它可以为任何类型的数据对象进行初始化。


PyObject_GC_New与malloc,除了分配内存外,还与垃圾回收机制相关