<tfoot id='VjwuK'></tfoot>
<i id='VjwuK'><tr id='VjwuK'><dt id='VjwuK'><q id='VjwuK'><span id='VjwuK'><b id='VjwuK'><form id='VjwuK'><ins id='VjwuK'></ins><ul id='VjwuK'></ul><sub id='VjwuK'></sub></form><legend id='VjwuK'></legend><bdo id='VjwuK'><pre id='VjwuK'><center id='VjwuK'></center></pre></bdo></b><th id='VjwuK'></th></span></q></dt></tr></i><div id='VjwuK'><tfoot id='VjwuK'></tfoot><dl id='VjwuK'><fieldset id='VjwuK'></fieldset></dl></div>

        <bdo id='VjwuK'></bdo><ul id='VjwuK'></ul>

      <small id='VjwuK'></small><noframes id='VjwuK'>

      1. <legend id='VjwuK'><style id='VjwuK'><dir id='VjwuK'><q id='VjwuK'></q></dir></style></legend>

        为什么 Visual C++ 在 C 中对从 const void ** 到 void * 的隐式转换发出警告,但在 C

        时间:2023-07-02
        <i id='OcIlU'><tr id='OcIlU'><dt id='OcIlU'><q id='OcIlU'><span id='OcIlU'><b id='OcIlU'><form id='OcIlU'><ins id='OcIlU'></ins><ul id='OcIlU'></ul><sub id='OcIlU'></sub></form><legend id='OcIlU'></legend><bdo id='OcIlU'><pre id='OcIlU'><center id='OcIlU'></center></pre></bdo></b><th id='OcIlU'></th></span></q></dt></tr></i><div id='OcIlU'><tfoot id='OcIlU'></tfoot><dl id='OcIlU'><fieldset id='OcIlU'></fieldset></dl></div>
          <bdo id='OcIlU'></bdo><ul id='OcIlU'></ul>

          <legend id='OcIlU'><style id='OcIlU'><dir id='OcIlU'><q id='OcIlU'></q></dir></style></legend>

                <small id='OcIlU'></small><noframes id='OcIlU'>

                <tfoot id='OcIlU'></tfoot>
                  <tbody id='OcIlU'></tbody>
                  本文介绍了为什么 Visual C++ 在 C 中对从 const void ** 到 void * 的隐式转换发出警告,但在 C++ 中没有警告?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  Microsoft Visual Studio 中的 C/C++ 编译器在 C 程序尝试时发出警告 C4090将指向 const 数据的指针(如 const void **const char **)的指针转换为 void *(即使这样的类型实际上并不是指向 const 的指针).更奇怪的是,同一个编译器默默地接受编译为 C++ 的相同代码.

                  The C/C++ compiler in Microsoft Visual Studio gives warning C4090 when a C program tries to convert a pointer to pointer to const data (like const void ** or const char **) to void * (even though such a type is not actually a pointer to const). Even more strangely, the same compiler silently accepts identical code compiled as C++.

                  这种不一致的原因是什么,为什么 Visual Studio(与其他编译器不同)在将指向 const 的指针的指针隐式转换为 void * 时会出现问题>?

                  What is the reason for this inconsistency, and why does Visual Studio (unlike other compilers) have a problem with implicitly converting a pointer to pointer to const into a void *?

                  我有一个 C 程序,其中在变量参数列表中传递的 C 字符串被读入数组(通过调用 va_arg 的循环).由于 C 字符串的类型为 const char *,因此跟踪它们的数组的类型为 const char **.这个指向带有 const 内容的字符串的指针数组本身是动态分配的(使用 calloc),并且我在函数返回之前(在 C 之后)free-strings 已处理).

                  I have a C program in which C-strings passed in a variable argument list are read into an array (by a loop in which va_arg is invoked). Since the C-strings are of type const char *, the array that keeps track of them is of type const char **. This array of pointers to strings with const content is itself allocated dynamically (with calloc) and I free it before the function returns (after the C-strings have been processed).

                  当我使用 cl.exe(在 Microsoft Visual C++ 中)编译此代码时,即使警告级别较低,free 调用也会触发警告 C4090.由于 free 采用 void *,这告诉我编译器不喜欢我将 const char ** 转换为 <代码>空*.我创建了一个简单的例子来确认这一点,其中我尝试将 const void ** 转换为 void *:

                  When I compiled this code with cl.exe (in Microsoft Visual C++), even with a low warning level, the free call triggered warning C4090. Since free takes a void *, this told me that the compiler didn't like that I had converted a const char ** to a void *. I created a simple example to confirm this, in which I try to convert a const void ** to a void *:

                  /* cast.c - Can a const void** be cast implicitly to void* ? */
                  
                  int main(void)
                  {
                      const void **p = 0;
                      void *q;
                      q = p;
                  
                      return 0;
                  }
                  

                  然后我按如下方式编译它,确认这是触发警告的原因:

                  I then compiled it as follows, confirming that this was what triggered the warning:

                  >cl cast.c
                  Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
                  Copyright (C) Microsoft Corporation.  All rights reserved.
                  
                  cast.c
                  cast.c(7) : warning C4090: '=' : different 'const' qualifiers
                  Microsoft (R) Incremental Linker Version 10.00.40219.01
                  Copyright (C) Microsoft Corporation.  All rights reserved.
                  
                  /out:cast.exe
                  cast.obj
                  

                  Microsoft 的 关于警告 C4090 的文档 说:

                  Microsoft's documentation on warning C4090 says:

                  此警告是针对 C 程序发出的.在 C++ 程序中,编译器会发出错误:C2440.

                  This warning is issued for C programs. In a C++ program, the compiler issues an error: C2440.

                  这是有道理的,因为 C++ 是一种比 C 强类型化的语言,并且 C++ 中不允许 C 中允许的潜在危险的隐式强制转换.Microsoft 的文档使它看起来像警告 C2440 在 C 中针对相同的代码或子集触发代码,这将在 C++ 中触发错误 C2440.

                  That makes sense, since C++ is a more strongly typed language than C, and potentially dangerous implicit casts allowed in C are disallowed in C++. Microsoft's documentation makes it seem like warning C2440 is triggered in C for the same code, or a subset of the code, that would trigger error C2440 in C++.

                  或者我是这么想的,直到我尝试将我的测试程序编译为 C++(/TP 标志执行此操作):

                  Or so I thought, until I tried compiling my test program as C++ (the /TP flag does this):

                  >cl /TP cast.c
                  Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
                  Copyright (C) Microsoft Corporation.  All rights reserved.
                  
                  cast.c
                  Microsoft (R) Incremental Linker Version 10.00.40219.01
                  Copyright (C) Microsoft Corporation.  All rights reserved.
                  
                  /out:cast.exe
                  cast.obj
                  

                  相同代码编译为C++时,不会出现错误或警告.可以肯定的是,我重建了,告诉编译器尽可能积极地发出警告:

                  When the same code is compiled as C++, no error or warning occurs. To be sure, I rebuilt, telling the compiler to warn as aggressively as possible:

                  >cl /TP /Wall cast.c
                  Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
                  Copyright (C) Microsoft Corporation.  All rights reserved.
                  
                  cast.c
                  Microsoft (R) Incremental Linker Version 10.00.40219.01
                  Copyright (C) Microsoft Corporation.  All rights reserved.
                  
                  /out:cast.exe
                  cast.obj
                  

                  它默默地成功.

                  那些构建是在 Windows 7 机器上使用 Microsoft Visual C++ 2010 Express Edition 的 cl.exe,但在 Windows XP 机器上,在 Visual Studio .NET 2003 的 cl.exe 和 Visual C++ 2005 Express Edition 的 cl.exe.因此,这似乎发生在所有版本上(尽管我尚未在所有可能的版本上进行测试),并且在我的计算机上设置 Visual Studio 的方式没有问题.

                  Those builds were with the Microsoft Visual C++ 2010 Express Edition's cl.exe on a Windows 7 machine, but the same errors occur on a Windows XP machine, in both Visual Studio .NET 2003's cl.exe and Visual C++ 2005 Express Edition's cl.exe. So it seems this happens on all versions (though I have not tested on every possible version) and is not a problem with the way Visual Studio is set up on my machines.

                  相同的代码在 Ubuntu 11.10 系统上的 GCC 4.6.1 中编译没有问题(版本字符串 gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1),设置为警告为尽可能积极,如 C89、C99 和 C++:

                  The same code compiles without a problem in GCC 4.6.1 on an Ubuntu 11.10 system (version string gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1), set to warn as aggressively as possible, as C89, C99, and C++:

                  $ gcc -ansi -pedantic -Wall -Wextra -o cast cast.c
                  cast.c: In function ‘main’:
                  cast.c:6:11: warning: variable ‘q’ set but not used [-Wunused-but-set-variable]
                  
                  $ gcc -std=c99 -pedantic -Wall -Wextra -o cast cast.c
                  cast.c: In function ‘main’:
                  cast.c:6:11: warning: variable ‘q’ set but not used [-Wunused-but-set-variable]
                  
                  $ g++ -x c++ -ansi -pedantic -Wall -Wextra -o cast cast.c
                  cast.c: In function ‘int main()’:
                  cast.c:6:11: warning: variable ‘q’ set but not used [-Wunused-but-set-variable]
                  

                  它确实警告 q 在被赋值后永远不会被读取,但该警告是有道理的并且是不相关的.

                  It does warn that q is never read from after being assigned, but that warning makes sense and is unrelated.

                  除了在启用所有警告的情况下不会在 GCC 中触发警告,并且在 GCC 或 MSVC 中都不会在 C++ 中触发警告之外,在我看来,从指针到指针转换为 const 到 void *根本不应该被认为是一个问题,因为虽然 void * 是一个指向非 const 的指针,但是一个指向 const 的指针也是一个指向非 const 的指针代码>常量.

                  Besides not triggering a warning in GCC with all warnings enabled, and not triggering a warning in C++ in either GCC or MSVC, it seems to me that converting from pointer to pointer to const to void * should not be considered a problem at all, because while void * is a pointer to non-const, a pointer to a pointer to const is also a pointer to non-const.

                  在我的实际代码(不是示例)中,我可以使用 #pragma 指令或显式强制转换,或编译为 C++(呵呵),或者我可以忽略它.但我宁愿不做任何这些事情,至少在我理解为什么会发生之前不做.(以及为什么它不会发生在 C++ 中!)

                  In my real-world code (not the example), I can silence this with a #pragma directive, or an explicit cast, or by compiling as C++ (heh heh), or I can just ignore it. But I'd rather not do any of those things, at least not before I understand why this is happening. (And why it doesn't happen in C++!)

                  我想到了一种可能的部分解释:与 C++ 不同,C 允许从 void * 隐式转换为任何指向数据的指针类型.所以我可以将一个指针从 const char ** 隐式转换为 void *,然后从 void * 隐式转换为 char**,从而可以修改它指向的指针的常量数据,而无需进行强制转换.那会很糟糕.但我看不出这比 C 较弱的类型安全所允许的各种其他事情更糟糕.

                  One possible, partial explanation occurs to me: Unlike C++, C allows implicit casting from void * to any pointer-to-data type. So I could have a pointer implicitly converted from const char ** to void *, and then implicitly converted from void * to char **, thereby making it possible to modify constant data it points to pointers to, without a cast. That would be bad. But I don't see how that is any worse than all sorts of other things that are allowed by C's weaker type-safety.

                  我想这个警告可能是有道理的,因为当非 void 指针类型转换为 void * 时选择不发出警告:

                  I guess maybe this warning makes sense given the choice not to warn when a non-void pointer type is converted to void *:

                  /* cast.c - Can a const void** be cast implicitly to void* ? */
                  
                  int main(void)
                  {
                      const void **p = 0;
                      void *q;
                      q = p;
                  
                      return 0;
                  }

                  >cl /Wall voidcast.c
                  Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
                  Copyright (C) Microsoft Corporation.  All rights reserved.
                  
                  voidcast.c
                  Microsoft (R) Incremental Linker Version 10.00.40219.01
                  Copyright (C) Microsoft Corporation.  All rights reserved.
                  
                  /out:voidcast.exe
                  voidcast.obj
                  

                  然而,如果这是故意的,那么:

                  And yet, if that is intentional, then:

                  1. 为什么 Microsoft 文档表明在 C 中产生此警告的代码会在 C++ 中产生错误?

                  1. Why does the Microsoft documentation indicate that code producing this warning in C produces an error in C++?

                  除了忽略或取消警告之外,是否有任何合理的替代方法,当必须free 一个非const 指向非const<的指针时/code> 指向 const 数据的指针(就像在我的现实世界中一样)?如果在 C++ 中发生这样的事情,我可以将在变量参数列表中传递的字符串存储在某个高级 STL 容器中而不是数组中.对于无法访问 C++ STL 并且不使用高级集合的 C 程序,这种事情不是一个合理的选择.

                  Besides ignoring or suppressing the warning, is there any reasonable alternative, when one must free a non-const pointer to non-const pointer to const data (as in my real-world situation)? If something like this happened in C++, I could store the strings passed in the variable argument list in some high-level STL container instead of an array. For a C program without access to the C++ STL and which doesn't otherwise use high-level collections, that sort of thing is not a reasonable option.

                  一些程序员在将警告视为错误的公司/组织政策下工作.C4090 即使使用 /W1 也已启用.人们以前一定遇到过这种情况.这些程序员是做什么的?

                  Some programmers work under a corporate/organizational policy of treating warnings as errors. C4090 is enabled even with /W1. People must have encountered this before. What do those programmers do?

                  推荐答案

                  显然这只是 VC++ 中的一个错误.

                  Apparently this is simply a bug in VC++.

                  如果你声明 const char **x; 结果是一个指向字符的只读"指针,它本身不是一个只读"指针(我使用术语只读",因为 const-ness 术语提出了错误的概念,即所指向的字符是常量,而这通常是错误的...... const 带有引用和指针是引用或指针的一个属性,并没有说明指向或引用数据的常量性).

                  If you declare const char **x; the result is a pointer to a "read-only" pointer to chars, and it's not itself a "read-only" pointer (I use the term "read-only" because const-ness term pushes the wrong concept that the character being pointed to is constant while this is false in general... const with references and pointers is a property of the reference or of the pointer and tells nothing about constness of the pointed-to or referenced data).

                  任何读/写指针都可以转换为 void * 并且 VC++ 在编译该代码时没有真正的理由发出警告,无论是在 C 中还是在 C++ 模式.

                  Any read/write pointer can be converted to a void * and VC++ has no real reason to emit a warning when compiling that code, neither in C nor in C++ mode.

                  请注意,这不是正式的问题,因为该标准没有规定应该或不应该发出哪些警告,因此编译器可以自由地为仍然符合要求的完全有效的代码发出警告.VC++ 实际上为有效的 C++ 代码发出了过多的警告......

                  Note that this is not formally a problem because the standard doesn't mandate which warnings should or should not be issued and therefore a compiler is free to emit warnings for perfectly valid code still remaining compliant. VC++ actually emits a plethora of those warnings for valid C++ code...

                  这篇关于为什么 Visual C++ 在 C 中对从 const void ** 到 void * 的隐式转换发出警告,但在 C++ 中没有警告?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                    • <bdo id='2229I'></bdo><ul id='2229I'></ul>
                      <i id='2229I'><tr id='2229I'><dt id='2229I'><q id='2229I'><span id='2229I'><b id='2229I'><form id='2229I'><ins id='2229I'></ins><ul id='2229I'></ul><sub id='2229I'></sub></form><legend id='2229I'></legend><bdo id='2229I'><pre id='2229I'><center id='2229I'></center></pre></bdo></b><th id='2229I'></th></span></q></dt></tr></i><div id='2229I'><tfoot id='2229I'></tfoot><dl id='2229I'><fieldset id='2229I'></fieldset></dl></div>

                      <small id='2229I'></small><noframes id='2229I'>

                        <legend id='2229I'><style id='2229I'><dir id='2229I'><q id='2229I'></q></dir></style></legend>

                          <tbody id='2229I'></tbody>
                      1. <tfoot id='2229I'></tfoot>