memset函数如何正确初始化内存?

99ANYc3cd6
预计阅读时长 12 分钟
位置: 首页 C语言 正文

什么是 memset

memset 是 C 标准库 <string.h> (或 <memory.h>) 中的一个函数,它的作用是将一块内存区域中的每个字节都设置为指定的值

c语言 memset
(图片来源网络,侵删)

你可以把它想象成用一个“油漆桶”去涂刷一块内存区域,把整个区域都染成同一种颜色(同一个字节值)。

函数原型

#include <string.h> // 或 <memory.h>
void *memset(void *ptr, int value, size_t num);

参数详解

  1. void *ptr:

    • 这是一个指向要被操作的内存区域的起始地址的指针。
    • 它的类型是 void *,意味着它可以接受任何类型的指针(如 int *, char *, struct * 等)。
    • 这个内存区域必须是你拥有并且可以修改的,不能是只读的内存。
  2. int value:

    • 这是你要设置的
    • 特别注意:虽然参数类型是 int,但 memset 是按字节操作的,它会把这个 int 值的低 8 位(一个字节)复制到目标内存区域的每一个字节中。
    • 你只会使用 00xFF(即 -1)这样的值,因为其他值可能会导致非预期的结果(用 1 去初始化一个 int,得到的结果不是 1,而是 0x01010101)。
  3. size_t num:

    c语言 memset
    (图片来源网络,侵删)
    • 这是你要设置的字节数。
    • size_t 是一个无符号整数类型,足以表示系统中可能的最大内存块大小。

返回值

  • 函数返回一个 void * 类型的指针,这个指针就是传入的第一个参数 ptr 的值。
  • 这个返回值主要是为了方便进行函数链式调用,但在实际使用中,我们通常会忽略它,直接使用我们传入的指针。

使用示例

示例 1:最常见的用法 - 数组清零

这是 memset 最经典和最安全的用途,将一块内存全部设置为 0

#include <stdio.h>
#include <string.h>
int main() {
    int arr[10];
    int i;
    // 打印初始化前的随机值
    printf("Before memset:\n");
    for (i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n\n");
    // 将 arr 数组的前 10 * sizeof(int) 个字节全部设置为 0
    // 因为 arr 是一个包含 10 个 int 的数组,所以总字节数是 10 * 4 = 40
    memset(arr, 0, sizeof(arr));
    // 打印清零后的值
    printf("After memset (with 0):\n");
    for (i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

输出:

Before memset:
4202528 0 4202528 0 4202528 0 4202528 0 4202528 0 
After memset (with 0):
0 0 0 0 0 0 0 0 0 0 

示例 2:将内存设置为 -1

将内存的每个字节都设置为 0xFF(即 11111111),对于有符号整数类型(如 int, char),这通常表示 -1

#include <stdio.h>
#include <string.h>
int main() {
    int arr[5];
    int i;
    // 将数组所有字节设置为 0xFF
    memset(arr, 0xFF, sizeof(arr));
    printf("Array after memset with 0xFF (-1):\n");
    for (i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

输出:

c语言 memset
(图片来源网络,侵删)
Array after memset with 0xFF (-1):
-1 -1 -1 -1 -1 

示例 3:一个常见的错误用法

初学者常常会犯一个错误:试图用 memset 来将一个数组设置为非 0 或非 -1 的特定值。

#include <stdio.h>
#include <string.h>
int main() {
    int arr[5];
    int i;
    // 错误!不要这样做!
    // 这会把 arr 的每个字节都设置为 1
    // 对于 4 字节的 int,每个元素会变成 0x01010101,即 16843009
    memset(arr, 1, sizeof(arr));
    printf("Array after incorrect memset with 1:\n");
    for (i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

输出:

Array after incorrect memset with 1:
16843009 16843009 16843009 16843009 16843009 

这显然不是我们想要的 1, 2, 3, 4, 5,如果要将数组初始化为特定值,应该使用循环。


memset vs. memcpy vs. memmove

这是一个非常容易混淆的点,这里做一个简单的对比:

函数 功能 参数
memset 设置内存区域为同一个值 ptr, value, num
memcpy 复制一块内存到另一块内存。 dest, src, num
memmove 移动一块内存到另一块内存,源和目标区域可以重叠 dest, src, num

关键区别:

  • memset 用于初始化清空
  • memcpy 用于复制,当源和目标内存不重叠时使用,效率更高。
  • memmove 用于移动,当源和目标内存可能重叠时使用,更安全。

  • 功能memset 是一个快速、底层的内存设置工具。
  • 用途:最常用于将内存块清零 (memset(ptr, 0, size))。
  • 核心:它是按字节操作的,不是按元素。
  • 警告不要用它来设置非 0 或非 -1 的特定值给多字节数据类型(如 int, float, struct)。
  • 头文件:使用时必须包含 <string.h>

memset 是 C 语言程序员工具箱中一个基础且强大的工具,理解它的正确用法和局限性非常重要。

-- 展开阅读全文 --
头像
如何用C语言实现findpic功能?
« 上一篇 04-19
dede如何调用文章路径?
下一篇 » 04-19

相关文章

取消
微信二维码
支付宝二维码

目录[+]