首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用strncpy_s()函数实现strncpy()功能?

如何用strncpy_s()函数实现strncpy()功能?
EN

Stack Overflow用户
提问于 2011-02-18 15:18:22
回答 4查看 9.4K关注 0票数 7

在某些情况下,我确实需要strncpy()函数-例如,我在一个预定义的接口中有一个函数,它传递了缓冲区的地址和缓冲区的大小:

代码语言:javascript
运行
复制
HRESULT someFunction( char* buffer, size_t length );

我可以复制一个以null结尾的字符串,长度不超过length -如果它的长度正好是length,我不会null终止字符串,调用者知道字符串以null字符或长度length结尾,无论哪个先发生,它都可以工作。

当然,我将使用strncpy()实现这一点

代码语言:javascript
运行
复制
HRESULT someFunction( char* buffer, size_t length )
{
    const char* toCopy = ...
    size_t actualLength = strlen( toCopy );
    if( actualLength > length ) {
        return E_UNEXPECTED; // doesn't fit, can't do anything reasonable 
    }
    strncpy( buffer, toCopy, length );
    return S_OK;
}

现在我有了这段代码,需要将它从Visual C++ 7迁移到Visual C++ 9。我编译它,然后使用see a warning that strncpy() is unsafe,我应该使用strncpy_s()

strncpy_s()被设计为总是空终止缓冲区,所以在上面的场景中我不能直接使用它作为替代。我必须在比length - 1更长的字符串上返回E_UNEXPECTED (而不是像以前那样返回length ),否则一旦字符串是length或更长的字符串,它将触发一个无效参数错误处理程序,否则程序将运行到未定义的行为。

到目前为止,我应用的解决方案是定义一个_CRT_SECURE_NO_WARNINGS,然后让编译器关闭。

有没有办法使用strncpy_s()作为strncpy()的实际替代品

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-08-01 17:44:21

对于具有固定目标缓冲区的场景,尝试使用str*cpy*()函数是一种常见的误解。这里的处理是,这些函数“复制,直到出现空字符或其他条件”。在这个场景中,有这样的代码:

代码语言:javascript
运行
复制
size_t actualLength = strlen( toCopy );
if( actualLength > length ) {
    return E_UNEXPECTED; // doesn't fit, can't do anything reasonable 
}

因此,在进行复制之前,代码知道实际的字符串长度。一旦知道了长度,就只有使用memcpy()才有意义,因为它允许一次复制多个字符,并且不会检查每个字符是否有空终止符,因此对于这种情况来说,它是直接和简洁的,并且作为副作用也更快。

代码语言:javascript
运行
复制
HRESULT someFunction( char* buffer, size_t length )
{
    const char* toCopy = ...
    size_t actualLength = strlen( toCopy );
    if( actualLength > length ) {
        return E_UNEXPECTED; // doesn't fit, can't do anything reasonable 
    }
    memcpy( buffer, toCopy, min( length, actualLength + 1 ) );
    return S_OK;
}

所以解决方案就是忘记strncpy()strncpy_s(),转而使用memcpy()

票数 2
EN

Stack Overflow用户

发布于 2011-02-18 15:31:14

您在这里面临的问题是您的函数本身是不安全的,就像strncpy()一样。这是不安全的,因为函数的调用者可能会忘记返回的字符串不是以null结尾的。如果这确实是您的函数所期望的行为,我建议不要定义_CRT_SECURE_NO_WARNINGS并全局禁用警告,而是使用#pragmas

代码语言:javascript
运行
复制
// document here exactly why you can not use strncpy_s
#pragma warning( push )
#pragma warning( disable : 4996 )
// your code that uses strncpy instead of strncpy_s
#pragma warning( pop ) 

这样,您就可以仅在绝对必须使用不安全函数的情况下禁用这些警告。

票数 5
EN

Stack Overflow用户

发布于 2011-02-18 15:45:11

您可以改用memcpy_s

代码语言:javascript
运行
复制
HRESULT someFunction( char* buffer, size_t length )
{
    const char* toCopy = ...
    size_t actualLength = strlen( toCopy );
    if( actualLength > length ) {
        return E_UNEXPECTED; // doesn't fit, can't do anything reasonable 
    }
    else if ( actualLength < length ) {
        actualLength++; // copy null terminator too
    }
    memcpy_s( buffer, length, toCopy, actualLength );
    return S_OK;
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5038614

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档