gpt4 book ai didi

c - 以“可能”在尽可能多的系统上工作的方式读取低指针位

转载 作者:行者123 更新时间:2023-11-30 17:06:27 26 4
gpt4 key购买 nike

看起来指针的低位为 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 类型,例如:

union Maybe_Terminator_Pointer {
uintptr_t flags;
type1* pointer1;
type2* pointer2;
...
};

...然后使用它,如果它有帮助的话。排除 char* 是可以的,因为它们当然不算数。

<小时/>

因此,这里的一个额外的类型双关问题是:用于进行终止测试的指针是一个 Item*,并且执行检查的例程不知道是哪种指针some-pointer 是具体的。

我想知道什么(如果有的话)是能够移植和编译这样一个技巧的最好的赌博。这包括将指针转换为 union 、#ifdef'ing 机器的字节顺序以及从带有位的字节中获取 char* 等。如果有人有经验,无论什么都可能可能有效或猜测。

想象一下,对于您的案例来说,减少大量数据是值得的。并且你有一个备份场景,如果人们编译发现这个技巧在某个地方不起作用......#ifdef 可以使用全尺寸的项目作为终结符并浪费额外的空间。所以想知道是否有任何技巧可以让这个明显违反标准的技巧有更好的机会在更多系统上工作。

最佳答案

( self 回答以提供更多信息并让人们发现我的替代方案的任何潜在问题。)

So wondering if there are any tips on to make this obviously-standards-violating trick have a better chance of working on more systems.

<小时/>

提示一(根据评论)是如果您能找到其他方法,请不要这样做。

例如,“你”提到了这个布局:

[(flags field1 field2...) (flags field1 field2...) some-pointer stuff stuff...]

但是“stuff stuff”中是否有任何东西不是指针——也许是无聊的旧整数,已知是偶数——你可以这样做同样的伎俩?如果是这样,为什么不重新排序:

[(flags field1 field2...) (flags field1 field2...) even-uintptr_t stuff...]

这样,无论您是否从 Item 中读取 flags ,它都将是相同的类型。如果你环顾一下像指针这样不透明的东西,你可能会发现当前代码中明显的不透明数字总是偶数......例如,测量聚合的许多字节计数是你可能保证的东西为 % 2 = 0

<小时/>

技巧二适用于上述替代方案 - 也许也有助于打破标准指针版本。确保在写入值时通过“别名”指针,并且不要直接通过 .->.

写入字段。

编译器不需要确保字段上两个不同结构之间的内存一致性,仅仅因为它们是相同的类型。假设 struct Auintptr_t field_a 开头,struct Buintptr_t field_b 开头,并且您放置一个指针到同一地址。如果您执行 some_a->field_a = value;,那么从该地址处的 some_b->field_b 指针读回很可能看不到该更新,因为编译器不会不要期望您通过 A 指针写入 B 字段。

因此通过指针来进行写入。像 uintptr_t *alias = &some_a->field_a;*alias = value 这样的东西将强制与任何整数的连续读取保持一致性(!)(对指针这个属性的性能后果不满意 is why restrict exists 。如果这个技巧要起作用,它只能通过利用指针的非限制行为来实现。)

(!) - 我认为您只需通过指针进行写入,而不是读取,但也许有人可以提供见解。

关于c - 以“可能”在尽可能多的系统上工作的方式读取低指针位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34704083/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com