Share via


strncpy, _strncpy_l, wcsncpy, _wcsncpy_l, _mbsncpy, _mbsncpy_l

将一个字符串的字符复制到另一个字符串。 提供这些函数的更安全版本;请参阅 strncpy_s_strncpy_s_lwcsncpy_s_wcsncpy_s_l_mbsncpy_s_mbsncpy_s_l

重要

_mbsncpy_mbsncpy_l 无法用于在 Windows 运行时中执行的应用程序。 有关详细信息,请参阅通用 Windows 平台应用中不支持的 CRT 函数

语法

char *strncpy(
   char *strDest,
   const char *strSource,
   size_t count
);
char *_strncpy_l(
   char *strDest,
   const char *strSource,
   size_t count,
   _locale_t locale
);
wchar_t *wcsncpy(
   wchar_t *strDest,
   const wchar_t *strSource,
   size_t count
);
wchar_t *_wcsncpy_l(
   wchar_t *strDest,
   const wchar_t *strSource,
   size_t count,
   _locale_t locale
);
unsigned char *_mbsncpy(
   unsigned char *strDest,
   const unsigned char *strSource,
   size_t count
);
unsigned char *_mbsncpy_l(
   unsigned char *strDest,
   const unsigned char *strSource,
   size_t count,
   _locale_t locale
);
template <size_t size>
char *strncpy(
   char (&strDest)[size],
   const char *strSource,
   size_t count
); // C++ only
template <size_t size>
char *_strncpy_l(
   char (&strDest)[size],
   const char *strSource,
   size_t count,
   _locale_t locale
); // C++ only
template <size_t size>
wchar_t *wcsncpy(
   wchar_t (&strDest)[size],
   const wchar_t *strSource,
   size_t count
); // C++ only
template <size_t size>
wchar_t *_wcsncpy_l(
   wchar_t (&strDest)[size],
   const wchar_t *strSource,
   size_t count,
   _locale_t locale
); // C++ only
template <size_t size>
unsigned char *_mbsncpy(
   unsigned char (&strDest)[size],
   const unsigned char *strSource,
   size_t count
); // C++ only
template <size_t size>
unsigned char *_mbsncpy_l(
   unsigned char (&strDest)[size],
   const unsigned char *strSource,
   size_t count,
   _locale_t locale
); // C++ only

参数

strDest
目标字符串。

strSource
资源字符串。

count
要复制的字符数。

locale
要使用的区域设置。

返回值

返回 strDest。 没有保留任何返回值以指示错误。

备注

strncpy 函数将 count 的初始 strSource 字符复制到 strDest 并返回 strDest。 如果 count 小于或等于 strSource 的长度,则将不会自动向复制的字符串追加 null 字符。 如果 count 大于 strSource 的长度,则目标字符串将用长度最长 count 的 null 字符填补。 如果源和目标字符串重叠,则 strncpy 的行为是未定义的。

重要

strncpy 将不检查 strDest 中空间是否足够;这将使其成为缓冲区溢出的一个可能的原因。 count 参数将限制复制的字符数;这不是 strDest 的大小限制。 请参阅以下示例。 有关详细信息,请参阅避免缓冲区溢出

如果 strDeststrSource 是一个 NULL 指针,或如果 count 小于或等于 0,则将调用无效的参数处理程序,如参数验证中所述。 如果允许继续执行,则这些函数返回 -1 并将 errno 设置为 EINVAL

wcsncpy_mbsncpy 分别是 strncpy 的宽字符及多字节字符版本。 wcsncpy_mbsncpy 的参数和返回值将相应变化。 否则这六个函数具有相同行为。

这些带有 _l 后缀的函数的版本相同,只不过它们使用传递区域设置而不是其与区域设置相关的行为的当前区域设置。 有关详细信息,请参阅 Locale

在 C++ 中,这些函数具有模板重载,以调用这些函数的更新、更安全副本。 有关详细信息,请参阅安全模板重载

默认情况下,此函数的全局状态范围限定为应用程序。 若要更改此行为,请参阅 CRT 中的全局状态

一般文本例程映射

TCHAR.H 例程 _UNICODE_MBCS 未定义 _MBCS 已定义 _UNICODE 已定义
_tcsncpy strncpy _mbsnbcpy wcsncpy
_tcsncpy_l _strncpy_l _mbsnbcpy_l _wcsncpy_l

注意

_strncpy_l_wcsncpy_l 没有区域设置依赖项,它们只是为了 _tcsncpy_l 提供的,不能直接调用。

要求

例程 必需的标头
strncpy <string.h>
wcsncpy <string.h><wchar.h>
_mbsncpy_mbsncpy_l <mbstring.h>

有关更多平台兼容性信息,请参阅兼容性

示例

以下示例演示 strncpy 的使用以及使用不当将如何导致程序 Bug 和安全问题。 编译器会为每个对 strncpy 的调用生成警告,类似于crt_strncpy_x86.c(15):警告 C4996:“strncpy”:此函数或变量可能不安全。请考虑改用 strncpy_s。若要禁止弃用,请使用 _CRT_SECURE_NO_WARNINGS。有关详细信息,请参阅联机帮助

// crt_strncpy_x86.c
// Use this command in an x86 developer command prompt to compile:
// cl /TC /W3 crt_strncpy_x86.c

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

int main() {
   char t[20];
   char s[20];
   char *p = 0, *q = 0;

   strcpy_s(s, sizeof(s), "AA BB CC");
   // Note: strncpy is deprecated; consider using strncpy_s instead
   strncpy(s, "aa", 2);     // "aa BB CC"         C4996
   strncpy(s + 3, "bb", 2); // "aa bb CC"         C4996
   strncpy(s, "ZZ", 3);     // "ZZ",              C4996
                            // count greater than strSource, null added
   printf("%s\n", s);

   strcpy_s(s, sizeof(s), "AA BB CC");
   p = strstr(s, "BB");
   q = strstr(s, "CC");
   strncpy(s, "aa", p - s - 1);   // "aa BB CC"   C4996
   strncpy(p, "bb", q - p - 1);   // "aa bb CC"   C4996
   strncpy(q, "cc",  q - s);      // "aa bb cc"   C4996
   strncpy(q, "dd", strlen(q));   // "aa bb dd"   C4996
   printf("%s\n", s);

   // some problems with strncpy
   strcpy_s(s, sizeof(s), "test");
   strncpy(t, "this is a very long string", 20 ); // C4996
   // Danger: at this point, t has no terminating null,
   // so the printf continues until it runs into one.
   // In this case, it will print "this is a very long test"
   printf("%s\n", t);

   strcpy_s(t, sizeof(t), "dogs like cats");
   printf("%s\n", t);

   strncpy(t + 10, "to chase cars.", 14); // C4996
   printf("%s\n", t);

   // strncpy has caused a buffer overrun and corrupted string s
   printf("Buffer overrun: s = '%s' (should be 'test')\n", s);
   // Since the stack grows from higher to lower addresses, buffer
   // overruns can corrupt function return addresses on the stack,
   // which can be exploited to run arbitrary code.
}

输出

ZZ
aa bb dd
this is a very long test
dogs like cats
dogs like to chase cars.
Buffer overrun: s = 'ars.' (should be 'test')

自动变量的布局和错误检测以及代码保护的级别可能随更改的编辑器设置而改变。 此示例在内置其他编译环境或使用其他编译器选项时可能会有不同的结果。

另请参阅

字符串操作
区域设置
多字节字符序列的解释
_mbsnbcpy_mbsnbcpy_l
strcatwcscat_mbscat
strcmpwcscmp_mbscmp
strcpywcscpy_mbscpy
strncat_strncat_lwcsncat_wcsncat_l_mbsncat_mbsncat_l
strncmpwcsncmp_mbsncmp_mbsncmp_l
_strnicmp_wcsnicmp_mbsnicmp_strnicmp_l_wcsnicmp_l_mbsnicmp_l
strrchrwcsrchr_mbsrchr_mbsrchr_l
_strset_strset_l_wcsset_wcsset_l_mbsset_mbsset_l
strspnwcsspn_mbsspn_mbsspn_l
strncpy_s_strncpy_s_lwcsncpy_s_wcsncpy_s_l_mbsncpy_s_mbsncpy_s_l
strcpy_swcscpy_s_mbscpy_s