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

时间:2014-09-08 13:21:26

标签: c pointers variable-initialization

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

#include <stdio.h>
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保存它,并且在这个编译器上它无法编译。

3 个答案:

答案 0 :(得分:7)

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

N1570§6.7.9/ p11:

  

标量的初始化程序应该是单个表达式,可选   用括号括起来。对象的初始值是   表达(转换后);相同的类型约束和   适用于简单分配的转换,采用类型   标量是其声明类型的非限定版本。

§6.5.16.1/ p1规定了简单分配:

  

以下其中一项应成立:

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

其中没有一个与左侧的指针和右侧的333相匹配。 §6.5.16.1/ p1是约束,并且在违反约束时产生诊断需要符合实现(§5.1.1.3/ p1):

  

符合要求的实施应至少产生一种诊断   消息(以实现定义的方式标识)如果a   预处理翻译单元或翻译单元包含一个   违反任何语法规则或约束,即使行为是   也明确指定为未定义或实现定义。

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

答案 1 :(得分:5)

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

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

答案 2 :(得分:-2)

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

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