strncpy 订阅
strncpy函数用于将指定长度的字符串复制到字符数组中,是 C语言的库函数之一,来自 C语言标准库,定义于 string.h。语法形式为:char *strncpy(char *dest, const char *src, int n),表示把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回被复制后的dest。 [1-2] 展开全文
strncpy函数用于将指定长度的字符串复制到字符数组中,是 C语言的库函数之一,来自 C语言标准库,定义于 string.h。语法形式为:char *strncpy(char *dest, const char *src, int n),表示把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回被复制后的dest。 [1-2]
信息
头文件
string.h
属    于
库函数
适    用
电脑编程
来    自
C语言标准库
中文名
strncpy
功    能
串拷贝
外文名
strncpy
strncpystrncpy基本格式
char *strncpy(char *destinin, char *source, int maxlen);destinin:表示复制的目标字符数组;source:表示复制的源字符数组;maxlen:表示复制的字符串长度。 [3] 
收起全文
精华内容
下载资源
问答
  • strncpy
    2021-05-19 10:00:28

    strncpy_s

    在头文件中定义

    (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

    作为所有边界检查函数,只有当__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

    #include

    #include

    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 ++文档|

    更多相关内容
  • 问题:函数memcpy(dest, src, sizeof(dest))、strncpy(dest, src, sizeof(dest))和snprintf(dest, sizeof(dest), “%s”, src)都可以将src字符串中的内容拷贝到dest字符串中。哪一种方式效率最高呢?就是说,哪种...
  • strncpy的正确用法: strncpy(dest, src, sizeof(dest));dest[sizeof(dest)-1] = ‘\0′; snprintf的正确用法:snprintf(dest, sizeof(dest), “%s”, src); strncpy的问题:1.size一定要用sizeof(dest)或sizeof...
  • 比如说strncpy函数,在linux kernel上是这样写的 /**  * strncpy – Copy a length-limited, %NUL-terminated string  * @dest: Where to copy the string to  * @src: Where to copy the string from  
  • strcpy 和strcnpy函数是字符串复制函数。接下来通过本文给大家介绍c语言中的strcpy和strncpy字符串函数使用,感兴趣的朋友跟随小编要求看看吧
  • 附加说明:如果参数 dest 所指的内存空间不够大,可能会造成缓冲溢出(buffer Overflow)的错误情况,在编写程序时请特别留意,或者用strncpy()来取代。 范例 #include main(){ char a[30] = string
  • 打包文件包含两个文件:c文件源代码、Makefile文件,运行环境在Ubuntu14.04下,使用自带的gcc编译器,同学们只需将文件夹复制到某一目录下之后在终端执行:1.“make”生成“test”可执行文件;2. 输入“./test”运行...
  • 电子-strncpy的用法.pdf

    2019-09-05 16:32:11
    电子-strncpy的用法.pdf,单片机/嵌入式STM32-F0/F1/F2
  • strncpy

    2018-04-01 19:27:59
    strncpychar *strncpy(char *destination, const char *source, size_t num);1. Copy characters from string Copies the first num characters of source to destination. If the end of the source C strin...

    strncpy

    char *strncpy(char *destination, const char *source, size_t num);
    1. Copy characters from string
            Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.
            No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).
            destination and source shall not overlap (see memmove for a safer alternative when overlapping).
    1.1 Parameters
    destination
            Pointer to the destination array where the content is to be copied.
    source
            C string to be copied.
    num
            Maximum number of characters to be copied from source.
            size_t is an unsigned integral type.
    1.2 Return Value
            destination is returned.
    2. Example
    2.1 example

    /*
     ============================================================================
     Name        : strncpy_example_1.c
     Author      : foreverstrong
     Version     :
     Copyright   : Your copyright notice
     Description : strncpy in C, Ansi-style
     ============================================================================
     */
    
    /* strncpy example */
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
    	char str1[] = "To be or not to be";
    	char str2[40];
    	char str3[40];
    
    	/* copy to sized buffer (overflow safe): */
    	strncpy(str2, str1, sizeof(str2));
    
    	/* partial copy (only 5 chars): */
    	strncpy(str3, str2, 5);
    	str3[5] = '\0'; /* null character manually added */
    
    	puts(str1);
    	puts(str2);
    	puts(str3);
    
    	return 0;
    }

    Output:

    To be or not to be
    To be or not to be
    To be
    
    3. strncpy, strncpy_s
            Defined in header <string.h>
    (1)

    char *strncpy(char *dest, const char *src, size_t count); (until C99)
    char *strncpy(char *restrict dest, const char *restrict src, size_t count); (since C99)
    (2)
    errno_t strncpy_s(char *restrict dest, rsize_t destsz, const char *restrict src, rsize_t count); (since C11)
            1) Copies at most count characters of the character array pointed to by src (including the terminating null character, but not any of the characters that follow the null character) to character array pointed to by dest.
            复制 src 所指向的字符数组的至多 count 个字符 (包含空终止字符,但不包含空字符后的任何字符) 到 dest 所指向的字符数组。
            If count is reached before the entire array src was copied, the resulting character array is not null-terminated.
            若在完全复制整个 src 数组前抵达 count ,则结果的字符数组不是空终止的。
            If, after copying the terminating null character from src, count is not reached, additional null characters are written to dest until the total of count characters have been written.
            若在复制来自 src 的空终止字符后未抵达 count,则写入额外的空字符到 dest,直至写入总共 count 个字符。
            The behavior is undefined if the character arrays overlap, if either dest or src is not a pointer to a character array (including if dest or src is a null pointer), if the size of the array pointed to by dest is less than count, or if the size of the array pointed to by src is less than count and it does not contain a null character.
            若字符数组重叠,若 dest 或 src 不是指向字符数组的指针 (包含若 dest 或 src 为空指针),若 dest 所指向的数组大小小于 count,或若 src 所指向的数组大小小于 count 且它不含空字符,则行为未定义。
            2) Same as (1), except that the function does not continue writing zeroes into the destination array to pad up to count, it stops after writing the terminating null character (if there was no null in the source, it writes one at dest[count] and then stops). Also, the following errors are detected at runtime and call the currently installed constraint handler function:
            同 (1) ,除了函数不持续写入零到目标数组以填满 count,它在写入空终止字符后停止 (若源中无空字符,则它于 dest[count] 写入一个然后停止)。并且在运行时检测下列错误,并调用当前安装的制约处理函数:
            src or dest is a null pointer
            destsz or count is zero or greater than RSIZE_MAX
           count is greater or equal destsz, but destsz is less or equal strnlen_s(src, count), in other words, truncation would occur
           overlap would occur between the source and the destination strings (源和目标字符串间会出现重叠)
            The behavior is undefined if the size of the character array pointed to by dest < strnlen_s(src, destsz) <= destsz; in other words, an erroneous value of destsz does not expose the impending buffer overflow. The behavior is undefined if the size of the character array pointed to by src < strnlen_s(src, count) < destsz; in other words, an erroneous value of count does not expose the impending buffer overflow.
            若 dest 所指的字符数组大小 < strnlen_s(src, destsz) <= destsz,则行为未定义;换言之,错误的 destsz 值不暴露即将发生的缓冲区溢出。若 src 所指的字符数组大小 < strnlen_s(src, count) < destsz,则行为未定义;换言之,错误的 count 值不暴露即将发生的缓冲区溢出。
            As all bounds-checked functions, strncpy_s is only guaranteed to be available if __STDC_LIB_EXT1__ is defined by the implementation and if the user defines __STDC_WANT_LIB_EXT1__ to the integer constant 1 before including string.h.
            同所有边界检查函数, strncpy_s 仅若实现定义了 __STDC_LIB_EXT1__ ,且用户在包含 string.h 前定义 __STDC_WANT_LIB_EXT1__ 为整数常量 1 才保证可用。
    3.1 Parameters
            dest - pointer to the character array to copy to
            src - pointer to the character array to copy from
            count - maximum number of characters to copy
            destsz - the size of the destination buffer
    3.2 Return value
            1) returns a copy of dest
            2) returns zero on success, returns non-zero on error. Also, on error, writes zero to dest[0] (unless dest is a null pointer or destsz is zero or greater than RSIZE_MAX) and may clobber the rest of the destination array with unspecified values.
    3.3 Notes
            As corrected by the post-C11 DR 468, strncpy_s, unlike strcpy_s, is only allowed to clobber the remainder of the destination array if an error occurs.
            strncpy_s 不同于 strcpy_s,仅若错误发生才被允许破坏目标数组的剩余部分。
            Unlike strncpy, strncpy_s does not pad the destination array with zeroes, This is a common source of errors when converting existing code to the bounds-checked version.
            Although truncation to fit the destination buffer is a security risk and therefore a runtime constraints violation for strncpy_s, it is possible to get the truncating behavior by specifying count equal to the size of the destination array minus one: it will copy the first count bytes and append the null terminator as always: strncpy_s(dst, sizeof dst, src, (sizeof dst)-1);
    4. Example
    4.1 example

    Run this code

    /*
     ============================================================================
     Name        : strncpy_example_2.c
     Author      : foreverstrong
     Version     :
     Copyright   : Your copyright notice
     Description : strncpy in C, Ansi-style
     ============================================================================
     */
    
    /* strncpy example */
    #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
    }
    
    Possible output:
    strncpy(dest, src, 5) to a 6-byte dest gives : 'h' 'i' '\0' '\0' '\0' 'f' 
    strncpy(dest2, src, 2) to a 2-byte dst gives : 'h' 'i' 

    References
    http://zh.cppreference.com/w/c/string/byte/strncpy
    http://en.cppreference.com/w/c/string/byte/strncpy
    http://www.cplusplus.com/reference/cstring/strncpy/

    展开全文
  • 用于了解安全函数strcpy_s、strncpy_s、snprintf_s、memcpy_s
  • 【那些年C++趟过的坑】strncpy字符串截断缺陷

    多人点赞 热门讨论 2022-07-09 14:05:36
    为了解决这个问题,strncpy诞生了,先看下定义:strncpy加一个参数num, 意为最大可拷贝的空间大小,就是说当字符串src长度比dest大时,会自动截断。 不过谁知道呢,strncpy会不会在截断发生时被’\0’呢。............


    前言

    char * strcpy(char* dest, const char *src)

    字符串拷贝strcpy,学过C/C++的人都非常熟悉,但这个函数有一个需要注意的地方,当字符串src大小比目标数组dest大时,那就会内存越界,发生崩溃。为了解决这个问题,strncpy诞生了,先看下定义:

    char * strncpy ( char * dest, const char * src, size_t num )

    strncpy加一个参数num, 意为最大可拷贝的空间大小,就是说当字符串src长度比dest大时,会自动截断。
    不过谁知道呢,strncpy会不会在截断发生时被’\0’呢。

    小贴士: C语言字符串末尾是以’\0’结尾的,如:
    char p[] = “Hello World!”; 实际上这实际存储空间比字符串“Hello World!”大一个,因为最后有一个’\0’。

    于是有一段时间,为了毫无顾忌的使用strncpy,有了下面丑陋的宏定义

    #define my_strncpy(dst, src) strncpy(dst, src, sizeof(dst)-1 >= strlen(src) ? strlen(src) : sizeof(dst)-1)
    

    代码解释:

    sizeof(dst)是目标数组的大小,sizeof(dst)-1是为了发生截断是留下一个’\0’的位置,strlen(src)是待拷贝字符串的长度。目标数组大小减1大于等于待拷贝字符串长度时,也就不会发生截断,则num=strlen(src); 反之,发生截断时,则num=sizeof(dst)-1。
    这样做看似,保证了发生截断时,预留一下一个‘\0’位置, 但真的靠谱吗?
    (先说结论:不靠谱,以免一些急于寻找结果的,没往下看,直接采用上面宏定义代码)
    如果对探究过程不感兴趣,只想知道结果,可以直接跳到1.5章节看结论,那里会对strncpy缺陷作一个总结 ==>传送门


    一、探究strncp字符拷贝截断缺陷

    通过前言部分,我们知道了,strcpy不可靠,可能发生数组越界引发崩溃,而strncpy貌似也用着不踏实。所以这一节我们做几个实验看看strcpy在各种情况下的表现。

    char * strncpy ( char * dest, const char * src, size_t num )
    

    下面通过四个小实验来探究下strncpy是不有缺陷:
    未截断时:
    1、dst长度正好等于src长度+1 (strncpy是否会自动补’\0’ )
    2、dst长度远大于src长度(strncpy是否会操作长度超出部分的内存)
    截断时:
    3、dst长度-1比src长度小(截断时是否会补’\0’)
    4、num长度是dst长度-1 (故意预留一个位置,看看是否会补‘\0’)

    1.1 dst长度等于src长度 + 1 (未截断)

    char * strncpy ( char * dest, const char * src, size_t num )
    

    这种情况下,dst正好能盛放src,并且后面应该会补一个’\0’。
    代码如下:

    #include <stdio.h>
    #include <memory.h>
    int main()
    {
            char szTemp[13];
            memset(szTemp, 1, sizeof(szTemp));
            strncpy(szTemp, "Hello World!", sizeof(szTemp));
            for (int i = 0; i < sizeof(szTemp)-1; i++)
            {
                    printf("[%c] ", szTemp[i]);
            }
            printf("[%d]", szTemp[sizeof(szTemp)-1]);
            printf("\n");
            getchar();
    }
    

    代码解释:

    字符串“Hello World!” 长度为12, 而szTemp数组大小是13,正好可以盛放字符串“Hello World!”并预留了’\0’的位置; 第6行,memset把数组szTemp全部元素置为1,是为了验证,拷贝完成后,是不是真的会补’\0’。第8-12行打印szTemp所有元素的值。预期输出结果应该是szTemp最后一个元素是‘\0’,也就是0。

    输出结果:
    在这里插入图片描述
    可以看到最一个元素是0,和预期相符。说明在不会发生截断时,strncp会在字符串末尾补’\0’。


    1.2 dst大小远大于src长度时(未截断)

    char * strncpy ( char * dest, const char * src, size_t num )
    

    因为1.1章节知道了,在不发生截断时strncpy会字符串末尾补’\0’,更进一步我想知道的是,当dst大小远大于src长度时,除了补’\0’, 其他元素会不会操作呢。
    实验代码:

    #include <stdio.h>
    #include <memory.h>
    int main()
    {
            char szTemp[20];
            memset(szTemp, 1, sizeof(szTemp));
            strncpy(szTemp, "Hello World!", sizeof(szTemp));
            for (int i = 0; i < strlen("Hello World!"); i++)
            {
                    printf("[%c] ", szTemp[i]);
            }
           int len = strlen("Hello World!");
           for (int i = 0; i < sizeof(szTemp) - strlen("Hello World!"); i++)
            {
                    printf("[%c] ", szTemp[i+len]);
            }
            printf("\n");
            getchar();
    }
    
    

    代码解释:

    目标数组szTemp长度是20,比字符串“Hello World!”长度要大的多。第7行strncp中num参数传的是sizeof(szTemp),也就是szTemp的大小,就是要看看除了补’\0’,还会做什么。第8-16行是打印szTemp的元素,字符串部分采用%c字符形式,其他部分采用%d整型,因为其他部分可能不是字符。

    结果输出:
    在这里插入图片描述
    啧啧啧,不看不知道,一看吓一跳,这已经不是补’\0’,而是所后面元素全置成0了。示意如下:
    在这里插入图片描述

    1.3 dst大小小于src长度(截断)

    char * strncpy ( char * dest, const char * src, size_t num )
    

    有了1.2章节的实验结果, 这次不再实验临界状态,直接让dst大小小于src长度,来看看补\0的情况。
    代码示例:

    #include <stdio.h>
    #include <memory.h>
    int main()
    {
            char szTemp[11];
            memset(szTemp, 1, sizeof(szTemp));
            strncpy(szTemp, "Hello World!", sizeof(szTemp));
            for (int i = 0; i < sizeof(szTemp)-1; i++)
            {
                    printf("[%c] ", szTemp[i]);
            }
            printf("[%d]", szTemp[sizeof(szTemp)-1]);
            printf("\n");
            getchar();
    }
    

    代码解释:

    szTemp大小是11,小于字符串“Hello World!”长度12。如果strncpy在截断时补’\0’的话,则最后一个元素会是0。

    输出结果:
    在这里插入图片描述
    从结果上看,最后一个元素不是0是100, 而100是d的ascii码值。所以,当截断发生时,strncpy直接把src里的前num个元素拷贝到目标数组dst里。
    这真是不幸的消息, strncpy确实不靠谱!

    1.4 num大小等dst大小减1(截断)

    char * strncpy ( char * dest, const char * src, size_t num )
    

    书接1.3, 截断时strncpy不会补0,但如果拷贝的时候给数组dst的长度预留一个元素呢,会不会strycpy就可以补0呢,下面实验一下:
    代码示例:

    #include <stdio.h>
    #include <memory.h>
    int main()
    {
            char szTemp[11];
            memset(szTemp, 1, sizeof(szTemp));
            strncpy(szTemp, "Hello World!", sizeof(szTemp)-1);
            for (int i = 0; i < sizeof(szTemp)-1; i++)
            {
                    printf("[%c] ", szTemp[i]);
            }
            printf("[%d]", szTemp[sizeof(szTemp)-1]);
            printf("\n");
            getchar();
    }
    

    代码解释:

    本次实验和1.3只有第7行不同,num=sizeof(szTemp)-1, 期望是留出一个位置自动补’\0’。

    输出结果:
    在这里插入图片描述
    从结果上看,没有补’\0’,与预期不一样。通过1.3、1.4的实验可以得出,strncpy在截断的时候不会自动在字符串末尾补'\0'

    1.5 结论

    通过以上4个实验,可以证明以下两点:

    1. strncpy在不发生截断时,将除待拷贝字符串部分全部置为0
    2. 当发生截断时,strncpy不会自动补'\0', 只是复制待拷贝字符串src的前num个元素

    本来是觉得不靠谱,那现在是真不靠谱了,还得用本文最开始的宏定义,不过得改进一下:

    原始版:

    #define my_strncpy(dst, src) strncpy(dst, src, sizeof(dst)-1 >= strlen(src) ? strlen(src) : sizeof(dst)-1)
    

    改进版:

    #define my_strncpy(dst, src, dst_size) strncpy(dst, src, dst_size); \
    			if (dst_size <= strlen(src)) dst[dst_size-1] = '\0'
    

    改进版代码解释:

    首先是dst_size是目标数组dst的大小, 第2行当dst长度小于等于字符串长度时, 手动在目标数组最后一位设置为’\0’。这个宏定义比原始版的多了补’\0’ 的操作,可以放心使用了~
    另外,既然strncp如此难用,作为C++开发者完全可以自己实现一个,当然也可以找其他替换函数,这里不再过多介绍。

    总结

    本文通过几个实验介绍了strncpy截断处理不会补\0的缺陷,给出了一个简单的改进代码;如果觉得有帮助,内容还可以,可以给博主点个关注。另外,如果文中有错误不当之处,希望不吝指正,大家一起共同进步。

    展开全文
  • strncpy 用法注意

    2022-06-17 11:13:22
    strncpy 用法和注意

    函数声明 (cplusplus)

    char * strncpy ( char * destination, const char * source, size_t num );
    /*
    Parameters:
    destination
    Pointer to the destination array where the content is to be copied.
    
    source
    C string to be copied.
    
    num
    Maximum number of characters to be copied from source.
    size_t is an unsigned integral type.
    
    Return Value:
    destination is returned.
    */
    

    Copy characters from string.
    Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.

    No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).

    destination and source shall not overlap (see memmove for a safer alternative when overlapping).

    从字符串复制字符.

    source的前num个字符复制到destination。如果在复制num个字符之前,就到了source 字符串的结尾(由空字符NULL表示),则会用零填充目标,直到总共写入num个字符为止。

    如果source长度大于num,则不会在destination的末尾隐式附加null字符。因此,在这种情况下,destination不应被视为以null结尾的C字符串(这样读取会溢出)。

    destinationsource不得重叠(重叠时,请参阅memmove以获得更安全的替代方案)。

    函数声明 (MSDN)

    char *strncpy(
       char *strDest,
       const char *strSource,
       size_t count
    );
    /*
    Parameters:
    strDest
    Destination string.
    
    strSource
    Source string.
    
    count
    Number of characters to be copied.
    
    Return Value:
    Returns strDest. No return value is reserved to indicate an error.
    */
    

    Remarks

    The strncpy function copies the initial count characters of strSource to strDest and returns strDest. If count is less than or equal to the length of strSource, a null character is not appended automatically to the copied string. If count is greater than the length of strSource, the destination string is padded with null characters up to length count. The behavior of strncpy is undefined if the source and destination strings overlap.

    strncpy函数将strSource的初始 count 个字符复制到strDest并返回strDest。如果count小于或等于strSource的长度,则不会在复制的字符串中自动追加空字符。如果count大于strSource的长度,则目标字符串将填充空字符直至长度为count。如果源字符串和目标字符串重叠,则strncpy的行为未定义。

    Important

    strncpy does not check for sufficient space in strDest; this makes it a potential cause of buffer overruns. The count argument limits the number of characters copied; it is not a limit on the size of strDest. See the following example. For more information, see Avoiding Buffer Overruns.

    strncpy未检查strDest中是否有足够的空间;这可能导致缓冲区溢出。count参数只是限制复制的字符数,而不是对strDest缓冲区大小的限制,所以此接口并没有对strDest缓冲区加以保护,需要用户在使用时选择合适的count值以此来避免strDest溢出。请参见以下示例。有关更多信息,请参阅避免缓冲区溢出。

    // 当我们不确认 strSource 长度时,可以将 count 定为 strDest 的缓冲区大小-1
    // 这样可以避免 strDest 的缓冲区溢出,并且任何时候 strDest 的结尾处都有 NULL
    void test(char* strSource)
    {
    	char strDest[16] = {0};
    	strncpy(strDest, strSource, 15);
    }
    
    

    Example

    // 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]; // This two arrays are adjacent(这两个数组在存储中的位置是相邻的,前面是t的20字节,紧接着是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  t溢出,并破坏了 s
       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.
    }
    

    Output

    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')
    

    参考

    MSDN - strncpy
    cplusplus - strncpy

    展开全文
  • 目录1.strcpy/strncpy2.sprintf/snprintf3.strncpy/snprintf 下面的测试基于VS2019,测试过程中会报错并提示使用诸如strcpy_s建议,只需要屏蔽报错强制编译执行即可——在代码开头加上: #pragma warning(disable:...
  • strcpy与strncpy的区别

    2021-05-21 12:55:45
    我们看看更安全的strncpy函数吧,原型:char *strncpy(char *dest, char *src, size_t num); 上述有问题的程序应该改为: #include using namespace std; int main() { char str[4] = {0}; char *p = "abcdefg"; ...
  • 打包文件包含两个文件:c文件源代码、Makefile文件,运行环境在Ubuntu14.04下,使用自带的gcc编译器,同学们只需将文件夹复制到某一目录下之后在终端执行:1.“make”生成“test”可执行文件;2. 输入“./test”运行...
  • C++中strncpy函数和strncpy_s函数的使用及注意事项

    万次阅读 多人点赞 2018-09-17 17:49:24
    在掌握了strcpy函数和strcpy_s函数之后,我们不可避免地会谈到strncpy函数和strncpy_s函数,其实这四个函数的功能几乎一致,就是对两个字符串数组进行复制和赋值,但是具体实现有一点点区别。 首先来说一下strncpy...
  • 冰冰学习笔记:strncpy,strncat,strncmp

    多人点赞 热门讨论 2022-03-22 21:52:33
    长度受限制的字符串处理函数 模拟实现strncpy,strncat,strncmp
  • C语言实现strncpy

    千次阅读 2022-03-26 13:00:56
    1.strncpy介绍 strncpy --- 字符串拷贝 --- 拷贝num个字符 char* strncpy ( char* destination, const char* source, size_t num ) 拷贝num个字符从源字符串到目标空间; 如果源字符串长度小于num,则拷贝完源...
  • strcpy ,strncpy ,strlcpy的用法好多人已经知道利用strncpy替代strcpy来防止缓冲区越界。但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式。1. strcpy我们知道,strcpy 是依据 \0 作为结束判断的,如果 ...
  • 文章目录strcpy描述和声明参数要求实例strncpy描述和声明参数要求实例memcpy描述和声明参数要求实例memmove描述和声明strlen注意事项字符数组中间有结束符'\0'拷贝情况内存区域重叠拷贝strcpy和strncpy比较strncpy和...
  • 在C语言中会经常用到拷贝函数,本文记录下strcpy、strncpy、memset函数的使用。strcpy函数与strncpy函数 函数作用:将一个字符串拷贝到另外一个字符串。把src所指向的以null为结束的字符串拷贝到dest所指向的内存...
  • strncpy 的标准用法为:(手工写上 \0) strncpy(path, src, sizeof(path) - 1); path[sizeof(path) - 1] = '\0'; len = strlen(path); 这几个strcpy的变形,在指定大小的时候,都要留一个位置给\0,所以拷贝的大小...
  • strncpy 和 memcpy

    2021-05-27 11:21:52
    strncpy 和 memcpy Tags:学习笔记 strncpy 函数原型:extern char *strncpy(char *dest, char *src, int n) 参数说明:dest为目的字符串,src为源字符串,n。 所在库名:#include <string.h> 函数功能:将src...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 47,126
精华内容 18,850
关键字:

strncpy