c - 始终将 strtok_s 的第一个参数保持为 NULL 是否正确?
问题描述
我曾经考虑过什么时候第一次调用strtok_s()
应该传递包含令牌的字符串作为第一个参数,如下代码:
char testString[100] = "1|2|3";
char *context = testString;
const char *token = strtok_s( testString, "|", &context );
while ( token )
token = strtok_s( NULL, "|", &context );
但是,我看到有人总是将第一个参数保留为NULL
,如以下代码:
char testString[100] = "1|2|3";
char *context = testString;
const char *token = strtok_s( NULL, "|", &context );
while ( token )
token = strtok_s( NULL, "|", &context );
我知道它的工作原理以及它是如何工作的。因为context
指向与 相同的缓冲区testString
。但我觉得有点奇怪,我的疑问是:
- 这是使用的好习惯
strtok_s()
吗?它可能面临哪些潜在的错误? - 如果这是一个好习惯,为什么
strtok_s()
还需要保留第一个参数?它可以NULL
像往常一样,不是吗?
解决方案
根据函数文档,函数的正确用法是你提到的第一个。
进一步引用 C11 标准(重点是我的),第 K.3.7.3.1 节(第 616 页):
对 strtok_s 函数的一系列调用将 s1 指向的字符串分解为一系列标记,每个标记由 s2 指向的字符串中的一个字符分隔。第四个参数指向调用者提供的 char 指针,strtok_s 函数在该指针中存储继续扫描相同字符串所需的信息。
序列中的第一个调用有一个非空的第一个参数,s1max 指向一个对象,该对象的值是第一个参数指向的字符数组中的元素数。第一次调用将初始值存储在 ptr 指向的对象中,并更新 s1max 指向的值以反映与 ptr 相关的元素数量。序列中的后续调用具有空的第一个参数,并且 s1max 和 ptr 指向的对象需要具有序列中先前调用存储的值,然后更新。s2 指向的分隔符字符串可能与调用不同。
因此,标准所说的是正确的用法是使用strtok_s
非 NULL 第一个参数调用,然后使用 NULL 第一个参数调用它。在第一次调用时,函数初始化一些状态,并使用提供的指针(最后一个参数)来存储它。
该标准没有提到应该如何使用最后一个参数,而不是保持状态,以便函数在使用未修改的指针调用时可以继续搜索相同的字符串。基本上,它消除了对 的内部状态的需要strtok
,例如,您可以同时标记多个字符串。
因此,状态空间的使用方式是由实现定义的。很可能是这样的情况,在某些实现中,它可以简单地将初始字符串放在那里并始终使用第一个参数 NULL 调用它,如您所展示的。但是不能保证在所有实现上都会发生这种情况,或者这种行为在库的未来版本中会保持不变。
要直接回答您的问题,是的,它可能有效,但不,这样做不是一个好主意。
推荐阅读
- javascript - 从 C# 执行 JavaScript
- python - 在 Py++ 中生成 boost 接口时出现关键错误
- javascript - 当主键的类型是日期时,我如何`findByPk`?
- csv - 如何在 GraphDB 上使用 SPARQL 通过 CSV 文件设置和更新现有节点的属性
- visual-studio-code - Visual Studio Code Community 和开源版本之间的区别
- pandas - 如何按位置选择 DatetimeIndex 的 Pandas 日期时间?
- c - 将 C 函数指针传递给 emscripten 回调
- angular - 如何在我的 Angular 7 项目中导入 ag-grid-enterprise
- php - JQuery 媒体模式部分仅有时加载
- jquery - 为什么我的复选框的值在我的 ASP.NET Core Web 应用程序中由 jQuery 设置时不会发布到我的控制器?