【问题标题】:Remove constness of a pointer in a struct in C删除 C 结构中指针的常量
【发布时间】:2012-11-15 21:04:57
【问题描述】:

所以我需要从 C 中的一些变量中删除 constness(我知道我在做什么)。所以我写了一个小宏 (UNCONST),它可以让我为 const 值分配一个新值。这对于像int 这样的普通变量非常有效。但这不适用于指针。所以我不能让一个指针使用我的宏UNCONST 指向不同的位置,而不会收到编译器警告。

这里有一个小测试程序unconst.c

#include <stdio.h>

#define UNCONST(type, var, assign) do { \
  type* ptr = (type*)&(var); \
  *ptr = (assign); \
} while(0)

struct mystruct {
  int value;
  char *buffer;
};

int main() {
  // this works just fine when we have an int
  const struct mystruct structure;
  UNCONST(int, structure.value, 6);
  printf("structure.value = %i\n", structure.value);

  // but it doesn't when we have an char *
  char *string = "string";
  UNCONST(char *, structure.buffer, string);
  printf("structure.buffer = %s\n", structure.buffer);

  // this doesn't work either, because whole struct is const, not the pointer.
  structure.buffer = string;
  printf("structure.buffer = %s\n", structure.buffer);
}

编译和执行

$ LANG=en gcc -o unconst unconst.c
unconst.c: In function ‘main’:
unconst.c:21:3: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
unconst.c:25:3: error: assignment of member ‘buffer’ in read-only object

有没有办法优化我的宏,让这个警告不出现?

【问题讨论】:

  • 你知道你可以写 string1 = string2 吗?
  • @Kylo 我没有,但似乎我简化了我的代码太多,我需要编辑问题。
  • 使用int 的第一段调用未定义的行为。编译器可能会合法地将i 放在只读内存中,然后您可能会遇到崩溃或其他意外结果(例如printf() 打印5 而不是6)。您依赖那里的实现的特殊性。因此,当您切换平台或编译器时,预计会出现问题。
  • 我的 2c:如果你经常需要“unconst”然后计划那个宏......难道不是其他地方有什么奇怪的地方吗?
  • 堆栈溢出经验法则 #4:OP 说“我知道我在做什么”,但他们不知道。

标签: c pointers gcc macros constants


【解决方案1】:

问题在:

const char *string1 = "string1";
UNCONST(char *, string1, string2);

string1不是真正的const,可以赋值,而是指向一个const字符数组。

其实是这样的:

string1 = string2;

编译得很好。

另一件事是如果你想复制数组。然后我会把你的宏写成这样:

#define UNCONST(type, var) (*(type*)&(var))

所以:

UNCONST(int, i) = 42;

要复制字符数组,您可以这样做:

strcpy(UNCONST(char**,string1), string2);

脚注:实际上我觉得这个宏没用:我发现:

*(int*)&i = 42;

像这种操作一样繁琐。

【讨论】:

  • 不错的答案,但我使用了一个简化很多的代码示例。所以我编辑了这个问题。 char 指针实际上位于 const struct
  • FreeBSD 使用这个宏:#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
【解决方案2】:

如果 string1 应该是一个 const 指针(而不是一个指向 const 数据的非 const 指针),这样写:

char * const ptr = "foo";

const char * const ptr = "foo";

如果你正确声明了你的指针,也许(我还没有测试过)你的 UCONST 宏会像你预期的那样工作。

【讨论】:

    猜你喜欢
    • 2012-04-22
    • 1970-01-01
    • 2017-05-30
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 2013-12-06
    • 1970-01-01
    • 2021-10-15
    相关资源
    最近更新 更多