Целочисленное переполнение - PullRequest
0 голосов
/ 08 мая 2009

У меня есть длинная беззнаковая длина, которую я использую для отслеживания громкости. Объем увеличивается на другой беззнаковый long long. Каждые 5 секунд я печатаю это значение, и когда оно достигает 32-битного максимума без знака, printf дает мне отрицательное значение. Ниже приведен фрагмент кода:

unsigned long long vol, vold;
char               voltemp[10];

vold = 0;

Позже ...

while (TRUE) {
    vol = atoi(voltemp);
    vold += vol;    
    fprintf(fd2, "volume = %llu);
}

Что я делаю не так? Это работает под RedHat 4 2.6.9-78.0.5.ELsmp gcc версии 3.4.5

Ответы [ 7 ]

1 голос
/ 08 мая 2009

Поскольку вы говорите, что оно печатает отрицательное значение, должно быть что-то еще не так, кроме использования atoi вместо strtoull. Спецификатор формата %llu просто не печатает отрицательное значение.

Похоже, проблема в вызове fprintf. Убедитесь, что вы включили stdio.h и что список аргументов действительно соответствует исходному коду.

0 голосов
/ 09 мая 2009

Если voltemp очень большой, вам нужно использовать strtoull, а не atoi.

0 голосов
/ 08 мая 2009

Для уточнения оператор fprintf был скопирован неправильно (моя ошибка, извините). Оператор fprintf должен фактически читать:

 fprintf(fd2, "volume = %llu\n", vold);

Кроме того, хотя по общему признанию небрежно, максимальная длина массива voltemp составляет 9 байтов (цифр), что находится в пределах 32-разрядного целого числа.

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

0 голосов
/ 08 мая 2009

Я думаю, проблема в том, что printf не обрабатывает% llu так, как вы думаете. Это, вероятно, занимает всего 32 бита из стека, а не 64.

% llu является стандартным только с C99. может, вашему компилятору нравится% LU лучше?

0 голосов
/ 08 мая 2009

Вы уверены, что fprintf может принимать longlong в качестве параметра, а не указатель на него? Похоже, что он конвертирует ваш longlong в int перед передачей.

0 голосов
/ 08 мая 2009

Вы не можете использовать atoi, если число может превышать границы со знаком int.

РЕДАКТИРОВАТЬ: атолл (который, по-видимому, является стандартным), как предлагается, является еще одним хорошим вариантом. Просто имейте в виду, что ограничивает вас signed long long. На самом деле, самый простой вариант - strtoull , который также является стандартным.

0 голосов
/ 08 мая 2009

Ну, я не могу точно сказать, потому что ваш код имеет синтаксические ошибки, но вот предположение:

vol = atoi(voltemp);

atoi преобразует ASCII в целое число. Возможно, вы захотите попробовать atol , но это приведет к длинному, а не длинному.

Ваша стандартная библиотека C МОЖЕТ иметь атолл .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...