【问题标题】:About what is leftover after running strtol关于运行 strtol 后剩余的内容
【发布时间】:2026-01-28 11:45:02
【问题描述】:

我无法理解 C 中 strtol() 的行为。例如,当我测试字符串 " 4396" 时,如果有:

char *test = " 4396";
char *ptr;
int result = strtol(test, &ptr, 10);
printf("%d\n", result);
printf("%d\n", strlen(ptr));

输出:

4396
//not 0

我只是想知道为什么长度不是0,因为我已经检查到最后了?

感谢您的帮助。

【问题讨论】:

  • ptr 是一个未初始化的指针,它和strtol 有什么关系?调用strlen(ptr) 只是未定义的行为
  • 另外,strtol 返回一个 long int
  • 编辑后我无法重现结果:ideone.com/MtRXaR(尽管可能是由于使用了错误的类型说明符?)
  • strlen returns size_t 所以用%d 打印也是UB。 Use %zu instead
  • (如您已编辑问题)使用" 4396" 后,ptr 设置为最后一位转换后的下一个字符,例如在 '6' 之后,它指向 nul-character 结尾 test。所以ptr 指向empty-string 并且strlen 等于0。您可以通过if (!*ptr) puts ("pointing at nul-character"); 确认

标签: c strtol


【解决方案1】:

以下建议的代码:

  1. 干净编译
  2. 执行所需的功能
  3. 注意对几个语句的更正
  4. 注意头文件的添加
  5. 注意添加功能:main()
  6. 在编程中,细节很重要

现在建议的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( void )
{
    char* test = " 4396";
    char *ptr;
    long result = strtol(test,&ptr,10);  // note the change from `int` to `long`
    printf("%ld\n",result);  // note the change from'%d' to '%ld'
    printf("%zu\n",strlen(ptr)); // note the change from '%d' to '%zu'
}

建议代码的输出是:

4396
0

注意第二个输出是 0,因为strlen() 不计算尾随 NUL 字节,ptr 指向 NUL 字节

【讨论】:

  • 虽然自 C99 起隐含,但建议显式添加 return 0;。将test 定义为const char * 也可以避免-Wall 的警告。
  • @chqrlie 在 Clion 和 Mac Os X 上具有以下标志,它不会警告我将 const 设为 char*set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64 -std=c11 -pedantic -O2 -Wall -Wextra -Wshadow -Wpointer-arith \ -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -pthread")
  • @chqrlie 如何使用它来警告我??
  • @snr:我确实在 OS/X 上收到了带有clang 的警告,但我的CFLAGS 变量中有-Wwrite-strings。具体的警告标签是-Wincompatible-pointer-types-discards-qualifiers。系统的const 指针参数限定(又名constification)提高了代码质量并避免了细微的错误。
  • @snr:编译器标志因编译器和平台的特殊性而因项目而异...然后我使用clang -O3 -Wall -Werror -Wwrite-strings -Wchar-subscripts -funsigned-char
【解决方案2】:

strtol() 存储了指向" 4396" 中最后一位数字之后的字符的指针,因此是指向此字符串常量的空终止符的指针。

ptr指向的C字符串长度为0,由strlen()返回,类型为size_t

看到语句printf("%d\n", strlen(ptr)); 没有输出,这非常令人惊讶。以下是一些提示:

  • 一种可能的解释是strlen() 返回一个size_t,你将它作为%d 的参数传递,它需要int。传递不兼容的类型,例如size_t,它可以具有不同的大小,具有未定义的行为。您应该使用 C99 转换规范 printf("%zu\n", strlen(ptr)); 或将长度转换为 unsigned long 以便移植到旧版 C 库:printf("%lu\n", (unsigned long)strlen(ptr));

  • 1234563
  • 您没有发布完整的程序,所以问题可能出在其他地方,在您没有发布的代码中。

  • 最后但同样重要的是:您更正了最初帖子中的代码,使问题变得无关紧要。 ptr 是一个未初始化的指针,传递给 strlen() 有未定义的行为,可能导致程序停止,这可以解释为什么你没有得到任何输出。

【讨论】: