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

将指针移至数组起始位置前是否存在问题?C语言代码疑问及改写需求

strend函数指针越界问题与改写方案

指针移动到数组起始位置之前的风险

将指针移动到数组起始位置之前是未定义行为。根据C语言标准,指向数组元素的指针仅能合法指向:

  • 数组的某个元素
  • 数组尾元素的下一个位置(尾后指针)

一旦指针越过数组首元素向前,就处于无效状态。此时对这类指针进行比较(如se >= s)或后续操作,结果不可预测,不同编译器可能有不同表现,甚至触发程序崩溃。

原代码的问题分析

  1. 指针越界的未定义行为:原代码中,当se减到s的前一个位置、te减到t的前一个位置时,se >= s和te >= t的比较属于未定义行为,因为此时指针已超出合法范围。
  2. 空字符串的潜在问题:若t是空字符串,te初始等于t,进入循环后te--会直接跳到t-1,后续指针操作完全违反标准。
  3. 关于“指针初始化为0导致下溢”:正常情况下,字符串指针不会指向地址0(NULL除外),若传入NULL,while(*te)会直接解引用空指针导致崩溃。即便极端情况t指向地址0,te--会生成非法地址,这属于指针非法访问,而非数值下溢,但同样是严重的未定义行为。

改写后的代码(避免指针越界)

我们可以先计算两个字符串的长度,确保从后往前比较时不会越过数组起始位置,以下是两种可靠实现:

实现方式1:先定位比较起始位置

#include <stdio.h>

int strend(char *s, char *t);

int main()
{
    char a[] = "hello world";
    char b[] = "orld";
    int i = strend(a, b);
    printf("%d", i);
    return 0;
}

int strend(char *s, char *t)
{
    // 空字符串默认匹配所有字符串结尾
    if (*t == '\0') {
        return 1;
    }

    // 计算s的长度
    char *s_ptr = s;
    size_t len_s = 0;
    while (*s_ptr++) {
        len_s++;
    }

    // 计算t的长度
    char *t_ptr = t;
    size_t len_t = 0;
    while (*t_ptr++) {
        len_t++;
    }

    // t比s长,直接不匹配
    if (len_t > len_s) {
        return 0;
    }

    // 将s移动到待比较的起始位置
    s_ptr = s + len_s - len_t;
    t_ptr = t;

    // 逐字符比较
    while (*t_ptr) {
        if (*s_ptr != *t_ptr) {
            return 0;
        }
        s_ptr++;
        t_ptr++;
    }

    return 1;
}

实现方式2:从后往前限定比较次数

#include <stdio.h>
#include <stddef.h> // 用于ptrdiff_t类型

int strend(char *s, char *t);

int main()
{
    char a[] = "hello world";
    char b[] = "orld";
    int i = strend(a, b);
    printf("%d", i);
    return 0;
}

int strend(char *s, char *t)
{
    char *s_end = s;
    char *t_end = t;

    // 定位到字符串末尾的'\0'
    while (*s_end) s_end++;
    while (*t_end) t_end++;

    // 计算t的长度
    ptrdiff_t t_len = t_end - t;
    // s的长度小于t,直接返回0
    if ((s_end - s) < t_len) {
        return 0;
    }

    // 从后往前比较t_len个字符,不会越界
    while (t_len-- > 0) {
        if (*(--s_end) != *(--t_end)) {
            return 0;
        }
    }

    return 1;
}

这两种实现都严格遵循C标准,避免了指针越界的未定义行为,同时正确处理了空字符串等边界情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 02:20:14