целочисленное переполнение в PIC - куда идет поток? - PullRequest
3 голосов
/ 09 января 2012

Работа с микрочипом 18f4620 PIC. Это должен быть стандартный вопрос ANSI C.

Скажи, что у меня

unsigned int16 badFlow=65535 //max unsigned int16 value

Это двоичное значение 1111 1111 1111 1111.

если я тогда

badFlow++;

битовая комбинация становится 1 0000 0000 0000 0000 17 бит Очевидно badFlow == 0, но дополнительный перевернутый бит либо

  1. отбрасывается
  2. или проживает там, где byte* flowPtr = &badFlow+2; точек.

Я предполагаю последнее, но надеюсь на первое.

Моя проблема: сотрудник написал какой-то плохой код со счетчиком, который переполнял все производимые продукты в течение ~ 2 лет. Учитывая, что наши клиенты берут плату за использование этих инструментов, это несколько миллионов долларов в опасности из-за потенциально плохих данных.

Ответы [ 6 ]

7 голосов
/ 09 января 2012

Арифметика в Си происходит с значениями , а не байтами в памяти.Ваше выражение badFlow++ эквивалентно badFlow = badFlow + 1.Правая сторона оценивается как тип int (из-за повышения по умолчанию, если int больше 16 бит; если int только 16 бит, то оно будет оценено как unsigned int), что приведет к 65536,затем, когда 65536 назначается в 16-разрядную переменную без знака, она уменьшается по модулю 65536, что приводит к 0.

Важно получить из этого ответа то, что badFlow++ не является прямой операцией надпамять на &badFlow (хотя она может быть реализована как таковая в некоторых реализациях).Это просто сокращение для добавления и назначения.

5 голосов
/ 09 января 2012

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

4 голосов
/ 09 января 2012

Переполнение или переполнение целочисленного типа в стандартном C, как правило, является безопасной операцией и не приведет к изменению памяти за пределами доступной переменной.В стандарте C бит переполнения отбрасывается, хотя реализация может хранить его в специальном регистре переполнения или в выделенной ячейке памяти.Например, в системах i386 переполнение сигнализируется в «флаге переноса».

Редактировать : Как указывает @aix, флаг переноса не обновляется каждой соответствующей инструкцией по сборке i386.,Это деталь реализации, конечно;язык C не дает двух сигналов о флагах переноса.

Edit 2 : И, как указывает Р., переполнение со знаком является неопределенным поведением, хотя каждая реализация, которую я видел, все еще обрабатываетэто безопасно.

4 голосов
/ 09 января 2012

Вариант 1 правильный, переполнение игнорируется.

4 голосов
/ 09 января 2012

Это не переполнится в памяти, которая следует за badFlow.

0 голосов
/ 09 января 2012

Переход на uint32 и создание новой версии программного обеспечения будет правильным выбором.

...