strncpy (Strings) – C 中文开发手册

[
  •   C 语言中文开发手册

    strncpy (Strings) - C 中文开发手册

    在头文件<string.h>中定义
    (1)
    char * strncpy(char * dest,const char * src,size_t count); (直到C99)
    char * strncpy(char * restrict dest,const char * restrict src,size_t count); (自C99以来)
    errno_t strncpy_s(char * restrict dest,rsize_t destsz,const char * restrict src,rsize_t count); (2) (自C11以来)

    1)将由src指向的字符数组的大部分计数字符(包括终止空字符,但不包括空字符后面的任何字符)复制到由dest指向的字符数组。如果在复制完整个数组src之前达到count,则生成的字符数组不会以null结尾。如果在复制src中的终止空字符之后,未达到count,则将额外的空字符写入dest,直到写入总计数字符。如果字符数组重叠,如果dest或src不是指向字符数组的指针(包括如果dest或src是空指针),如果dest指向的数组大小小于count,则行为未定义, 或者如果src指向的数组大小小于count并且不包含空字符。2)与(1)相同,除了该函数不会继续将零写入目标数组以填充计数,它将在写入终止空字符后停止(如果源中没有空值,它将在dest处写入一个 [count]然后停止)。 此外,在运行时检测到以下错误并调用当前安装的约束处理函数:src或者dest是空指针destsz或者count是零或大于RSIZE_MAX count大于或等于destsz,但destsz小于或等于strnlen_s(src, count),换句话说,会发生截断源和目标字符串之间会发生重叠如果dest <strnlen_s(src,destsz)<= destsz指向的字符数组的大小,则行为不确定; 换句话说,destsz的错误值不会暴露即将发生的缓冲区溢出。 如果字符数组的大小由src <strnlen_s(src,count)<destsz; 换句话说,count的错误值不会暴露即将发生的缓冲区溢出。作为所有边界检查函数,只有当__STDC_LIB_EXT1__由实现定义并且用户在包含string.h之前将__STDC_WANT_LIB_EXT1__定义为整数常量1时,strncpy_s才能保证可用。

    参数

    dest - 指向要复制到的字符数组的指针
    SRC - 指向要复制的字符数组的指针
    count - 最大数量的字符复制
    destsz - 目标缓冲区的大小

    返回值

    1)返回 dest 副本2)在成功时返回零,错误时返回非零值。 另外,如果出错,则将0写入dest [0](除非dest为空指针或destsz为零或大于RSIZE_MAX),并可能用未指定的值来摧毁目标数组的其余部分。

    注意

    正如后C11 DR 468所纠正的那样,strncpy_s与strcpy_s不同,只有在发生错误时才允许对目标数组的其余部分进行截断。与strncpy不同,strncpy_s不会用零填充目标数组,这是将现有代码转换为边界检查版本时常见的错误来源。尽管适合目标缓冲区的截断存在安全风险,并因此违反了strncpy_s的运行时间约束,但可以通过指定count等于目标数组的大小减1来获得截断行为:它将复制第一个计数字节和 像往常一样追加空终止符:strncpy_s(dst,sizeof dst,src,(sizeof dst)-1);

    #define __STDC_WANT_LIB_EXT1__ 1
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(void)
    {
        char src[] = "hi";
        char dest[6] = "abcdef"; // no null terminator
        strncpy(dest, src, 5); // writes five characters 'h', 'i', '\0', '\0', '\0' to dest
        printf("strncpy(dest, src, 5) to a 6-byte dest gives : ");
        for(size_t n = 0; n < sizeof dest; ++n) {
            char c = dest[n];
            c ? printf("'%c' ", c) : printf("'\\0' ");
        }
     
        printf("\nstrncpy(dest2, src, 2) to a 2-byte dst gives : ");
        char dest2[2];
        strncpy(dest2, src, 2); // truncation: writes two characters 'h', 'i', to dest2
        for(size_t n = 0; n < sizeof dest2; ++n) {
            char c = dest2[n];
            c ? printf("'%c' ", c) : printf("'\\0' ");
        }
        printf("\n");
     
    #ifdef __STDC_LIB_EXT1__
        set_constraint_handler_s(ignore_handler_s);
        char dst1[6], src1[100] = "hello";
        int r1 = strncpy_s(dst1, 6, src1, 100);      // writes 0 to r1, 6 characters to dst1
        printf("dst1 = \"%s\", r1 = %d\n", dst1,r1); // 'h','e','l','l','o','\0' to dst1
     
        char dst2[5], src2[7] = {'g','o','o','d','b','y','e'};
        int r2 = strncpy_s(dst2, 5, src2, 7);        // copy overflows the destination array
        printf("dst2 = \"%s\", r2 = %d\n", dst2,r2); // writes nonzero to r2,'\0' to dst2[0]
     
        char dst3[5];
        int r3 = strncpy_s(dst3, 5, src2, 4);        // writes 0 to r3, 5 characters to dst3
        printf("dst3 = \"%s\", r3 = %d\n", dst3,r3); // 'g', 'o', 'o', 'd', '\0' to dst3 
    #endif
    }

    可能的输出:

    strncpy(dest, src, 5) to a 6-byte dst gives : 'h' 'i' '\0' '\0' '\0' 'f'
    strncpy(dest2, src, 2) to a 2-byte dst gives : 'h' 'i'
    dst1 = "hello", r1 = 0
    dst2 = "", r2 = 22
    dst3 = "good", r3 = 0

    参考

    C11标准(ISO / IEC 9899:2011): 7.24.2.4 strncpy函数(p:363-364) K.3.7.1.4 strncpy_s函数(p:616-617) C99标准(ISO / IEC 9899:1999): 7.21.2.4 strncpy函数(p:326-327) C89 / C90标准(ISO / IEC 9899:1990): 4.11.2.4 strncpy函数

    扩展内容

    strcpystrcpy_s(C11) 将一个字符串复制到另一个(函数)
    memcpymemcpy_s(C11) 将一个缓冲区复制到另一个(功能)
    strndup (dynamic memory TR) 将字符串的副本分配给指定大小(函数)

    | 用于strncpy的C ++文档 |

  •   C 语言中文开发手册
    ]
    转载请保留页面地址:https://www.breakyizhan.com/c-3/28045.html

    posted on 2020-07-09 10:30  MrAit  阅读(312)  评论(0编辑  收藏  举报

    导航