指针访问字符串无法回退的问题及代码疑问
C语言指针操作的两个问题及解答
问题描述
- 实现
ft_between函数时,通过指针自增赋值字符后,指针指向字符串末尾,直接用printf输出无内容,必须偏移16位才能打印。疑惑为何之前类似操作没问题,是否和malloc有关?想找不用数组下标、纯指针操作的“回退”方法。 ft_nbr2str函数中,指针自增后返回调用方却能正常打印整个字符串,对此存在疑问。
相关代码
ft_between函数
char *ft_between(char *str, size_t from, size_t to) { char *between; between = malloc(16); while ((from >= 0) && (from < to) && (to < ft_strlen(str))) { *(between++) = str[from++]; } *between = '\0'; printf("%s\n", between); // 无输出 printf("%s\n", between - 16); // 能打印,但之前从没这么做过... return (between);// 调用方拿到的指针仍指向字符串末尾 }
ft_nbr2str函数
void ft_nbr2str(char *str, size_t nbr, char *base, size_t base_len) { if (nbr >= base_len) { ft_nbr2str(str, (nbr / base_len), base, base_len); while (*str != '\0') str++; *str = base[nbr % base_len]; } else *str = base[nbr]; }
问题解答
关于ft_between的问题
- 核心原因:你在循环中直接修改了
between指针本身——每次between++都会让它从malloc返回的起始地址向内存高地址移动,循环结束后它已经指向了字符串末尾的'\0'位置,此时用它打印自然是空字符串。 - 和
malloc无关,完全是指针操作逻辑的问题。之前没遇到这种情况,大概率是之前的代码中保留了原始指针的副本,没有直接移动指向堆内存起始位置的指针。 - 指针“回退”的正确做法:保存
malloc返回的原始指针,后续操作使用副本,最终用原始指针打印和返回:char *ft_between(char *str, size_t from, size_t to) { char *between = malloc(16); char *start = between; // 保存堆内存的起始地址 // 注意:size_t是无符号类型,from >= 0永远为真,可删除该判断 while ((from < to) && (to < ft_strlen(str))) { *(between++) = str[from++]; } *between = '\0'; printf("%s\n", start); // 用原始起始地址打印 return start; // 返回起始地址,调用方才能拿到完整字符串 } - 为什么偏移16位能打印?因为你
malloc了16字节,起始地址刚好是between -16(前提是你写满了16字节),但这属于未定义行为——如果to-from小于16,这个操作会访问到堆内存之外的区域,绝对不能这么用。
关于ft_nbr2str的疑问
这个函数的关键在于C语言的函数参数是值传递:
- 每次递归调用
ft_nbr2str时,传入的str是原始指针的副本,子函数中对str的自增操作只会修改副本,不会改变调用方手里的原始指针。 - 递归过程中,所有字符都是从原始指针指向的缓冲区起始位置开始写入的,调用方手里的指针始终指向缓冲区开头,所以能正常打印整个字符串。
内容的提问来源于stack exchange,提问作者RoGKôT
相关产品推荐
相关产品推荐

