const аргумент функции указателя константы

Для внедренного проекта SW нам нужно использовать некоторые const volatile TYPE * указатели const volatile TYPE * . Теперь у нас есть некоторые функции вычисления, которые выглядят следующим образом:

 uint8 calc(const volatile uint8 *array, uint8 value) { ... } 

Данные обеих переменных не изменяются во время выполнения функции.

Вызывающий код выглядит следующим образом:

 const volatile uint8 *array = (const volatile uint8 *)0x00010111; uint8 value = 8; uint8 result = calc(array, value); 

Вопрос в том, будет ли разница, если мы создадим функции calucation без волатильных аргументов:

 uint8 calc(const uint8 *array, uint8 value) { ... } 

Для вызова мы отбрасываем волатильность:

 uint8 result = calc((const uint8 *)array, value); 

Плюсы для второго решения более гибкие: мы можем использовать эту функцию также для нелетучих переменных. Но разве это имеет значение, если мы отбросим volatile, и наш компилятор делает некоторые сильные оптимизации?

Вы можете ВСЕГДА использовать функцию с энергонезависимыми аргументами. Его просто то, что код в функции обрабатывает данные объекты, как если бы они были неустойчивыми (скорее всего, потеряла производительность на пути). Его немного сложно представить, какая функция с изменчивыми аргументами («потому что они могут измениться без предупреждения») могла бы разумно сделать. Когда вы пишете, в вашем случае данные не меняются в любом случае, поэтому наиболее гибким решением является объявление параметров const и забывание об изменчивости.

И, пожалуйста, используйте «uint8_t», а не какое-то домашнее имя типа uint8 – его в стандарте с 1996 года!

Существует два случая: либо функция манипулирует аппаратными регистрами и т. Д. Напрямую. Затем вы должны иметь изменчивый параметр. Или функция не имеет ничего общего с аппаратными регистрами вообще. Тогда он не должен быть изменчивым. Между этими двумя случаями нет промежуточной точки.

Кроме того, calc((const uint8_t*)array, value); это просто плохая, возможно баггия версия

 const uint8_t* ptr = array; calc(ptr, value); 

Первая форма плохая, потому что порядок оценки аргументов функции – это неуказанное поведение. Компилятор может сначала выбрать левый операнд или правый операнд, и вы не можете знать или принимать заказ. Поскольку доступ к летучести является побочным эффектом, ваш исходный код может давать разные результаты при каждом создании программы. Это особенно проблематично (и, возможно, опасно) в встроенных системах реального времени.

Поэтому рекомендуется избегать доступа к изменчивым переменным внутри выражений (см. MISRA-C: 2004 12.2).

Это зависит от того, что действительно может произойти из-за volatile .

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

Если это не имеет значения или более важны «старые» значения, оставьте volatile .