为什么执行无效指针初始化的程序在C中编译得很好?

我编写了一个简单的C程序,我希望它在编译时会失败,但遗憾的是它在C中编译并运行良好,但在C ++中编译失败。 考虑以下计划:

#include  int main() { char *c=333; int *i=333; long *l=333; float *f=333; double *d=333; printf("c = %u, c+1 = %u",c,c+1); return 0; } 

访问此链接: http : //ideone.com/vnKZnx

我认为由于C ++的强类型检查,这个程序肯定无法在C ++中编译。 为什么这个程序用C编译? 事实上,编译器也会显示警告。 我正在使用Orwell Dev C ++ IDE(gcc 4.8.1编译器)。 我也在其他编译器(Borland Turbo C ++ 4.5)上尝试了相同的程序,通过扩展名.c保存它,并且在这个编译器上它无法编译。

此代码既不是合法C也不是合法C ++。

N1570§6.7.9/ p11:

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

§6.5.16.1/ p1规定了简单的任务:

以下其中一项应持有:

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

它们都不匹配左侧的指针和右侧的333 。 §6.5.16.1/ p1是一个约束 ,在约束违规时产生诊断需要符合实现(§5.1.1.3/ p1):

如果预处理转换单元或转换单元包含违反任何语法规则或约束的情况,则符合的实现应生成至少一个诊断消息(以实现定义的方式标识),即使该行为也明确指定为未定义或实现 – 定义。

碰巧GCC决定在C模式下产生警告而不是错误,并继续编译它,但它没有必要。

C可以将数字转换为指针。 char* c = 123c设置为指向内存中的第123个字节。

虽然这几乎无用,几乎肯定是桌面编程中的错误,但在嵌入式系统中,必须与硬件接口,硬件可能在某些硬编码的内存地址中寻找值。

在种族上,你的代码没有任何问题。 您正在使用整数常量值333初始化指针,然后打印地址。 它显示的警告可能是因为整数值是类型转换为地址类型。

当您尝试取消引用指针时,问题就会开始。 它会给出分段错误。