对于任何类型,使用const void *而不是void *

时间:2014-10-07 15:31:22

标签: c pointers const standards c99

指向void(void*)的指针兼容并且可以保存任何其他指针类型。对于指向const void(const void*)的指针也是如此。

自:

6.3.2.3,p2:对于任何限定符q,指向非q限定类型的指针可以转换为指向 该类型的q限定版本;存储在原始和转换指针中的值 应比较相等。

因为我被允许这样做:

int n = 0 ;
void* p = &n ;

我应该也允许这样做:

int n = 0 ;
const void* p = &n ;

这让我想到了最后一点,即所有这些也应该适用于复合文字。

void SomeFunc( const void* p ) { printf("%p",p) } ;

SomeFunc( &( int ){ 12345 } ) ;

应该由C标准定义(和允许)吗?

2 个答案:

答案 0 :(得分:2)

我会直接承认我很少在C中发现复合文字的需要,但你的语法肯定是有根据的。如果我正确地理解了你的问题,那就是试图确定应用于复合文字的上述address-of运算符是否会产生const vs非const指针。

除非化合物本身是常量限定的,否则它是非常量的。我没有方便的C99标准,但我能为此提出的最好的例子就是:

  

C11标准§6.5.2.5p11

     

可以通过以下结构指定只读复合文字:

  (const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}

结合以下对复合文字的存储资格的描述:

  

C11标准§6.5.2.5p5

     

复合文字的值是初始化列表初始化的未命名对象的值。如果复合文字出现在函数体外,则该对象具有静态存储持续时间;否则,它具有与封闭块相关的自动存储持续时间。

因此存储也存在(即它不驻留在某处的只读存储器中)。除非const合格,否则复合文字实际上是非const的(如果复合文字数组或结构实际上可能具有自己的const限定,则其中的数据/元素)。 / p>

Type *void*const void*的翻译机制有望显而易见,但值得注意的是你的样本有些扭曲:

void SomeFunc( void* p ) { printf("%p\n",p); } ;
void SomeFuncConst( const void* p ) { printf("%p\n",p); } ;

int main()
{
    SomeFunc( &( int ){ 12345 } ) ;        // OK. int* to void* 
    SomeFuncConst( &( int ){ 12345 } ) ;   // OK. int* to const void*
    SomeFuncConst &(const int){12345} );  // OK. const int* to const void*
    SomeFunc( &( const int ){ 12345 } ) ;  // ERROR. const int* not allowed as void*
}

考虑到所有这一切,我完全看似错误地理解了你的问题,如果这样,那么我可以澄清一下我的删除链接。

答案 1 :(得分:1)

此次通话没有问题

SomeFunc( &( int ){ 12345 } ) ;

C标准中有一个类似的例子

drawline(&(struct point){.x=1, .y=1},
         &(struct point){.x=3, .y=4});

根据C标准(6.5.2.2函数调用)

  

7如果表示被调用函数的表达式具有类型   确实包含一个原型,参数被隐式转换为   如果通过赋值,对相应参数的类型,采取   每个参数的类型是其不合格的版本   声明的类型。

C标准相对于转化似乎存在差距。 C ++标准

中描述了更详细的隐式转换

1标准转化是具有内置含义的隐式转化。第4条列举了全套此类转换。标准转换序列是按以下顺序的一系列标准转换:

- 来自以下集合的零或一次转换:左值到右值的转换,数组到指针的转换以及函数到指针的转换。

- 来自以下设置的零次或一次转换:整数促销,浮点促销,积分转换,浮点转换,浮点积分转换,指针转换,指向成员转换的指​​针以及布尔转换。

- 零或一个资格转换。

因此可以看出,标准转换序列包括一个指针转换和一个限定转换。

C标准可以给出类似的详细描述。