C99标准的第7.18.1.4节规定:
以下类型指定无符号整数类型,其属性是任何有效指针
void都可以转换为此类型,然后转换回指针void,结果将与原始指针进行比较:
uintptr_t
这是否意味着只有void *类型可以转换为uintptr_t和返回而不改变原始指针的值?
特别是,我想知道是否需要使用以下代码uintptr_t:
int foo = 42;
void * bar = &foo;
uintptr_t baz = bar;
void * qux = baz;
int quux = *(int *)qux; /* quux == foo == 42 */
Run Code Online (Sandbox Code Playgroud)
或者,如果C99标准保证这个更简单的版本产生相同的效果:
int foo = 42;
uintptr_t bar = &foo;
int baz = *(int *)bar; /* baz == foo == 42 */
Run Code Online (Sandbox Code Playgroud)
void *在转换指针之前是否需要转换uintptr_t,反之亦然?
const Boo *constBoo;
Boo *nonConstBoo;
nonConstBoo = ((union {const Boo *_q; Boo *_nq;})constBoo)._nq;
Run Code Online (Sandbox Code Playgroud)
以上构造在C11中是有效的,还是只有GCC/clang扩展,您可以以这种方式将指针强制转换为匿名联合?如果它无效,是否有其他方法可以在有效的C11代码中编写等效表达式?
目的是模拟C++ const_cast,它将与C11兼容并提供一些基本类型的安全性.从const到非const指针的显式转换将使用-Wcast-qual选项触发警告,这是不合需要的.
编辑:问题在这里深入解释(谢谢@Eric Postpischil).这似乎是海湾合作委员会的一个错误.
首先,让我从一些上下文开始:我正在编写的代码是使用我无法更改的API,在GCC版本上我无法更改,使用编译标志我不允许删除,当我'完成它必须有正确的零警告或#pragmas.
编辑:也没有工会.
EDIT2:假设构建系统在太阳下也使用-Wall -ansi -pedantic和其他所有警告.我明天会确认GCC版本,但我相当肯定它不高于GCC 7.与此同时,我正在使用GCC 6.3进行测试.
编辑3:我将问题标记为"已回答".为了完整起见,我在下面添加了更多信息:
我已经检查了正在使用的编译器版本,它并不漂亮.我们正在使用Mingw并gcc.exe --version告诉我它是GCC 3.4.5.
此外,编译标志包括wall wextra wcast-qual wpointer-arith wconversion wsign-conversion与手头问题无关的其他标志.
请考虑以下代码:
#include "stdio.h"
#include "stdint.h"
typedef uint32_t MyType[4];
const MyType* foo(const uint8_t* a)
{
return (const MyType*) a;
}
void myapi_foo(const MyType* d) {}
int main()
{
uint8_t a[4*sizeof(uint32_t)];
const MyType* b = foo((const uint8_t*) a);
myapi_foo(b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用GCC和-Wcast-qual标志编译,此代码将抛出以下警告:
警告:从指针目标类型[-Wcast-qual]返回(const MyType*)a抛出丢弃'const'限定符;
编辑:澄清,错误是在这一行:
return (const MyType*) a;
Run Code Online (Sandbox Code Playgroud)
我知道问题的根本原因是typedef类型MyType,它实际上是一个数组.遗憾的是,我没有修改这个typedef,API函数myapi_foo及其参数类型的可疑选择.说实话,我真的不明白 …