C 为什么为null测试浮点值会产生编译错误“二进制操作数无效==(具有“float”和“void*”)”?

C 为什么为null测试浮点值会产生编译错误“二进制操作数无效==(具有“float”和“void*”)”?,c,void,operands,C,Void,Operands,错误: scanf("%f", &lista2.pret); fflush(stdin); if (lista2.pret == NULL ) goto eror2; // error fseek(o,(nn-1)*sizeof(lista2),SEEK_SET); fwrite(&lista2,sizeof(lista2),1,o); break; } fclose(o); break; } 怎么了?在==运

错误:

    scanf("%f", &lista2.pret);
    fflush(stdin);

    if (lista2.pret == NULL ) goto eror2; // error

    fseek(o,(nn-1)*sizeof(lista2),SEEK_SET);
    fwrite(&lista2,sizeof(lista2),1,o);

    break;
  }

  fclose(o);
  break;
}
怎么了?

在==运算符上有一个约束:

-两个操作数都具有算术类型

-两个操作数都是指向兼容类型的合格或不合格版本的指针

-一个操作数是指向对象类型的指针,另一个是指向void的限定或非限定版本的指针;或

-一个操作数是指针,另一个是空指针常量

lista2.pret显然是一种浮点算术类型,因此不能与NULL进行比较。只有指针类型可以与NULL进行比较。

要测试scanf在这种情况下是否成功扫描浮点,您应该使用:

[Error] invalid operands to binary == (have 'float' and 'void *')`
float类型不使用NULL表示没有值。NULL与指针一起使用,指针可以具有实际对象的地址,也可以具有“值”NULL。但是,与其他一些语言不同,C通常没有表示对象未持有有效值的空值。NULL仅用于指针,而不用于整数、浮点值或其他类型的对象

浮点类型实际上有一个“值”来表示对象不包含数字。它被称为NaN,而不是数字,包含后在源代码中为NaN。您可以测试lista2.pret是否为NaN。然而,由于NAN不是数字,它们不能等于任何东西,因此您不会使用lista2.pret==NAN进行测试。相反,您可以使用isnanlista2.pret

但是,scanf将NaN放入浮点并不表示失败。scanf通过其返回值指示故障。它返回成功执行的转换次数。因此,当使用scanf%f和&lista2.pret将某些输入转换为浮点时,结果将是0或1,表示成功转换了0或1。它也可能是EOF,表示发生了一些输入故障。因此,要测试scanf是否成功扫描了浮点,请将其返回值与1进行比较


顺便说一句,您应该知道fflushstdin是基础C语言的一个扩展,它依赖于实现。您可能正在使用Microsoft Windows。在其他C实现中,fflushstdin可能无法以相同的方式工作,并且可能会中断程序。

浮点永远不能为NULL。这是一个无效的比较。lista2.pret==NULL无效,这就是问题所在。你想在那里做什么?pret是如何定义的?你使用的是哪种编译器?@Code peedient:float可以比较为NULL。根据C标准,NULL是一个NULL指针常量,NULL指针常量可以是一个值为0的整数常量表达式,也可以是一个转换为void*的表达式。如果C实现选择前者,那么lista2.pret==NULL是一个有效的表达式,其中整数零将转换为float。因此,有更多的概念在发挥作用,而不仅仅是“NULL不代表float”。这从技术上回答了这个问题。但是,如果我们看一下代码,为什么会有人将浮点值与NULL进行比较?对于精通C语言的人来说,这是毫无意义的,因为他们是不同的,而且是完全不同的。事实上,它只是在扫描之后的一个线索。作者似乎试图辨别是否成功获得了浮动。这在某些编程语言中是有意义的;某些其他编程语言具有空占位符,以指示值不存在。因此,OP提出的真正问题可能是:“为什么我的scanf成功测试不起作用?”
if (1 != scanf("%f", &lista2.pret))
    goto ero2;