C Linux内核分配实现中的指针计算

C Linux内核分配实现中的指针计算,c,linux,pointers,caching,C,Linux,Pointers,Caching,参考指南第8.2.12章。分配楼板对象时,有以下代码: void * kmem_cache_alloc(kmem_cache_t *cachep, int flags) { unsigned long save_flags; void *objp; struct array_cache *ac; local_irq_save(save_flags); ac = cache_p->array[smp_processor_id()];

参考指南第8.2.12章。分配楼板对象时,有以下代码:

void * kmem_cache_alloc(kmem_cache_t *cachep, int flags)
{  
    unsigned long save_flags;  
    void *objp;  
    struct array_cache *ac;  
    local_irq_save(save_flags);  
    ac = cache_p->array[smp_processor_id()];  
    if (ac->avail) 
    {  
       ac->touched = 1;
       objp = ((void**)(ac+1))[--ac->avail];  
    } else  
        objp = cache_alloc_refill(cachep, flags);  
    local_irq_restore(save_flags);  return objp; 
}
现在,根据指南,查看行
((void**)(ac+1))[--ac->avail]

因为本地缓存阵列存储在ac描述符之后, ((void**)(ac+1))[--ac->avail]获取该自由对象的地址,并 降低ac->avail的值

但是,由于
ac
是指向类型
struct array\u cache
的指针,该类型包含以下字段(按此顺序)-

[type]无符号整数

[姓名]有效

[说明]指向本地缓存中可用对象的指针数。 该字段还充当缓存中第一个可用插槽的索引

[type]无符号整数

[姓名]限额

[说明]本地缓存的大小,即本地缓存中的最大指针数

[type]无符号整数

[名称]批次计数

[说明]本地缓存重新填充或清空的块大小

[type]无符号整数

[姓名]感动

[说明]如果最近使用了本地缓存,则标志设置为1

因此,
ac+1
将指向
avail
值的第二个字节(或相反端的第三个字节),这毫无意义

我弄错了吗?

是的,你弄错了

指针算法是根据所指向的类型而不是字节来计算的

考虑这一点:

int a[2], *p = a;

++p;
这使得
p
等于
&a[1]
,而不是
((char*)&a[0])+1
。因此,该增量将实际指针值增加
sizeof*p
,即
sizeof(int)

请记住,数组索引是通过指针算法工作的,因此也必须采用这种方式


在C语言中实现各种数据结构时,通常会有一个内存块,该内存块从某个
struct
的实例开始,然后是其他数据(通常由
struct
中的字段描述)。该数据的第一个字节位于
sp+1
,假设
sp
是指向
struct
的指针,就像您显示的代码一样。

您能提供这种类型编码的更多常用用法和示例吗?我希望使用另一个结构来包装这个数据,这个包装结构将有一个指向另一个结构的指针字段,还有一个指向另一个数据的字段。这条路很干净。为什么要使用这样的代码?它有什么好处?