简体   繁体   English

使用memset初始化三值结构数组

[英]Initialize array of 3-value structures using memset

How do I initialize array of structures with values? 如何使用值初始化结构数组? So, I have structure color with rgb values. 因此,我具有带有rgb值的结构颜色。

struct color{
    GLfloat r;
    GLfloat g;
    GLfloat b;
}

and trying to initialize it with 1.0f. 并尝试使用1.0f对其进行初始化。

color* cArray = (color*) malloc(w*h*sizeof(color));
memset(&cArray, 1.0, sizeof color);

But instead of correct work I get segmentation fault on cArray[0]. 但是我没有正确的工作,而是在cArray [0]上遇到了分段错误。 What do I miss? 我想念什么?

Note: Do not cast void * (result of malloc() ) to other pointers and always check the result of malloc() & friends . 注意:请勿将void *malloc()结果) malloc()为其他指针,并始终检查malloc()和friends的结果

Memset takes an unsigned char (most likely 8 bits) and treats the area passed as an array of char. Memset接受一个无符号的char(最有可能是8位),并将通过的区域视为char数组。 It has no idea of structs, arrays etc. Just of a 1-dimensional array of char. 它不知道结构,数组等。只是char的一维数组。 (as @chqrlie noted, memset() actually takes an int ; this is, however, internally converted to unsigned char ). (正如@chqrlie所指出的, memset()实际上是一个int ;但是,它在内部转换为unsigned char )。

The segfault is because you pass the address of cArray which is a pointer to the actual array, not its value which would be the array itself. segfault是因为您传递了cArray的地址,该地址是指向实际数组的指针,而不是其值(该值将是数组本身)。

For float, memset() most likely only makes sense setting it to all- 0 : 对于float,memset()最有可能仅将其设置为all- 0才有意义:

memset(cArray, 0, sizeof(struct color) * w * h);

Note: memset has no idea on data types. 注意:memset对数据类型一无所知。 It just takes a pointer to a block of memory and a count and stores the value to that area. 它只需要指向一个内存块和一个计数的指针,并将值存储到该区域。 It is your responsibility all arguments are valid! 所有论据均有效,这是您的责任!

Note that writing the memory area with 0 is actually float zero ( 0.0 , actually +0.0 ), as that has all bits cleared. 请注意,用0写入存储区实际上是浮点数零( 0.0 ,实际上是+0.0 ),因为它清除了所有位。 That was a briliant intention by the guys who dsigned the encoding for floats. 对浮点数进行编码的家伙们的意图很强烈。

As you allocate right before, you can combine this using calloc() . 如前所述,您可以使用calloc()将其合并。 That will allocate and clear the memory area of the array. 这将分配并清除阵列的内存区域。 However, if you intend to set all values explicitly anyway, you better stick with malloc() . 但是,如果打算以任何方式显式设置所有值,则最好坚持使用malloc()

If you want to set other float values, you have to write your own loop. 如果要设置其他浮点值,则必须编写自己的循环。 However, you can threat the array as 1-dimensional for that. 但是,您可以为此威胁数组为一维数组。

for ( size_t i = 0 ; i < w * h ; i++ )
    cArray[i] = (struct color){ .r = 1.0, .g = 1.0, .b = 1.0 };

That uses a compound literal . 那使用复合文字 Alternatively you can also set the fields seperately. 另外,您也可以单独设置字段。

If you are upt for speed, the compount-literal approach might be the fastest. 如果您追求速度,那么复合文字方法可能是最快的。 This way ,the compiler might very well load al values into three registers and store them directly into memory using store-multiple. 这样,编译器很可能将al值加载到三个寄存器中,并使用store-multiple将它们直接存储到内存中。 However it might do, I would bet the compiler will recognize that pattern and optimize as hell, as it is commonly used for very large loops. 无论如何,我敢打赌,编译器将识别出该模式并进行优化,因为它通常用于非常大的循环。

You can't use memset() to set float values. 您不能使用memset()设置float值。

The memset() function is used for bytes, so using it for float s is not allowed, you need to explicitly initialize each member memset()函数用于字节,因此不允许将其用于float ,您需要显式初始化每个成员

This is memset() 's signature 这是memset()的签名

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

although it expects int 1 for it's second parameter, the standard says 尽管它的第二个参数是int 1 ,但标准表示

7.24.6 Miscellaneous functions 7.24.6其他功能

7.24.6.1 The memset function 7.24.6.1 memset函数

  1. The memset function copies the value of c (converted to an unsigned char ) into each of the first n characters of the object pointed to by s . memset函数将c的值(转换为unsigned char复制到s指向的对象的前n 字符中的每个字符中。

" converted to an unsigned char " so it sets bytes. 转换为unsigned char ”,因此它设置字节。

Also take in consideration the following: 还请考虑以下几点:

  1. You don't need to cast the return value of malloc() , and it's better if you don't do it. 不需要malloc()的返回值,如果不这样做,则更好。

  2. Always check that malloc() returned non- NULL , specially when allocating a lot of memory. 始终检查malloc()返回非NULL ,尤其是在分配大量内存时。


1 As you can see you can't pass float. 1 如您所见,您不能通过浮点数。

There are multiple problems with your code: 您的代码有多个问题:

You allocate a matrix w x h of color structures: 您分配color结构的矩阵w x h

color *cArray = (color*) malloc(w * h * sizeof(color));

The cast is not necessary in C, but opinions differ about the recommended alternatives. 在C语言中,强制转换不是必需的,但是对于推荐的替代方案,意见不一。 A safer version would be: 一个更安全的版本是:

color *cArray = malloc(w * h * sizeof(*cArray));

More importantly, our call to memset is incorrect in multiple ways: 更重要的是,我们对memset的调用在许多方面都是错误的:

memset(&cArray, 1.0, sizeof color);
  1. You pass the address of the pointer instead of the value of the pointer cArray . 您传递指针的地址而不是指针cArray的值。
  2. You only pass the size of a single color structure. 您只传递单个color结构的大小。 This size exceeds the size of the pointer, hence the crash. 此大小超出了指针的大小,因此导致崩溃。 If you intended to set the whole array you should have store the size into a temporary variable. 如果要设置整个数组,则应将大小存储到一个临时变量中。
  3. You pass a double instead of an int as the value to set. 您传递double精度值而不是整数作为要设置的值。 You cannot initialize an array of double values with memset : this function initializes a block of memory by setting all bytes to the same value. 您不能使用memset初始化一个double memset值数组:此函数通过将所有字节设置为相同值来初始化内存块。 Passing 0 would initialize double values correctly if your system uses IEEE-754 representation for floating point values, otherwise it might invoke undefined behaviour. 如果系统将IEEE-754表示形式用于浮点值,则传递0将正确初始化double精度值,否则,它可能会调用未定义的行为。

You must initialize the matrix with a loop: 您必须使用循环初始化矩阵:

for (size_t i = 0, n = w * h; i < n; i++) {
    cArray[i].r = cArray[i].g = cArray[i].b = 1.0;
}

This loop can be optimized by modern compilers. 可以通过现代编译器优化此循环。 I suggest you play with this very interesting tool: http://gcc.godbolt.org/# . 我建议您使用这个非常有趣的工具: http : //gcc.godbolt.org/#

You can also keep a copy of a pre-initialized array and use memcpy to initialize the allocated array. 您还可以保留一个预初始化数组的副本,并使用memcpy初始化分配的数组。

First, colors are (in your case) 3 bytes, not 3 floats. 首先,(在您的情况下)颜色是3个字节,而不是3个浮点数。

then this code: 然后这段代码:

struct color{
    GLfloat r;
    GLfloat g;
    GLfloat b;
}

and trying to initialize it with 1.0f.

color* cArray = (color*) malloc(w*h*sizeof(color));
memset(&cArray, 1.0, sizeof color);

will cause a compiler to raise several warnings: 将导致编译器发出以下警告:

due to the compiler will not knowing what a 'color' is due to: 由于编译器将不知道什么是“颜色”,原因是:

syntax errors in the struct definition
and references to the struct are missing the 'struct' modifier.

when calling malloc() (and family of functions) always check (!=NULL) the returned value to assure the operation was successful. 调用malloc()(和函数系列)时,请始终检查(!= NULL)返回值以确保操作成功。

In C, do not cast the returned value from malloc() (and family of functions) 在C语言中,请勿转换malloc()(和函数族)的返回值

notice that a struct definition ends with a ';' 注意,结构定义以“;”结尾

suggest using: 建议使用:

struct color
{
    char r;
    char g;
    char b;
};

struct color* cArray = NULL;
if( NULL == (cArray =malloc(w*h*sizeof(struct color))))
{ // then malloc failed
    perror( "malloc for struct color array failed" );
    exit( EXIT_FAILURE )
}

// implied else, malloc successful

memset(&cArray, 1, w*h*(sizeof (struct color) );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM