【发布时间】:2016-01-10 09:52:01
【问题描述】:
似乎指针的低位为 0 或多或少是可移植的 (可移植显然并不意味着“标准”,但人们可以摆脱它并且可以在某些方面使用它来获得一些优势在某些情况下,希望通过编译开关禁用)。
想弄巧成拙的项目都用过,倒数第二位运气不太好:
How portable is using the low bit of a pointer as a flag?
但是假设一个人不想仅仅将一点数据插入到已知类型的指针中。你希望你能做的是使用低位 0 来允许指针类型作为终止符执行“双重任务”。
所以你的物品看起来像这样:
struct Item {
uintptr_t flags; // low bit zero means "not an item"
type1 field1;
type2 field2;
...
};
那么您希望某些项目容器看起来像这样:
[(flags field1 field2...) (flags field1 field2...) some-pointer stuff stuff...]
因此,您将摆脱“沉没成本”(假设数据结构中的一些内部管理指针用于其他目的)为您终止。
更新:为了更清楚地了解情况:这是控制代码库和结构的地方。因此,像这样使用的结构中的任何指针都可以声明为联合类型,例如:
union Maybe_Terminator_Pointer {
uintptr_t flags;
type1* pointer1;
type2* pointer2;
...
};
...然后使用它,如果它有帮助的话。排除char*s 很好,因为它们当然不会计算在内。
所以这里一个额外的类型双关语问题是:用于执行终止测试的指针是Item*,而执行检查的例程不知道具体是哪种类型的指针some-pointer。
我想知道如果有的话,最好的赌注是能够移植和编译这样的技巧。这包括将指针转换为联合,#ifdef'ing 机器的字节顺序并从带有位的字节中获取 char* 等等。如果有人有经验,无论更多可能工作或猜测。
想象一下,为您的案例付出努力是值得的,因为它会减少大量数据。如果人们在编译时发现该技巧在某处不起作用,那么您有备用方案......#ifdef 可以使用完整尺寸的项目作为终止符并浪费额外的空间。所以想知道是否有任何技巧可以让这个明显违反标准的技巧更有可能在更多系统上工作。
【问题讨论】:
-
没有“最不便携”的方式。不需要对齐的架构,或者如果您使用
packedstructs,则 LSB 根本不可用。除非你有真正的内存限制,否则额外的代码开销是不值得的。如果你有内存问题,你有一个特定的系统。这仍然远远超出了 C 标准。 -
@Olaf 我不知道你是否特别说这种情况比链接帖子中的可能性要小得多......例如引用 “在“理论”中:据我所知,这是未定义的行为。在“现实”中:它可以在日常 x86/x64 机器上工作,也可能在 ARM 上工作?” 我的问题更多关于“现实”方面;特别是因为如果环境的细节没有解决,这可以(正如我所说的)在编译中被关闭,所以如果写这个(最好赔率,基本上)
-
我声明了它不起作用的场景,包括 x86 和 ARM。在 8 位架构上,它会严重失败。
-
不超过widewr架构。但这是一个完全不相关的主题。
-
允许以这种方式滥用“any 指针类型”的目标是极其不现实的。例如,大多数体系结构对
char指针使用all 指针位。因此,至少,您只能对指向其地址保证低位为 0 且不可移植的数据类型的指针执行此操作。
标签: c pointers c89 termination type-punning