2

该问题的答案表明,标量可以转换为_Bool,而结果的整数值_Bool将是01

这个问题的公认答案指出指针是标量。

是否无法将指针隐式转换为_Bool,因此是编译器错误?

例如:

$ cat ./main.c 
// main.c

#include <stdbool.h>

int main( int argc, char* argv )
{
  int  i;
  int* p   = &i;
  bool foo = (bool)p;
  bool bar = p;

  return 0;
}

编译器失败(其中之一):

$ /path/to/mips_fp_le-gcc --version
2.95.3
$ /path/to/mips_fp_le-gcc ./main.c 
./main.c: In function `main':
./main.c:10: incompatible types in initialization

传递编译器(众多之一):

$ gcc --version
gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcc ./main.c 
$ 

请注意,只有隐式转换,而不是强制转换(显式转换),被标记为问题编译器的错误。
另外,请注意,根据对此问题的评论,指出的问题编译器是旧的 - 从 2001 年开始 - 这可能与这是否是真正的编译器错误有关。(我无法控制的原因阻止了注意到问题交叉编译器的版本升级)

4

1 回答 1

1

是的,这是一个编译器错误。尽管 C 在整数类型和指针类型之间没有任何方向的隐式转换,也没有指针类型之间的隐式转换,除非在特殊情况下,例如指向/从指向 void 的指针或从指向非限定的指针到指向限定的指针,它确实定义了隐式转换为_Bool. (传统上,许多编译器在其他地方支持这种隐式转换,但这样做是有害的,并且不是 C 语言的一部分。)

关于隐式转换的语言在6.5.16.1 Simple assignment下:

应满足下列条件之一:

  • 左操作数具有原子、合格或非限定算术类型,右操作数具有算术类型;
  • 左操作数具有与右操作数兼容的结构或联合类型的原子、限定或非限定版本;
  • 左操作数具有原子、限定或非限定指针类型,并且(考虑左操作数在左值转换后将具有的类型)两个操作数都是指向兼容类型的限定或非限定版本的指针,并且左侧指向的类型具有所有右边指向的类型的限定符;
  • 左操作数具有原子、限定或非限定指针类型,并且(考虑左操作数在左值转换后将具有的类型)一个操作数是指向对象类型的指针,另一个是指向限定或非限定版本的指针void,并且left指向的类型具有right指向的类型的所有限定符;
  • 左操作数是原子的、合格的或不合格的指针,右操作数是空指针常量;或者
  • 左操作数的类型为 atomic、qualified 或 unqualified _Bool,而右操作数是指针。

在标准中出现隐式转换的其他地方,它被指定为“好像通过赋值”,参考上文。例如,在 6.5.2.2 函数调用中:

如果表示被调用函数的表达式具有包含原型的类型,则参数将被隐式转换,就像通过赋值一样,...

请注意,您的问题实际上是关于初始化的,这不是 C 中的赋值,而是不同的东西。但是,6.7.9 初始化¶11 涵盖了它:

标量的初始值设定项应为单个表达式,可选择用大括号括起来。对象的初始值是表达式的初始值(转换后);与简单赋值相同的类型约束和转换 apply,将标量的类型作为其声明类型的非限定版本。

于 2019-12-03T00:51:58.000 回答