在C++中使用memset作为结构体数组

问题描述 投票:0回答:3

嗯,我想要一个像

memset
但对于
struct
的函数,这样它就可以在某些或所有元素上使用,如下所示:

// create array of person data elements
struct {
  unsigned char name[25];
  unsigned char age;
  unsigned int numberPhone;
} persons [256];

// the 256 people have the same name
memset(person, { "Mohammed", 0, 0 } ,sizeof(persons) / sizeof(persons[0]));

我可以使用

for loop
,但我更喜欢使用
memset
,因为在这种情况下它比
for loop
性能更高。

c++ arrays memory struct memset
3个回答
4
投票

您不能为此使用

std::memset
std::memset
将内存区域中的所有 bytes 设置为相同的值:

void* memset( void* dest, int ch, std::size_t count );

将值

static_cast<unsigned char>(ch)
复制到
dest
指向的对象的每个前计数字符中。

如果所有 256 个对象都应使用相同的值进行初始化,只需默认它们即可:

struct {
    unsigned char name[25] = "Mohammed";
    unsigned char age = 0;
    unsigned int numberPhone = 0;
} persons [256];

不需要更多。

如果您想要默认值,请创建一个实例,然后

std::fill
数组:

#include <algorithm>    // fill
#include <iostream>
#include <iterator>     // begin, end
#include <type_traits>  // remove_reference

int main() {
    struct {
        unsigned char name[25];
        unsigned char age;
        unsigned int numberPhone;
    } persons[256];

    // an instance with the proper values:
    std::remove_reference_t<decltype(persons[0])> temp{
        .name = "Mohammed", .age = 0, .numberPhone = 0};

    // fill the array
    std::fill(std::begin(persons), std::end(persons), temp);
}

注意:

std::remove_reference_t<decltype(persons[0])>
是获取匿名类的 type 的一种麻烦方法。更愿意为您创建的类型命名。


0
投票

memset
不适合初始化结构体,因为它只能将每个字节设置为相同的值。为了使用不同的数据类型初始化像您这样的结构体,您需要定义一个默认结构体,并使用循环或为此目的设计的标准函数将其复制到数组中的每个元素,这可以保持良好的性能和正确性。


0
投票

标准 C 函数

memset
的声明方式如下

void *memset(void *s, int c, size_t n);

也就是说,它用第二个参数中存储的单个字符填充第一个参数指向的所有内存。所以它不适合你这样的任务。

此外,最好使用命名结构,因为这可以简化对结构类型的引用。并且至少数据成员

age
应该具有类型
unsigned int
而不是类型
char
,因为否则要输出
age
,您在任何情况下都需要将其转换为类型,例如
int
unsigned int

如果您确实指的是 C++,则可以使用标准算法

memset
,而不是使用
std::for_each
。例如

这是一个演示程序。

#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    const std::size_t numberOfPersons = 5 /*or 264*/;
    struct Person
    {
        unsigned char name[25];
        unsigned int age;
        unsigned int numberPhone;
    } persons[numberOfPersons];

    std::for_each( std::begin( persons ), std::end( persons ),
        []( auto &person )
        {
            person = { "Mohammed", 0, 0 };
        } );

    for ( const auto &person : persons )
    {
        const auto &[name, age, numberPhone] = person;
        std::cout << "name = " << name 
            << ", age = " << age 
            << ", phone number = " << numberPhone << '\n';
    }
}

程序输出为

name = Mohammed, age = 0, phone number = 0
name = Mohammed, age = 0, phone number = 0
name = Mohammed, age = 0, phone number = 0
name = Mohammed, age = 0, phone number = 0
name = Mohammed, age = 0, phone number = 0

或者代替标准算法

std::for_each
,您可以使用标准算法
std::generate
或标准算法
std::fill
,如下所示

std::generate( std::begin( persons ), std::end( persons ),
    []() -> Person
    {
        return { "Mohammed", 0, 0 };
    } );

std::fill( std::begin( persons ), std::end( persons ),
     Person { "Mohammed", 0, 0 } );

或者,如果您还不知道标准算法,那么只需使用基于范围的 for 循环即可

for (auto &person : persons)
{
    person = { "Mohammed", 0, 0 };
}

但最简单的方法是在其声明中初始化结构,而不使用任何算法或使用默认初始化器的循环。

#include <iostream>

int main()
{
    const std::size_t numberOfPersons = 5 /*or 264*/;
    struct Person
    {
        unsigned char name[25] = "Mohammed";
        unsigned int age = 0;
        unsigned int numberPhone = 0;
    } persons[numberOfPersons];

    for ( const auto &person : persons )
    {
        const auto &[name, age, numberPhone] = person;
        std::cout << "name = " << name 
            << ", age = " << age 
            << ", phone number = " << numberPhone << '\n';
    }
}

如您所见,既没有使用 memset,也没有使用任何算法,甚至也没有使用循环来初始化数组。:)

考虑到这个基于范围的 for 循环

for ( const auto &person : persons )
{
    const auto &[name, age, numberPhone] = person;
    std::cout << "name = " << name 
        << ", age = " << age 
        << ", phone number = " << numberPhone << '\n';
}

可以重写为

    for (const auto &[name, age, numberPhone] : persons)
    {
        std::cout << "name = " << name
            << ", age = " << age
            << ", phone number = " << numberPhone << '\n';
    }
}

这些循环仅从 C++17 标准开始有效。否则你可以写

for ( const auto &person : persons )
{
    std::cout << "name = " << person.name 
        << ", age = " << person.age 
        << ", phone number = " << person.numberPhone << '\n';
}

对于 C 来说,除了使用循环之外没有其他方法,因为在 C 中你可能无法为其数据成员声明一个具有默认初始化程序的结构。

© www.soinside.com 2019 - 2024. All rights reserved.