哪个最标准:strnlen 或 strnlen_s?
Which is most standard: strnlen or strnlen_s?
在我当前的项目中,我正在根据 C11 标准(使用 gcc -std=c11
构建)进行编码,并且需要类似 strnlen
的东西(strlen
的“安全”版本 returns 以 0 结尾的字符串的长度,但不超过给定的最大值)。所以我查了一下(例如 https://en.cppreference.com/w/c/string/byte/strlen),似乎 C11 标准提到了这样一个函数,但是名字是 strnlen_s
.
因此我选择了 strnlen_s
,但是当包含 string.h
时结果是未定义的。另一方面,strnlen
已定义,所以我目前的解决方案是使用 strnlen
并注明标准名称似乎是 strnlen_s
但这不是由 GCC 定义的。
问题是:我假设 strnlen
是最便携的名称是否正确,或者我可以做些什么来使代码最 portable/standard?
注意:Microsoft (https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strnlen-strnlen-s) 实现了这两个函数,区别在于 strnlen_s
检查字符串指针是否为 NULL
和 returns 0
这种情况下 strnlen
没有这样的检查。
string 是 c++ 头文件,string.h 是 c 头文件(至少对于 gcc 是这样)。 strlen_s (afaik) 是 Microsoft extension to the C library。你说得对,strlen 会更标准。如果需要字节数,也可以使用 memchr。对于@Basile 的观点,如果你需要字符数,你需要一些支持 UTF-8 的东西。
The question is: am I correct to assume that strnlen is the most portable name to use or what could I do for the code to be most portable/standard?
不,它根本不可移植。它从来不是 C 的一部分。它包含在 POSIX 中,这并不重要。
我会想象标准中不存在该功能的原因,可能是因为当我们已经有 memchr(str, '[=11=]', max);
.
时它是多余的
strnlen_s
是 C11 附件 K 中可选边界检查接口的一部分。整章结果是一个巨大的失败,几乎没有任何编译器实现它。 Microsoft 有类似的命名函数,但它们有时不兼容。所以我假设所有 _s
函数都是完全不可移植的。
所以这两个都不用,用memchr
或strlen
。
编辑
如果您出于某种原因必须自己实施strnlen
,那么我建议您这样做:
#include <string.h>
size_t strnlength (const char* s, size_t n)
{
const char* found = memchr(s, '[=10=]', n);
return found ? (size_t)(found-s) : n;
}
strnlen_s()
在 C 标准的附件 K 中指定,从版本 C11 开始。这个附件没有广泛实施,甚至微软的实施也不完全符合指定的版本。语义是扭曲的,尤其是在错误处理方面。我建议不要使用它。
strnlen()
是 POSIX.1-2008 中指定的一个简单函数,可在许多平台上使用。在不提供的平台上很容易实现:
#include <string.h>
size_t strnlen(const char *s, size_t n) {
size_t i;
for (i = 0; i < n && s[i] != '[=10=]'; i++)
continue;
return i;
}
The question is: am I correct to assume that strnlen
is the most portable name to use or what could I do for the code to be most portable/standard?
对于 C,strnlen
可以,因为该名称未保留。它不是标准的一部分,所以你可以添加。
POSIX reserves str...()
,因此您可能想使用其他名称。
strnlen_s
与 K.3.7.4.4 冲突 strnlen_s 函数 并且有一个有争议的历史,您可能不希望将您的代码绑定到其中。避免将函数命名为 strnlen_s()
.
我会避免与公共库的名称联盟,其中任何函数都添加了 2 个名称:正式的 less-likely-to-collide-name 和 macro
size_t nielsen_strnlen(const char *s, size_t maxsize);
#define slength nielsen_strnlen
或者干脆直接去不太可能发生碰撞的东西。
size_t nstrnlen(const char *s, size_t maxsize);
更深入:OP 似乎想要使用标准 C 库(或当前版本)之外的流行函数,但在将代码移植到其他系统时可能可用。 OP 希望提供一个 use-my-code-if-not-available 功能。
小心行事。
我会使用宏(或包装函数)
#if ON_SYSTEM_WITH_strnlen
#define slength strnlen
#else
#define slength nielsen_strnlen
#endif
... 然后调用 slenth()
.
当 OP 的代码版本完全不符合预期(今天和明天)或者因为它不是标准时,问题就会出现,各种实现有所不同 - 在其实现上有一点点。为了减轻影响,请考虑使用宏或函数包装器间接寻址。
附带问题:参数顺序和潜在的 new principle to the "original principles" of C。
size_t foo1(const char *s, size_t maxsize);
// arranged such that the size of an array appears before the array.
size_t foo2(size_t maxsize, const char *s);
size_t foo3(size_t maxsize, const char s[maxsize]);
在我当前的项目中,我正在根据 C11 标准(使用 gcc -std=c11
构建)进行编码,并且需要类似 strnlen
的东西(strlen
的“安全”版本 returns 以 0 结尾的字符串的长度,但不超过给定的最大值)。所以我查了一下(例如 https://en.cppreference.com/w/c/string/byte/strlen),似乎 C11 标准提到了这样一个函数,但是名字是 strnlen_s
.
因此我选择了 strnlen_s
,但是当包含 string.h
时结果是未定义的。另一方面,strnlen
已定义,所以我目前的解决方案是使用 strnlen
并注明标准名称似乎是 strnlen_s
但这不是由 GCC 定义的。
问题是:我假设 strnlen
是最便携的名称是否正确,或者我可以做些什么来使代码最 portable/standard?
注意:Microsoft (https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strnlen-strnlen-s) 实现了这两个函数,区别在于 strnlen_s
检查字符串指针是否为 NULL
和 returns 0
这种情况下 strnlen
没有这样的检查。
string 是 c++ 头文件,string.h 是 c 头文件(至少对于 gcc 是这样)。 strlen_s (afaik) 是 Microsoft extension to the C library。你说得对,strlen 会更标准。如果需要字节数,也可以使用 memchr。对于@Basile 的观点,如果你需要字符数,你需要一些支持 UTF-8 的东西。
The question is: am I correct to assume that strnlen is the most portable name to use or what could I do for the code to be most portable/standard?
不,它根本不可移植。它从来不是 C 的一部分。它包含在 POSIX 中,这并不重要。
我会想象标准中不存在该功能的原因,可能是因为当我们已经有 memchr(str, '[=11=]', max);
.
strnlen_s
是 C11 附件 K 中可选边界检查接口的一部分。整章结果是一个巨大的失败,几乎没有任何编译器实现它。 Microsoft 有类似的命名函数,但它们有时不兼容。所以我假设所有 _s
函数都是完全不可移植的。
所以这两个都不用,用memchr
或strlen
。
编辑
如果您出于某种原因必须自己实施strnlen
,那么我建议您这样做:
#include <string.h>
size_t strnlength (const char* s, size_t n)
{
const char* found = memchr(s, '[=10=]', n);
return found ? (size_t)(found-s) : n;
}
strnlen_s()
在 C 标准的附件 K 中指定,从版本 C11 开始。这个附件没有广泛实施,甚至微软的实施也不完全符合指定的版本。语义是扭曲的,尤其是在错误处理方面。我建议不要使用它。
strnlen()
是 POSIX.1-2008 中指定的一个简单函数,可在许多平台上使用。在不提供的平台上很容易实现:
#include <string.h>
size_t strnlen(const char *s, size_t n) {
size_t i;
for (i = 0; i < n && s[i] != '[=10=]'; i++)
continue;
return i;
}
The question is: am I correct to assume that
strnlen
is the most portable name to use or what could I do for the code to be most portable/standard?
对于 C,strnlen
可以,因为该名称未保留。它不是标准的一部分,所以你可以添加。
POSIX reserves str...()
,因此您可能想使用其他名称。
strnlen_s
与 K.3.7.4.4 冲突 strnlen_s 函数 并且有一个有争议的历史,您可能不希望将您的代码绑定到其中。避免将函数命名为 strnlen_s()
.
我会避免与公共库的名称联盟,其中任何函数都添加了 2 个名称:正式的 less-likely-to-collide-name 和 macro
size_t nielsen_strnlen(const char *s, size_t maxsize);
#define slength nielsen_strnlen
或者干脆直接去不太可能发生碰撞的东西。
size_t nstrnlen(const char *s, size_t maxsize);
更深入:OP 似乎想要使用标准 C 库(或当前版本)之外的流行函数,但在将代码移植到其他系统时可能可用。 OP 希望提供一个 use-my-code-if-not-available 功能。
小心行事。
我会使用宏(或包装函数)
#if ON_SYSTEM_WITH_strnlen
#define slength strnlen
#else
#define slength nielsen_strnlen
#endif
... 然后调用 slenth()
.
当 OP 的代码版本完全不符合预期(今天和明天)或者因为它不是标准时,问题就会出现,各种实现有所不同 - 在其实现上有一点点。为了减轻影响,请考虑使用宏或函数包装器间接寻址。
附带问题:参数顺序和潜在的 new principle to the "original principles" of C。
size_t foo1(const char *s, size_t maxsize);
// arranged such that the size of an array appears before the array.
size_t foo2(size_t maxsize, const char *s);
size_t foo3(size_t maxsize, const char s[maxsize]);