c语言 strcpy strncpy,使用C语言的strcpy,strncpy,memset函数

c语言 strcpy strncpy,使用C语言的strcpy,strncpy,memset函数_第1张图片

复制功能通常以C语言使用. 本文记录了strcpy,strncpy和memset函数的使用.

c语言 strcpy strncpy,使用C语言的strcpy,strncpy,memset函数_第2张图片

功能: 将一个字符串复制到另一个. 将src指向的以null终止的字符串复制到dest指向的内存空间. dest是char *,而src是const char *. 注意,src指向的存储空间只能在函数中读取,不能修改. 该函数的返回值是char *类型,它返回修改后的字符串的地址.

注意: strcpy函数将src指向的字符串(包括终止符(\ 0))复制到dest指向的区域. 因此,可以确保目标以“ \ 0”结尾. strcpy只知道src字符串的第一个地址,它将始终复制到'\ 0'位置. dest指向的区域必须足够大才能完成复制.

strncpy函数类似于,但它将n个字节复制到dest区域. 如果src的长度小于n,则目标区域将填充空白字符.

使用strcpy时需要注意两点: 1)src字符串以'\ 0'结尾2)dest区域足够大,可以复制所有dest,否则将导致缓冲区溢出.

错误示例:

//

// main.cpp

// strcpyExample

//

// Created by mini on 12/24/13.

// Copyright (c) 2013 mini. All rights reserved.

//

#include

#include

using namespace std;

int main(int argc, const char * argv[])

{

char buf1[10];

char buf2[10];

//char *s = "hello world";

strcpy( buf1, "hello world" );

strcpy( buf2, "holly shit!");

cout << &buf1 << endl;

cout << &buf2 << endl;

cout << buf1 << endl;

cout << buf2 << endl;

}

输出:

0x7fff5fbffa5e

0x7fff5fbffa54

!

holly shit!

Program ended with exit code: 0

分析: 函数堆栈向下增长. 从内存的高地址->低地址增长. 即,堆栈顶部的地址低于堆栈底部的地址. 因此,buf1的地址为高(堆栈的底部),而buf2的地址为低(堆栈的顶部). 分配的两个字符数组均为10,并且要复制的内容将超出边界. 复制两个字符串的内容后,如下所示:

c语言 strcpy strncpy,使用C语言的strcpy,strncpy,memset函数_第3张图片

c语言 strcpy strncpy,使用C语言的strcpy,strncpy,memset函数_第4张图片

因此,使用strcpy时请注意跨境问题. 该函数的实现者无法知道src字符串的长度和目标存储空间的大小. 因此,“确保您不会超出范围”是函数调用者的责任. 调用者提供的dest参数应指向足够大的存储空间. 调用者还有责任“确保不会超出范围”. 调用者提供的src参数所指向的内存必须确保'\ 0'结束.

那时候写出边界可能没有错,但是函数返回时会发生错误,因为写出边界会覆盖存储在堆栈帧中的返回地址,并且当出现以下情况时,该函数会跳转到非法地址该函数返回,因此发生错误. 这称为分段错误. 如果不仅仅是分割错误,那就更严重了. 缓冲区溢出错误通常由恶意用户使用. 函数返回到预先设计的地址,然后执行设计的指令. 如果设计巧妙,则可以启动shell并根据需要执行命令. 如果在具有root特权的可执行程序中存在此类错误,后果将非常严重. 该技术目前也是非常流行的饼干.

技术.

此外: src和dest指向的存储空间不能重叠. 通常,带有指针参数的C标准库函数基本上有此要求,并且每个指针参数指向的内存空间不能相互重叠.

strncpy参数n指定最多将n个字节从src复制到dest,即,如果将其复制到'\ 0',则结束. 如果复制n个字节没有遇到'\ 0',则结束相同. 调用者负责提供适当的n值,例如使n的值等于dest指向的存储空间的大小,例如:

char buf1[10] = "abcdefghi";

strncpy( buf1, "hello world", sizeof( buf1 ) );

此代码可以完全填充buf1的空间,但这不能保证dest以'\ 0'结尾. 因此,读取时发生越界错误. 调用方必须确保dest以'\ 0'结尾. 您可以手动添加这样的句子.

char buf1[10] = "abcdefghi";

strncpy( buf1, "hello world", sizeof( buf1 ) );

buf1[ sizeof(buf1) - 1 ] = '\0';

strncpy也有一个功能. 如果在所有副本完成后src字符串不如n个字节那么好,则缺少多少个字节将完成'\ 0'.

strcpy和strncpy的返回值:

这两个函数都返回一个dest指针,并且dest最初是作为调用者传递的,那么为什么要返回它呢?这样做是为了使函数调用可以用作指针类型的表达式. 例如,printf(“%s \ n”,strcpy(buf,“ hello”)),如果strcpy返回void,则不能直接使用它.

strcpy和strncpy摘要:

使用strcpy时,最好确保您不会写越界或读越界. 当strncpy时strncpy函数,您可以手动添加结束符号. 例如:

strncpy(buf,str,n);

if( n > 0)

buf[n - 1] = '\0';

功能原型:

void * memset ( void * ptr, int value, size_t num );

功能:

memset函数用值填充ptr指向的内存地址的前num个字节. 通常用于清除内存区域. 例如,您将一个int数组定义为一个[10]. 如果a是全局数组或静态变量,则会自动生成为0. 如果它是局部变量,则可以使用memset(a,0,10)清除为0,适合在循环函数中进行初始化或更新.

示例:

int a[10];

for( int s: a )

cout << s << " ";

memset( a, 0, sizeof( a ) );

cout << endl;

for( int s: a )

cout << s << " ";

cout << endl;

输出:

0 1 1606417120 32767 0 1 0 0 1606417136 32767

0 0 0 0 0 0 0 0 0 0

memset可以轻松清除结构类型变量或数组.

示例:

如果我们定义一个结构数组:

struct student {

char name[20];

int age;

int number;

};

通常,有一个结构变量Student. 如何清除s的值?您可以使用以下方法:

s.name[0] = '\0';

s.age = 0;

s.number = 0;

此方法实际上效率低下,需要大量代码. 我们可以使用memset来执行:

struct student s ;

strcpy( s.name, "hehe" );

s.age = 10;

s.number = 10;

cout << s.name << " " << s.age << " " << s.number << endl;

memset( &s, 0, sizeof( s ) );

cout << s.name << " " << s.age << " " << s.number << endl;

输出:

hehe 10 10

0 0

c语言 strcpy strncpy,使用C语言的strcpy,strncpy,memset函数_第5张图片

如果它是结构数组,则可以这样使用它:

student s[10];

memset( s, 0, sizeof( student ) * 10 );

功能原型:

void *memcpy(void *dest, const void *src, size_t n); void *memmove(void *dest, const void *src, size_t n);

功能:

memcpy函数将src指向的内存地址中的n个字节复制到dest指向的内存地址中.

memmove还将n个字节从src指向的内存地址复制到dest指向的内存地址. 尽管它称为移动,但实际上是副本. 它与memcpy有一点不同. 如果memcpy的两个参数src和dest指向的存储区重叠,则不能保证正确的复制,但是memmove可以正确复制. 如果定义数组char data [20] =“ hello world \ n”strncpy函数,则要将字符串后移一个字节到“ hhello

world \ n“,您可以使用memmove(buf + 1,buf,13)实现此功能,但是memcpy(buf + 1,buf,13)无法完成复制:

这两个函数以及strcpy和strncpy之间的区别:

strcpy函数遇到“ \ 0”时结束. memcpy遇到“ \ 0”时不会结束. 相反,它将肯定复制n个字节. 复制函数的命名规则是,以str开头的函数将输出以'\ 0'结尾的字符串,而以mem开头的函数不关心字符串'\ 0'. 以mem开头的函数不会将参数视为字符串,因此参数的指针类型为void *而不是char *

错误示例:

int main(int argc, const char * argv[])

{

char data[20] = "Dont give up!";

memcpy( data + 1, data, 13 );

char data2[20] = "Dont give up!";

memmove( data2 + 1, data2, 13 );

cout << data << endl;

cout << data2 << endl;

}

输出:

DDont givv upp

DDont give up!

第一个函数将出现乱码,第二个函数将正常执行. 这是两者之间的区别.

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/tongxinshuyu/article-145494-1.html

你可能感兴趣的:(c语言,strcpy,strncpy)