![]() |
成熟的柳树 · 威廉·莫里斯-抖音百科· 7 月前 · |
![]() |
豪气的香瓜 · 凤还朝,妖孽王爷请让道漫画全集免费(下拉式) ...· 1 年前 · |
![]() |
豁达的黄豆 · 万达8条内容驳自媒体造谣:现金超2000亿 ...· 1 年前 · |
![]() |
活泼的风衣 · 【智己汽车2023款智己L7 Snake ...· 1 年前 · |
c语言 memcpy strcpy memcpy函数 |
https://cloud.tencent.com/developer/article/2242919?from=15425&areaSource=102001.2&traceId=cMyomc2w8wYlvI6E768eg |
![]() |
坚强的木耳
1 年前 |
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5];
arr2 = arr1; // 错误,不能直接赋值
使用循环遍历数组中的每一个元素
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5];
for (int i = 0; i < 5; i++) {
arr2[i] = arr1[i];
使用std::array时,可以使用赋值运算符来复制:
std::array<int, 5> arr1 = {1, 2, 3, 4, 5};
std::array<int, 5> arr2;
arr2 = arr1;
使用C语言库函数解决
strcpy()函数用于复制一个字符串到另一个字符串。该函数的语法如下:
char *strcpy(char *dest, const char *src);
它从源字符串src复制字符到目标字符串dest,包括NULL字符(即字符串结束标志)。
strncpy()函数与strcpy()类似,但是其复制的字符数可以限制。该函数的语法如下:
char *strncpy(char *dest, const char *src, size_t n);
它从源字符串src复制字符到目标字符串dest,但是最多复制n个字符。
举个例子:
#include <iostream>
#include <cstring>
int main()
char source[] = "Hello, World!";
char destination[50];
// using strcpy
strcpy(destination, source);
std::cout << "After using strcpy: " << destination << std::endl;
// using strncpy
strncpy(destination, source, 5);
destination[5] = '\0';
std::cout << "After using strncpy: " << destination << std::endl;
return 0;
}
输出:
After using strcpy: Hello, World!
After using strncpy: Hello
PS:详见C Primer Plus P351
memcpy() 和 memmove() 是 string.h 库中的两个常用的内存复制函数。这两个函数可以用来处理任意类型的数组,并复制从源数组到目标数组。
memcpy() 函数把一块内存复制到另一块内存, 但是不会去处理内存是否重叠 。它可以被用来处理整个数组或仅仅一部分。它的语法如下:
void *memcpy(void *dest, const void *src, size_t n);
memmove() 函数的作用与 memcpy() 类似, 可以处理内存重叠的情况 。它的语法如下:
void *memmove(void *dest, const void *src, size_t n);
如果你想复制一个整数数组,例如:
int source[5] = {1, 2, 3, 4, 5};
int target[5];
memcpy(target, source, sizeof(source));
这两个函数是 C 语言中非常有用的内存复制函数,可以用来处理任意类型的数组,也可以用来处理字符数组。
PS:详见C Primer Plus P558
c和c++使用的内存拷贝函数,memcpy函数和memmove函数的功能都是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
要使用这两个库函数需要引用头文件 <string.h> 函数原型: void* memcpy(void* destination,const void* source,size_t num); voidmemmove(void destination,const void* source,size_t num); destination:目的地指针(首地址) source:源头指针(首地址) num:需要复制的字节数
memcpy和memmove都是C语言标准库函数,用于内存拷贝。两者的主要区别在于:
因为memcpy的运行速度比memmove快,所以memcpy常常被用于内存拷贝。在程序员能确保源区域和目标区域没有重叠或者能够接受重叠部分数据被覆盖的情况下memcpy是很好的选择。但是在不能确定源区域和目标区域是否重叠或者不能接受重叠部分数据被覆盖的情况下,应该使用memmove以保证数据完整性。
举个例子,假设我们有一个字符数组char arr[10],我们想把arr[2]
arr[5]这4个字符移动到arr[6]
arr[9]这4个位置上。 如果使用memcpy(arr+6, arr+2, 4),结果就会是这样的:
原数组: | A | B | C | D | E | F | G | H | I | J |
拷贝后: | A | B | C | D | E | C | D | E | C | J |
可以发现,原本arr[6]~arr[9]的数据被覆盖了。 如果使用memmove(arr+6, arr+2, 4),结果就会是这样的:
原数组: | A | B | C | D | E | F | G | H | I | J |
拷贝后: | A | B | C | D | E | C | D | E | F | J |
可以发现,原本arr[6]~arr[9]的数据没有被覆盖,源区域的数据也没有丢失。 在这个例子中,memmove 保证了数据完整性,而memcpy没有。 简而言之,memcpy是一个快速的内存拷贝函数,memmove是一个安全的内存拷贝函数,当你不能确保源区域和目标区域是否重叠或者不能接受重叠部分数据被覆盖的情况下,应该使用memmove来保证数据完整性。
借一下图: https://blog.csdn.net/m0_66363962/article/details/126903690
通过上图的变化路程可知: memcpy总是从低地址开始往高地址复制的 ,但是当dest>src,并且目的地与源头有重叠时,使用memcpy会覆盖掉源头后面的数据,导致结果出错。这个时候就需要进行判断,如果再次出现上面的事件, 我们应当从高地址往低地址开始复制 , 但是memcpy函数在设计时没有这种判断。 所以使用memmove函数解决。
memcpy从高地址往低地址复制不会受内存重叠时的问题的影响。 从低地址往高地址复制时需要使用memmove函数。
1.在 C 语言中,使用 memcpy 函数进行内存复制通常比使用循环赋值更快。这是因为 memcpy 是一个底层的函数,它可以直接操作内存 ,而不需要进行额外的运算。它使用缓存和高级的内存管理技术来提高性能。
2.另外, memcpy 函数 可以 并行执行 ,因此多核处理器上能够更高效地运行,而 循环赋值 是 串行执行 的,所以性能更差。
下面是一个使用 memcpy 函数进行内存复制的示例代码:
#include <string.h>
int main() {
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5];
memcpy(arr2, arr1, sizeof(arr1));
// arr2 is now {1, 2, 3, 4, 5}
return 0;
请注意,当源和目标内存块有重叠时,memcpy 函数可能会出现不确定的行为,因此在这种情况下应该使用 memmove 函数代替。
PS:并行执行是指多个任务在同时进行,也就是多个任务同时执行。串行执行是指一个任务执行完成后再执行下一个任务,也就是一个任务一个任务地执行。
memcpy 函数通常是通过硬件加速来实现并行执行的。例如,许多现代处理器都具有内置的存储器控制器,可以并行地从一个地址拷贝数据到另一个地址。这些控制器可以利用多个通道和多个缓存来并行执行数据拷贝操作,从而大大提高了数据拷贝的速度。
memcpy 本身不支持多核并行 ,它是由系统底层实现的,通常使用的是硬件级的指令来提高复制效率。
关于memcpy并行,通常指的是在单核内部使用SIMD(单指令多数据)指令来并行执行复制操作。SIMD指令可以在一个时钟周期内处理多个数据。例如,128位的AVX指令可以同时处理8个32位整数或4个64位整数。这样可以减少数据处理时间,提高复制效率。
所以memcpy并行指的是在单核内部使用SIMD指令来并行执行复制操作。
memcpy 函数 也可以 使用多线程和多核处理器来实现并行执行。 例如,如果将数据分成若干块,每个线程分别处理一块数据,这样就可以并行执行数据拷贝操作。
如果要在多核并行的情况下使用memcpy,可以使用多线程或多进程的方式,将大块数据分割成多个小块,分别在不同的核上进行复制。这样可以利用多核的计算能力来提高复制效率。
具体实现的方式可以使用pthread库或OpenMP来实现多线程,或者使用MPI来实现多进程。其中使用OpenMP是目前并行计算中比较流行的方式。
但是这种方式需要更多的编程工作量和空间复杂度,而且对于小块数据来说反而会增加开销,所以通常在复制大块数据的场景下使用。
总之,memcpy函数实现并行执行的方式有很多,具体实现取决于具体环境。
线程可以设置亲和度,这样可以指定它运行在哪个 CPU 核上。这样做的目的是为了提高性能,因为在同一个 CPU 核上运行的线程可以共享缓存和其他硬件资源,而在不同核上运行则不能。不过,这需要程序员手动设置,并且需要操作系统的支持。
在不同的操作系统和编程语言中,设置线程亲和度的方式可能有所不同。下面给出一些常见的例子:
在设置亲和度之前,需要先确定系统中可用的 CPU 核数量,并将线程亲和度设置为对应的核的标识。一般来说,亲和度是一个位图,每个位对应一个 CPU 核。
需要注意的是, 设置线程亲和度可能会导致系统性能变差,因为这需要额外的上下文切换.
PS:上下文切换是指 CPU 从一个线程切换到另一个线程时所需要进行的操作。在切换过程中,需要保存当前线程的环境(如寄存器的值),并将新线程的环境加载到 CPU 中。这个过程会消耗一定的时间,如果频繁发生,会导致系统性能下降。
在设置线程亲和度时,如果线程频繁地在不同的 CPU 核之间切换,就会导致上下文切换频繁发生,从而导致系统性能变差。因此,在设置线程亲和度时,需要谨慎考虑,确保它对系统性能的影响是最小的。
![]() |
成熟的柳树 · 威廉·莫里斯-抖音百科 7 月前 |