【问题标题】:void * arithmetic无效*算术
【发布时间】:2011-04-24 18:58:14
【问题描述】:
#include<stdio.h>
int main(int argc,char *argv[])
{
   int i=10;
   void *k;
   k=&i;

   k++;
   printf("%p\n%p\n",&i,k);
   return 0;
}

++ 是对 void* 的合法操作吗?有些书说不是 但是 K & R 没有说任何关于 void * 算术的内容(K & R 2/e 的第 93,103,120,199 页)

请澄清。

PS : GCC 至少在 k++ 中没有抱怨。

【问题讨论】:

标签: c auto-increment


【解决方案1】:

您不能增加指向void 的指针。编译器不知道目标结构的 sizeof 是什么。

【讨论】:

  • 就我而言它确实知道,GCC 知道 -
  • $ make gcc -g -Wall -o test test.c $ ./test 0xbfcaf3d8 0xbfcaf3d9
  • 似乎 gcc 在增加 k 时认为 k 是一个整数...... &amp;i + 1 是什么?
【解决方案2】:

不,标准未涵盖void* 的算术运算。为此使用char*

【讨论】:

    【解决方案3】:

    这是一个GCC extension

    在 GNU C 中,指向 void 的指针和指向函数的指针支持加法和减法运算。这是通过将 void 或函数的大小视为 1 来完成的。

    如果您添加-pedantic 标志,它将产生警告:

    warning: wrong type argument to increment

    如果您想遵守标准,请将指针转换为char*

    k = 1 + (char*)k;
    

    标准规定不能对void* 执行加法(k+1),因为:

    1. 指针运算是通过将k 视为指向void(C99 §6.5.6/7)数组的第一个元素(#0)的指针来完成的,k+1 将返回元素在这个“数组”中排名第一(第 6.5.6/8 节)。

    2. 为此,我们需要考虑一个void 的数组。 void 的相关信息是 (§6.2.5/19)

      void 类型包含一组空值;它是一个不完整的类型,无法完成。

    3. 但是,数组的定义要求元素类型不能不完整(第 6.2.5/20 节,脚注 36)

      由于对象类型不包含不完整类型,无法构造不完整类型的数组。

    因此k+1 不能是有效的表达式。

    【讨论】:

      【解决方案4】:

      该标准要求所有指针算术运算符都要求指针指向完整的对象类型。 void 是不完整的类型。 GCC 做错了。

      【讨论】:

        【解决方案5】:

        关于 void* 的算术是 GCC 扩展。当我用clang -Wpointer-arith 编译你的代码时,输​​出是:

        test.c:9:4: 警告:使用 GNU void* 扩展 [-Wpointer-arith]
        k++;
        ~^
        

        指针增量的通常行为是将指针类型的大小添加到指针值。例如 :

        
        int *p;
        char *p2;
        p++; /* adds sizeof(int) to p */
        p2 += 2; /* adds 2 * sizeof(char) to p2 */

        由于void 没有大小,您不应该对void* 指针执行指针运算,但GNU C 允许这样做。

        【讨论】:

          猜你喜欢
          • 2020-10-05
          • 2018-08-17
          • 2013-08-17
          • 1970-01-01
          • 1970-01-01
          • 2019-04-16
          • 1970-01-01
          • 1970-01-01
          • 2014-10-05
          相关资源
          最近更新 更多