【问题标题】:pointer-to-const conversion in CC中的指针到常量转换
【发布时间】:2009-10-26 11:51:13
【问题描述】:

以下代码在 GCC 上编译时不会发出警告,但在 Visual Studio 2005 中会发出警告。

const void * x = 0;
char * const * p = x;

x 指向一个未知类型的常量对象,p 指向一个指向 char 的常量指针。为什么分配给 p 会导致警告?

同样,这是 C,而不是 C++。谢谢。

【问题讨论】:

  • 可以添加警告信息吗?
  • 同意 Etan:如果声明了警告信息,这个问题会更清楚。它是:警告 C4090: 'initializing' : different 'const' qualifiers
  • 我的 VS2005(配置为 C++)在这种情况下实际上返回一个错误:'initializing' : cannot convert from 'const void ' to 'char *const *'。从“void”转换为指向非“void”的指针需要显式转换
  • 将代码编译为 C 应该会给你 C4090 警告。
  • 一些编译器即使在void * 转换中看到指针似乎具有不同的间接级别时也会发出警告。这可能是 MSVC++ 警告的原因。否则,这段代码没有问题。

标签: c constants


【解决方案1】:

发生这种情况是因为当您将一种类型的指针指向另一种类型时,有时会无意中完成(错误),因此编译器会警告您。

因此,为了告诉编译器您确实打算这样做,您必须进行显式转换,如下所示:

        const void * x = 0;
        char * const * p = (char * const * )x;

附:首先我写了“大部分时间都是无意完成的”,但是当 AndreyT 正确地说 void * 专门为此目的而存在时,他让我重新考虑了这一点。

【讨论】:

  • 这是一种 c++ 风格的“破坏类型”方法。正确的解决方案在 C 中是不同的。
  • void * 专门为此目的而存在。对此发出警告将完全没有用。在这种情况下发出警告的唯一理由可能是指针中明显不同的间接级别,而不仅仅是因为它们指向不同的类型。
【解决方案2】:

C 代码有效且符合标准的编译器不应发出警告,因为 const 已正确保留,并且将 void * 转换为任何指针类型(除了函数指针)是隐式的。

C++ 编译器应该对隐式转换发出警告,但有关丢弃 const 限定符的警告是错误的,应该被视为编译器错误。

【讨论】:

    【解决方案3】:

    如果x 指向struct Thing 而不是char 会怎样?在这种情况下,您将做一些未指定行为的事情。 GCC 倾向于让您这样做,因为它假设您足够聪明,不会朝自己的脚开枪,但警告是有充分理由的。

    【讨论】:

    • gcc 让你这样做,因为标准说 void * 可以隐式转换为任何指针类型(函数指针除外)
    【解决方案4】:

    您必须从右到左阅读以下内容。
    字符 * 常量 * p = x;

    例如:
    P 指向一个 char 类型的 const 指针。

    【讨论】:

      【解决方案5】:
      const void * x = 0;
      char * const * p = x;
      

      起初我以为你是想获取 x 的地址并为此编写代码。然后我决定 x 指向一个指向 char [] 的指针。无论如何,这仍然很混乱:

      #include <stdio.h>
      int main()
      {
              char s [] = "Hello World!";
              const void * x = s;
              const char * const * const p = (const char * const *)&x;
              printf("%s\n", *p);
      /* won't compile
              *p++;      // increments x to point to 'e'
              (**p)++;   // increments 'H' to 'I'
      */
              const char * y = s;
              x = &y;
              const char * const * const q = x;
              printf("%s\n", *q);
      /* won't compile
              *q++;
              (**q)++;
      */
              return 0;
      }
      

      p 声明中char 之前的额外const 会阻止(**p)++ 编译。但是,q(在 GCC 中)声明之前添加的 const 会影响 warning: dereferencing ‘void *’ pointererror: increment of read-only location ‘**q’(**q)++。希望有所帮助,它对我有所帮助:-)

      【讨论】:

        【解决方案6】:
        warning C4090: 'initializing' : different 'const' qualifiers
        

        您不能将const void 转换为char *const 甚至char *。通过取消引用p,您现在可以修改*(char *)(*x)。这是 C 中关于指针的一个鲜为人知的微妙之处。

        p 的工作类型是:

        char const **p = x;
        

        是的,我像男人一样把const放在右边。

        【讨论】:

        • 警告是错误的,因为const 被保留(记住要从内到外阅读声明,const voidvoid const 相同)
        • 不。在 C 编译器上运行它。问题是将 const void 填充到 char *const 中。通过取消 p,您现在可以修改 x。
        • 这没有任何意义。无法修改xp。我们从不在代码中的任何地方获取x 的地址。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-02
        • 2015-08-01
        • 2013-04-14
        • 2021-10-02
        • 2021-06-19
        • 2021-07-11
        相关资源
        最近更新 更多