Как установить изменчивый массив в ноль с помощью memset?

volatile uint8_t reset_mask[768] = {0}

Теперь я устанавливаю значения элементов этого массива в 1 во время одной из внутренних операций.

В другом функциональном вызове мне нужно установить для всех элементов этого массива значение 0. Один из способов — использовать цикл for, но я считаю, что лучший способ назначить все элементы массива — использовать memset

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

но я получаю эту ошибку: - "приведение от типа" volatile uint8_t* {aka volatile unsigned char*}' к типу "void*" отбрасывает квалификаторы"

В случае, если мы не можем использовать здесь memset, есть ли лучший способ установить все элементы этого изменчивого массива за один раз?


person Ankur    schedule 17.06.2013    source источник
comment
std::fill(std::begin(reset_mask), std::end(reset_mask), 0); работает.   -  person R. Martinho Fernandes    schedule 17.06.2013
comment
@R.MartinhoFernandes Это должен быть ответ (поскольку это действительно единственный правильный ответ). В C, конечно, ему пришлось бы использовать свой собственный цикл.   -  person James Kanze    schedule 17.06.2013
comment
Для чего вы используете volatile массив? Возможно, вам придется отключить некоторые/все прерывания?   -  person Martin James    schedule 17.06.2013
comment
Есть ли веская причина, по которой вы используете volatile. Volatile следует использовать только для отображаемых в память регистров FIFO, где memset совершенно неуместен. Пожалуйста, не используйте volatile в многопоточности. Скорее используйте соответствующие замки.   -  person doron    schedule 17.06.2013
comment
Volatile используется потому, что reset_mask используется несколькими PU, одновременно выполняющими один и тот же код и изменяющими значения элементов массива. В моей ситуации есть условие, в котором проверяется while(reset_mask[pu]==0){..//В этом цикле не устанавливается reset_mask, поэтому, если мы не используем volatile, из-за оптимизации компилятора это может получить оптимизацию в то время как (истина). Использование ключевого слова Volatile предотвращает такую ​​оптимизацию компилятора.......}   -  person Ankur    schedule 17.06.2013
comment
Используйте замки. Помните, что операции чтения и записи могут быть переупорядочены. Volatile только влияет на компиляцию и не влияет на поведение процессора. Если вы хотите гарантировать порядок чтения и записи между потоками, ваш ЦП предоставит барьеры памяти данных. Там будут включены соответствующие блокировки, Volatile не способ сделать это.   -  person doron    schedule 17.06.2013
comment
Взгляните на: stackoverflow.com/questions/3612505/   -  person doron    schedule 17.06.2013
comment
@doron - «Пожалуйста, не используйте volatile в многопоточности» - действительно. Я предположил, что 'reset_mask' был чем-то вроде драйвера, прерывания, где 'volatile' был действительно полезен.   -  person Martin James    schedule 17.06.2013


Ответы (2)


Вы «можете» использовать memset для отбрасывания изменчивости с const_cast, но это удалит изменчивую семантику. Так что, если это не подходит для вас, вы застряли с петлевой версией. Если ваша реализация не дает вам версию memset, которая использует volatile* и задокументирована для выполнения вашей работы. (Я думаю, маловероятно, что вне встроенных систем это меня удивит даже там.)

person Balog Pal    schedule 17.06.2013

Как сказал Балог Пал, отбрасывание volatile для вызова memset нарушает семантику volatile. Весь memset может быть оптимизирован, или может произойти неопределенное поведение.

Либо напишите свой собственный цикл для обнуления массива, либо используйте этот memset_volatile:

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

Настоящий memset также возвращает s, а c — это int, но мне эта версия чище.

Совершенно неясно, разрешено ли компилятору оптимизировать эту функцию для записи более одного байта за раз, поэтому, если массив очень большой, это может быть немного медленным.

Изменить: начиная с C11 существует memset_s. По какой-то причине указатель на volatile не требуется, поэтому вам нужно отбросить volatile. Однако гарантируется фактическая перезапись памяти.

person Tor Klingberg    schedule 10.05.2017