Summary
微软视频演播室的C/C++汇编者发出警告C4090。 当一项C方案试图将点人转换为const
数据(如const void **
或const char **
至(尽管这种类型实际上不是
const
的点)。 更奇怪的是,同一汇编者沉默地接受与C++相同的编码。
这种不一致的原因何在,视觉演播室(与其他汇编者一样)为什么在暗中将点名改为点码(<条码/代码>)变成一个“避免条码>的问题?
Details
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(在微软C++中)汇编该代码时,即使警报水平较低,<代码>免费<>代码>打电话触发了C4090。 自<条码>以来条码> 见void*
,对我说,汇编者照样把const char **
改为 void*>。 我为证实这一点创造了一个简单的例子,其中我试图将<条码>const 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 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
对C方案发出了警告。 在C++方案中,汇编者发行了一个错误:C2440。
这一点是有意义的,因为C++是一种比C更严格的语言,C++允许的具有潜在危险的隐含物在C++中被排除。 微软文件似乎如警告C2440在C中就同一代码或该代码的一个子集触发错误,即C2440在C++中。
或者,我认为,在我尝试将我的测试方案汇编成C++(/TP
)之前,我就认为, 国旗:
>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++,则无错误或警告。 我相信,我重建了,告诉汇编者,尽可能积极地警告:
>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
它无声地取得成功。
这些建筑有微软视像C++2010年快版(cl.exe
,载于Windows 7 机器,但视像室2003年网的视力XP机器也出现同样的错误:cl.exe
。 因此,在所有版本中似乎都发生了这种情况(尽管我还没有对每一种可能的版本进行测试),而且我机器上安装视频演播室的方式并不成问题。
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条码>,但这种警告是有意义的,也是无关紧要的。
除了在海合会发出警告,以及海合会或海卫会无法在C++上发出警告外,我认为,从点到点转换到<代码> 避免*完全不应被视为问题,因为< 编码> 避免* 是非<条码>-const的指点。
在我的实际世界法典(不是例子)中,我可以以<条码>#pragma指令或明确表述的方式,或通过汇编C++(hheh)来保持沉默,或者我只能忽视这一指令。 但我没有做任何事情,至少在我理解为什么发生这种情况之前。 (为什么在C++中发生这种情况!)
一种可能的局部解释是:不同于C++, C允许从<代码>中删除*到任何点对数据类型。 因此,我可以从<条码>const char **到 撤销*
,然后从<条码>中默示转换,从条码>到<条码>**条码>,从而可以修改固定数据,使之指向点人,而无需投放。 这将是坏的。 但是,我看不出,这怎么说比C所允许的更弱的类型安全的其他一切情况更糟。
鉴于非<条码>撤销条码>指点类型改为<条码> 撤销*条码>时选择不警告,我可能认为这种警告是合理的:
/* 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
然而,如果是故意的,则:
微软文件为什么表明在C中产生这种警告的代码在C++中产生错误?
除了忽视或压制警告外,还有任何其他合理选择,即必须<条码>免费<>/代码>、非<条码>const、非<条码>、条码/代码>(如我的真实情况)数据? 如果在C++发生类似情况,我可以储存一些高级别的STL集装箱而不是一个阵列的变式论点清单中所用的座标。 如果C方案没有进入C++ STL,并且没有其他手段使用高层次的收集,那么这种选择就不是合理的。
一些方案者在公司/组织政策下将警告视为错误:C4090。 即便有<代码>/W1。 人民以前必须碰到这一点。 这些方案者做了些什么?