C语言内存函数

在 C 语言的编程世界里,内存管理至关重要,而内存函数则是开发者操控内存的得力工具。今天,我们就一同深入探索 C 语言中几个常用内存函数的奥秘,包括memcpymemmovememsetmemcmp

1.memcpy:内存数据复制大师

memcpy函数用于从源内存地址source开始,向后复制指定字节数num的数据到目标内存地址destination。其函数原型为:void *memcpy(void *destination, const void *source, size_t num);。需要注意的是,memcpy在复制过程中遇到'\0'不会停止,而且当源和目标内存有重叠时,复制结果是未定义的。

来看一个简单示例:

cpp 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    int arr1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int arr2[10] = {0};
    memcpy(arr2, arr1, 20);

    int i = 0;
    for (i = 0; i < 10; i++) {
        printf("%d ", arr2[i]);
    }
    return 0;
}

上述代码将arr1的前 20 个字节(也就是前 5 个int型元素)复制到arr2中。

下面是memcpy的模拟实现:

cpp 复制代码
void *memcpy(void *dst, const void *src, size_t count) {
    void *ret = dst;
    // 断言确保目标和源指针有效
    assert(dst);
    assert(src);

    while (count--) {
        // 逐字节复制
        *(char *)dst = *(char *)src;
        dst = (char *)dst + 1;
        src = (char *)src + 1;
    }
    return ret;
}

在这个模拟实现中,通过assert检查指针有效性,然后利用while循环逐字节复制数据,保证内存数据的准确传输。

2.memmove:处理重叠内存的高手

memmove函数的功能与memcpy相似,原型为void *memmove(void *destination, const void *source, size_t num);,但它的优势在于能够处理源内存块和目标内存块重叠的情况。

比如下面这个例子:

cpp 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    int arr1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    memmove(arr1 + 2, arr1, 20);

    int i = 0;
    for (i = 0; i < 10; i++) {
        printf("%d ", arr1[i]);
    }
    return 0;
}

这段代码将arr1的前 20 个字节复制到从arr1 + 2开始的位置,由于存在内存重叠,memmove能够正确处理。

memmove的模拟实现稍微复杂一些:

cpp 复制代码
void *memmove(void *dst, const void *src, size_t count) {
    void *ret = dst;
    if (dst <= src || (char *)dst >= ((char *)src + count)) {
        // 非重叠情况,从低地址向高地址复制
        while (count--) {
            *(char *)dst = *(char *)src;
            dst = (char *)dst + 1;
            src = (char *)src + 1;
        }
    } else {
        // 重叠情况,从高地址向低地址复制
        dst = (char *)dst + count - 1;
        src = (char *)src + count - 1;
        while (count--) {
            *(char *)dst = *(char *)src;
            dst = (char *)dst - 1;
            src = (char *)src - 1;
        }
    }
    return ret;
}

这里通过判断目标和源地址的关系,分别处理非重叠和重叠两种情况,确保在各种场景下都能准确复制数据。

3.memset:内存数据设置专家

memset函数用于将内存区域ptr的前num个字节设置为指定值value,函数原型为void *memset(void *ptr, int value, size_t num);

例如:

cpp 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "hello world";
    memset(str, 'x', 6);
    printf(str);
    return 0;
}

运行这段代码,会将str的前 6 个字符替换为'x',输出xxxxxxworldmemset在初始化内存、清空缓冲区等场景中经常使用。

4.memcmp:内存数据比较利器

memcmp函数用于比较从ptr1ptr2指针指向的位置开始的num个字节,函数原型为int memcmp(const void *ptr1, const void *ptr2, size_t num);。它的返回值用于指示两个内存块内容的关系:

  • 返回值小于 0,表示ptr1中第一个不匹配的字节小于ptr2中的对应字节(按无符号字符值比较);
  • 返回值等于 0,表示两个内存块内容相等;
  • 返回值大于 0,表示ptr1中第一个不匹配的字节大于ptr2中的对应字节(按无符号字符值比较)。

示例代码如下:

cpp 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    char buffer1[] = "DWgaOtP12df0";
    char buffer2[] = "DWGAOTP12DF0";
    int n;
    n = memcmp(buffer1, buffer2, sizeof(buffer1));

    if (n > 0)
        printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
    else if (n < 0)
        printf("'%s' is less than '%s'.\n", buffer1, buffer2);
    else
        printf("'%s' is the same as '%s'.\n", buffer1, buffer2);

    return 0;
}

这段代码比较buffer1buffer2的内容,并根据比较结果输出相应信息。

通过对memcpymemmovememsetmemcmp这几个内存函数的学习,我们掌握了在 C 语言中高效处理内存数据的方法。它们在数据处理、内存初始化、数据比较等诸多场景中发挥着重要作用,是 C 语言开发者不可或缺的编程工具。希望大家在今后的编程实践中,能够灵活运用这些函数,编写出更加健壮、高效的代码。

相关推荐
Ar-Sr-Na37 分钟前
STM32现代化AI开发指南-VSCode环境配置(macOS)
c语言·人工智能·vscode·stm32·嵌入式硬件·硬件工程
2301_789015622 小时前
C++:智能指针
c语言·开发语言·汇编·c++·智能指针
weixin_446023563 小时前
C语言开发Win32程序太麻烦?微软不支持有3个原因
c语言·微软·mfc·win32程序·开发难度
程序员zgh3 小时前
C/C++ 单元测试系统 构建
c语言·开发语言·c++·学习·单元测试
孬甭_3 小时前
揭开指针的面纱(中)
c语言
草莓熊Lotso3 小时前
【Linux系统加餐】 mmap 文件映射全解:从底层原理、API 到实战开发(含 malloc 模拟实现)
android·linux·运维·服务器·c语言·c++
深邃-3 小时前
【C语言】-数据在内存中的存储(2):浮点数在内存中的存储
c语言·开发语言·数据结构·c++·算法·html5
智者知已应修善业3 小时前
【51单片机利用外部中断编写程序用两个按键控制数码管显示从0到9,S1控制加计数0—9,S2控制减计数9—0。】
c语言·经验分享·笔记·算法·51单片机
cch89183 小时前
Java vs C语言:编程语言终极对决
java·c语言·开发语言
智者知已应修善业3 小时前
【51单片机实现0-7和8-1循环显示共阴数码管】2023-5-12
c语言·经验分享·笔记·算法·51单片机