【发布时间】:2021-03-03 14:30:20
【问题描述】:
我正在编写一些库代码,向用户公开一个 const 指针,但在某些操作期间,我需要更改此指针指向的位置(幕后 switcheroo 技巧)。我必须在不遇到 UB 或严格混叠违规的情况下解决此问题的一个想法是使用带有 const 成员的联合:
// the pointed-to objects (in production code, these are actually malloc'd blocks of mem)
int x = 0, y = 7;
typedef union { int * const cp; int * p; } onion;
onion o = { .cp = &x };
printf("%d\n", *o.cp); // <---------------------- prints: 0
o.p = &y;
printf("%d\n", *o.cp); // <---------------------- prints: 7
但我不知道这是否定义明确......有人知道它是否(或不是)以及为什么?
编辑:我想我提到我正在建立一个图书馆,因为很多人要求澄清这方面的细节,而不是回答我想要的更简单的问题。
下面,我通过将类型从 int* 更改为 int 来简化代码,现在我的问题很简单:以下定义明确吗?
typedef union { int const cp; int p; } onion;
onion o = { .cp = 0 };
printf("%d\n", o.cp); // <---------------------- prints: 0
o.p = 7;
printf("%d\n", o.cp); // <---------------------- prints: 7
【问题讨论】:
-
向第 2 位回答并不得不隐藏他们的答案的人道歉:我的帖子中有一个错字,大大改变了问题
-
当您使用“常量指针”时,您是专门使用
int * const cp来表示cp是const还是您想要const int * cp表示cp指向const数据? -
我的意思是:
int * const cp(错字是:const int * cp) -
请在您的问题中显示您的库如何公开指针。我猜你想实现指针只能在库内部修改,而不能由库的用户修改。我建议使用将指针返回给库用户的 getter 函数,而不是提供全局指针变量。您应该考虑到,当您在内部更改旧指针值时,使用该库的代码可能仍具有旧指针值的副本。这也可能由于编译器优化而发生,因为
const告诉编译器该值以后不会更改。 -
@Bodo 好问题:我知道指向结构或联合的指针可以转换为指向其第一个成员的指针,反之亦然(这让我意识到联合成员的顺序是颠倒的...我将在此评论后解决此问题)。我在想我可以将工会的地址传递给第一个成员的地址。不知道那会是什么样子......也许:
(int * const *)&myunion
标签: c pointers language-lawyer undefined-behavior unions