从malloc的自定义内存分配器中,考虑以下两个宏:
#define GET_HDR(bp) (*(int *)((int *)(bp) – 1))
#define GET_HDR(bp) (*(int *)((char **)(bp) – 1))
此处bp
是void
指针。
GET_HDR(bp)
用于获取HEADER
的内容,该内容是在空指针bp
之前存储的4字节块。这里第一个宏取空指针bp
,将它转换为int并减去1以将指针移回4字节,使其指向HEADER
块,然后取消引用指针以赋值{{ 1}}阻止。
但是第二个宏怎么做呢?指针如何被操纵以达到HEADER
阻止?
答案 0 :(得分:3)
宏可能假定char *
的大小与int
相同。
(
*(int *)( /* Treat result as pointer to int and dereference */
(char **)(bp) /* bp is cast to a pointer to (char *) */
– 1 /* take bp back sizeof(char *) bytes (presumably also 4) */
)
)
答案 1 :(得分:1)
指针是指针,但指针算术取决于type
。如果int
和char *
的大小不同,那么当减去1时,宏在内存中的偏移量不会相同。当您再次转换为*(int *)
以获取值时,你最终可能得到不同的结果。
使用指针运算时必须小心。如果int
和char *
在系统上不同,则会出现问题。例如,x86_64
指针大小为8-bytes
,int
的大小为4-bytes
。 x86
指针大小为4-bytes
,int
的大小也为4-bytes
。
当你施放(int *)(bp) - 1
时,你要求任何系统上的指针 - 之前 - bp
(或4-bytes
之前bp
4-byte int
- 涵盖大多数系统)。但是,(char **)(bp) - 1
上的x86_64
投标会在8-bytes
之前询问bp
之前的指针4-bytes
与x86
之前的6.5.6
。这可能会导致问题。
您必须小心地在宏中转换为不同类型,并避免违反严格别名规则。请参阅C标准的6.5.7
和typedef void (^ saveBlock_block_t )(WhateverYourReturnObjectType *obj);
@interface DetailTableViewCell : UITableViewCell
- (void)configureCell:(NSString *)textFieldVal
cellBlock:(saveBlock_block_t)cellBlock;
@end
部分。这里没有涉及,但如果您依赖宏中的多个强制转换,则可能会掩盖违规行为。