Как заставить работать аргумент изменчивой функции? - PullRequest
0 голосов
/ 28 мая 2020

Я совершенно не знаком с C ++, я использую C все время. В моем недавнем хобби-проекте мне нужно смешать библиотеку C ++ с моим кодом C, что вынудило меня использовать основной код C ++. cpp.

Я сейчас вмешиваюсь в свой код C для компиляции как C ++. Это даже работает очень хорошо, за исключением одной проблемы, которую я просто не могу решить.

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

volatile time_t UNIX_TIME = 0;
volatile struct tm TIME_CUR_LOCALTIME;  

if (htim == &htim2){
    UNIX_TIME++;
    TIME_CUR_LOCALTIME = *localtime(&UNIX_TIME);
}

Из библиотеки time.h:

struct tm *localtime (const time_t *_timer);

С gcc это компилируется безупречно.

g++ - это отдельная история. Это дает мне ошибку:

ошибка: передача 'volatile tm' в качестве аргумента 'this' отбрасывает квалификаторы [-fpermissive]

Я пробовал несколько приведений и прочее, Единственный способ, которым это начинает работать само по себе, - это когда я отбрасываю оба изменчивых квалификатора. Но я этого не хочу.

Как правильно заставить это работать? У меня нет идей.

Ответы [ 2 ]

0 голосов
/ 28 мая 2020

Ни в стандарте C, ни в стандарте C ++ не делается попыток различать guish между объектами, которые будут изменены таким образом, чтобы компилятор не имел оснований ожидать, те, которые будут записаны только способами, компилятор понимает, но может также быть прочитан способами, которых не было бы ожидать, и те, которые, хотя и объявлены volatile, фактически никогда не будут доступны способами, которые компилятор не ожидал (последняя ситуация может возникнуть с библиотеками, которые иногда будет использоваться в системах, где доступ к объектам осуществляется извне, а иногда и в системах, где это не так). Все объекты, не относящиеся к atomi c, к которым можно получить доступ способами, которых компилятор не ожидал, должны быть квалифицированы как volatile, и поскольку - с точки зрения стандарта - все объекты, квалифицированные как volatile, могут быть прочитаны или написано произвольными внешними средствами, любой доступ к такому объекту без квалификатора volatile вызывает Undefined Behavior, , независимо от того, действительно ли происходит какой-либо внешний доступ . Авторы Стандарта, вероятно, признали, что, поскольку люди, желающие продавать компиляторы, будут разумно обращаться с такими случаями, не обращая внимания на то, обязаны ли они это делать, в Стандарте нет необходимости рассматривать такие случаи. Однако не все разработчики компиляторов связаны этим принципом.

Лучшим способом добиться такого поведения, вероятно, было бы скопировать UNIX_TIME в пару обычных объектов, убедившись, что они совпадают и повторяются в противном случае выполняется попытка чтения, а затем передается адрес этой функции любым функциям, которым потребуется адрес объекта, хранящего время. Как отмечалось в другом месте, следует избегать таких функций, как localtime, которые используют буферы stati c, использовать такие функции, как localtime_r, но что важно, если кто-то хочет закрыть компилятор, - это скопировать объект в другое место перед использованием.

0 голосов
/ 28 мая 2020

Сначала скопируйте время в энергонезависимый экземпляр:

time_t t = UNIX_TIME;
tm local = *localtime(&t);
TIME_CUR_LOCALTIME.tm_sec   = local.tm_sec;
TIME_CUR_LOCALTIME.tm_min   = local.tm_min;
TIME_CUR_LOCALTIME.tm_hour  = local.tm_hour;
TIME_CUR_LOCALTIME.tm_mday  = local.tm_mday;
TIME_CUR_LOCALTIME.tm_mon   = local.tm_mon;
TIME_CUR_LOCALTIME.tm_year  = local.tm_year;
TIME_CUR_LOCALTIME.tm_wday  = local.tm_wday;
TIME_CUR_LOCALTIME.tm_yday  = local.tm_yday;
TIME_CUR_LOCALTIME.tm_isdst = local.tm_isdst;
...