首页 > 代码库 > 关于memset() 函数的使用

关于memset() 函数的使用

第一次接触了memset() 函数。 感觉的确是一个能够高效的实现对一个array 进行一次性初始化的fancy way。 下面给出介绍:

memset() 函数定义在头文件<<cstring>>中, prototype 如下:

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

函数的作用是: fill the first num bytes(注意不是element) of block of memory(由空指针ptr指向) with value. 最后我们会解释这句话的含义。

关于size_t 这个类型, 是定义在C标准库中的。 

援引百度百科介绍:

在C++中,设计 size_t 就是为了适应多个平台的 。size_t的引入增强了程序在不同平台上的可移植性。size_t是针对系统定制的一种数据类型,一般是整型(int),因为C/C++标准只定义一最低的位数,而不是必需的固定位数。而且在内存里,对数的高位对齐存储还是低位对齐存储各系统都不一样。为了提高代码的可移植性,就有必要定义这样的数据类型。一般这种类型都会定义到它具体占几位内存等。当然,有些是编译器或系统已经给定义好的。经测试发现,在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,这样利用该类型可以增强程序的可移植性。

 所以size_t 一般和int 所占用的存储空间是相同的:

#include <iostream>

using namespace std;

int main()
{
    cout << sizeof(size_t) << endl;
    cout << sizeof(int) << endl;
    return 0;
}

运行结果如下:


不难看出, 对于(我的电脑是32位的), int 和 size_t 的空间是相同的。

为了进一步加强对内存的概念, 我又做了如下转型的测试:

#include <iostream>

using namespace std;

int main()
{
    int i = 100;
    cout << sizeof(static_cast<char>(i));
    return 0;
}

运行结果如下:

可见使用转型的时候, 转型后的数据是存储在一个temp 的char 型的变量。 占用的内存当然为1 byte 了。

再看下例:

#include <iostream>

using namespace std;

int main()
{
    int i = 100;
    cout << sizeof(static_cast<char>(i)) << endl;
    cout << sizeof(i);
    return 0;
}




但是转型的时候, 可能会丢失信息。



下面使用memset() 函数。

官方文件中, 对memset() 函数的comment 如下:

.is a very efficient way to set all values of the_array to zero。

首先, 该函数返回初始化后的buffer。


可以通过下图查看memset() 函数去初始化数组与用for loop 对数组初始化这两种方法的所需要的时间的比较:



可见, 随着数组的大小越来越大, memset的效率优势愈发明显。

上述是对char 的形式初始化, 我们可以直接使用大小作为memset第三个参数。 因为char 型数组占用的空间大小(以byte 计数)就是size的值。

但是对于int型的数组, 由于一个int 型的值会占用4 bytes, 所以使用起来会不同。

详见下例:

 

#include <iostream>

using namespace std;

/* memset example */
#include <iostream>
#include <cstring>

int main ()
{
    int myArray[11];
    char str[] = "almost every programmer should know memset!";

    memset(str,'-',6);
    cout << str << endl;

    memset(myArray, 10, 11 * sizeof(int));
    for(int i = 0; i < 11; i++) {
       cout << myArray[i] << " ";
    }
    cout << endl;

    memset(myArray, 10, sizeof(myArray));
    for(int i = 0; i < 11; i++) {
       cout << myArray[i] << " ";
    }


    return 0;
}
运行结果如下:



问题来了: 对于上例子中, 对char 型数组的初始化, 输出符合预期。 但是对于整型数组却不符合预期, 为什么呢。 答案就是memset 是对于memory block  是一个字节一个字节的赋值。 由于int 型数组一个int元素就有4个bytes, 当然不符合预期了。 

相信改为0后就可以了, 另外改为-1 也可以:

#include <iostream>

using namespace std;

/* memset example */
#include <iostream>
#include <cstring>

int main ()
{
    int myArray[11];
    char str[] = "almost every programmer should know memset!";

    memset(str,'-',6);
    cout << str << endl;

    memset(myArray, 0, 11 * sizeof(int)); // 注意不能是<span style="font-family: Arial, Helvetica, sans-serif;">memset(myArray, 0, 11 ); 啊</span>

    for(int i = 0; i < 11; i++) {
       cout << myArray[i] << " ";
    }
    cout << endl;

    memset(myArray, -1, sizeof(myArray));
    for(int j = 0; j < 11; j++) {
       cout << myArray[j] << " ";
    }


    return 0;
}

运行结果如下:


所以memset() 函数不能让我们对数组初始化某一个特定的整数。 Anyway, 可以高效的初始化为0 或者-1 就okay咯。






关于memset() 函数的使用