Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set volatile array to zero using memset?

volatile uint8_t reset_mask[768] = {0}

Now I am setting the values of this array elements to 1 during one of internal operations.

In another functional call, I need to set all the elements of this array to 0. One way is by using for loop but I believe better way to assign all the elements of array is by using memset

memset(reset_mask, 0, sizeof(reset_mask));

but I am getting this error :- "cast from type 'volatile uint8_t* {aka volatile unsigned char*}' to type 'void*' casts away qualifiers"

In case we cannot use memset here, is there a better way to set all elements of this volatile array in one go?

like image 903
Ankur Avatar asked Jun 17 '13 09:06

Ankur


People also ask

How do you use memset?

memset() is used to fill a block of memory with a particular value. The syntax of memset() function is as follows : // ptr ==> Starting address of memory to be filled // x ==> Value to be filled // n ==> Number of bytes to be filled starting // from ptr to be filled void *memset(void *ptr, int x, size_t n);

What does memset function do in C++?

memset in C++ This function converts the value of a character to unsigned character and copies it into each of first n character of the object pointed by the given str[]. If the n is larger than string size, it will be undefined. void* memset( void* str, int c, size_t n);

What is memset and memcpy?

memset() is used to set all the bytes in a block of memory to a particular char value. Memset also only plays well with char as it's its initialization value. memcpy() copies bytes between memory. This type of data being copied is irrelevant, it just makes byte-for-byte copies.

How do you string a memset?

Syntax: void* memset( void* str, int ch, size_t n); Memset() converts the value ch to unsigned char and copies it into each of the first n characters of the object pointed to by str[]. If the object is not trivially-copyable (e.g., scalar, array, or a C-compatible struct), the behavior is undefined.


2 Answers

You "can" use memset casting away volatileness with const_cast, but it will remove the volatile semantics. So unless that is okay for you, you're stuck with the loop version. Unless your implementation gives you a version of memset that takes volatile* and is documented to do your job. (I'd think unlikely outside embedded systems, would surprise me even there.)

like image 200
Balog Pal Avatar answered Oct 23 '22 16:10

Balog Pal


As Balog Pal said, casting away volatile to call memset breaks the volatile semantics. The whole memset may get optimized away, or undefined behaviour badness happens.

Either write your own loop to zero out the array, or use this memset_volatile:

void memset_volatile(volatile void *s, char c, size_t n)
{
    volatile char *p = s;
    while (n-- > 0) {
        *p++ = c;
    }
}

The real memset also returns s and c is an int, but this version is cleaner to me.

It is quite unclear if the compiler is allowed to optimize this function to write more than one byte at a time, so if the array is very large it could be a bit slow.

Edit: Since C11 there is memset_s. It doesn't take a pointer to volatile for some reason, so you have to cast away the volatile. It is however guaranteed to actually overwrite the memory.

like image 21
Tor Klingberg Avatar answered Oct 23 '22 17:10

Tor Klingberg