You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

指针与非零整数的不等比较曾何时合法?C++标准中如何规定?

关于指针与非零整数不等比较的C++标准历史问题

编译背景与错误信息

在Win10 x64系统的MSYS2环境下编译Seven Kingdoms: Ancient Adversaries项目2.15.5版本时,使用编译命令:

./configure --prefix=/dbg CPPFLAGS=-DDEBUG CFLAGS="-g -O0" && make

出现如下编译错误:

In file included from ../include/ALL.h:33,
                 from OCOLTBL.cpp:25:
OCOLTBL.cpp: In member function 'void ColorTable::generate_table(int, PalDesc&, RGBColor (*)(RGBColor, int, int))':
OCOLTBL.cpp:194:54: error: ordered comparison of pointer with integer zero ('BYTE*' {aka 'unsigned char*'} and 'int')
  194 |         err_when(absScale < 0 || palD.reserved_color < 0 || palD.pal == NULL);
      |                                  ~~~~~~~~~~~~~~~~~~~~^~~
../include/OERROR.h:52:32: note: in definition of macro 'err_when'
   52 |    #define err_when(cond)   if(cond) err.internal(NULL,__FILE__, __LINE__)
      |                                ^~~~

其中palD.reserved_color的类型为unsigned char *。

核心疑问

  • 指针与非零整数的不等比较曾在何时合法?
  • 当时C++标准中如何处理?
  • 过去ptr < 0这类表达式如何工作?
  • 最后一次合法时标准的定义是什么?

问题解答

1. 合法时期

早期C标准(C98/C03)以及更早的C标准(C89/C90)允许指针与整数进行包括不等比较在内的各类比较操作。从C11开始,指针与非零整数的不等比较被明确列为未定义行为,现代编译器会直接报错或发出严重警告。

2. 早期标准的处理方式

在C98/C03中:

  • 指针可以隐式转换为std::ptrdiff_t(一种有符号整数类型,用于表示两个指针之间的差值);
  • 整数也可以转换为指针类型,但仅当整数是0时行为定义明确,非零整数转换为指针属于实现定义行为;
  • 当执行ptr < 0这类比较时,实际是先将指针转换为std::ptrdiff_t类型,再与整数0进行比较。

3. ptr < 0的实际工作逻辑

在早期的实模式或分段内存模型(比如DOS时代的16位系统)中,指针通常包含段地址和偏移地址两部分。某些内存模型下,偏移地址使用有符号整数表示(如16位有符号整数),此时ptr < 0可以用来判断指针的偏移部分是否为负数,对应内存中的低地址区域。但在现代平坦内存模型(如x86_64)中,指针是无符号的64位值,ptr < 0的结果永远为假,这类比较完全没有实际意义。

4. 最后一次合法的标准定义

C++03是最后允许这类比较的官方标准,其相关条款定义如下:

指针可以与整数类型的值进行比较。指针转换为整数类型的结果是实现定义的。除了指针可以与值为0的整数常量表达式比较外,其他指针与整数的比较结果是实现定义的。

内容的提问来源于stack exchange,提问作者Zsar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 13:05:32