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

C语言中比较指向不同char对象的两个指针是否为未定义行为?

memmove实现中的指针比较是否属于未定义行为?

以下是gcc中memmove的实现代码:

void *
memmove (void *dest, const void *src, size_t len)
{
  char *d = dest;
  const char *s = src;
  if (d < s)
    while (len--)
      *d++ = *s++;
  else
    {
      char *lasts = s + (len-1);
      char *lastd = d + (len-1);
      while (len--)
        *lastd-- = *lasts--;
    }
  return dest;
}

C11标准在6.5.8. 关系运算符中规定:

当比较两个指针时,结果取决于所指向对象在地址空间中的相对位置。若两个指向对象类型的指针指向同一个对象,或都指向同一个数组对象的最后一个元素之后的位置,则它们相等。若所指向的对象是同一个聚合对象的成员,则指向结构体中后声明成员的指针大于先声明成员的指针,指向数组中下标值较大元素的指针大于下标值较小元素的指针。指向同一个联合对象所有成员的指针都相等。若表达式P指向数组对象的一个元素,表达式Q指向同一个数组对象的最后一个元素,则指针表达式Q+1大于P。除此之外的所有情况,行为都是未定义的。

上述代码中存在比较两个不同对象指针的操作:

if (d < s)

这是否属于未定义行为?或者说,指向char类型的指针比较是良定义的?


解答

严格按照C11标准的定义,这个d < s的比较属于未定义行为——当两个char*指针指向完全无关的对象(既不属于同一聚合体、同一数组,也不是同一数组的末尾位置)时,关系运算符的比较结果是标准未规定的。

但在实践中,主流平台和编译器会让这个操作正常工作:

  • 主流硬件的地址空间是线性统一的,char*指针本质对应线性地址的数值,比较指针大小等价于比较地址数值,平台层面有明确的结果。
  • memmove作为标准库核心函数,编译器会针对这类代码做特殊兼容处理,保证其行为符合预期。

需要注意的是:这种“依赖平台行为”的写法只适合标准库这类特殊场景,普通应用代码绝对不要依赖指针跨对象的关系比较,必须严格遵循C标准的规定,只在指针指向同一对象、同一数组或聚合体成员时使用关系比较。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:32:18