Сдвиг влево int
имеет потенциал для неопределенного поведения (UB) каждый раз, когда бит «один» сдвигается в знаковый бит.
Это может произойти с произвольными int
значениями, как в some_int << 8
.
getc()
возвращает значения в диапазоне unsigned char
или отрицательное значение EOF
. Сдвиг влево EOF
- UB. Значение влево, равное 128 с 128 << 24
, равно UB.
Вместо этого накапливайте неотрицательные значения из getc()
, используя unsigned math.
Рекомендовать изменить сигнатуру функции для учета ошибок конца файла / ввода.
#include <stdbool.h>
#include <limits.h>
// return true on success
bool ReadInt(int *dest) {
unsigned urnt = 0;
for (unsigned shift = 0; shift < sizeof urnt * CHAR_BIT; shift += CHAR_BIT) {
int ch = getc(xxx);
if (ch == EOF) {
return false;
}
urnt |= ((unsigned) ch) << shift;
}
*dest = (int) urnt;
return true;
}
Преобразование (int) urnt
вызывает «сигнал, определяемый реализацией, или сигнал, определяемый реализацией, повышается», и это обычно ожидаемая функциональность: значения в urnt
выше INT_MAX
«обтекание».
В качестве альтернативы, педантичный код может использовать:
if (urnt > INT_MAX) {
*dest = (int) urnt;
} else {
*dest = ((int) (urnt - INT_MAX - 1)) - INT_MAX - 1;
}
Улучшения для image->colors * unit_size
.
//int unit_size = 0;
// unit_size = sizeof(unsigned int);
size_t unit_size = sizeof(unsigned int);
// unsigned int malloc_size = 0;
if (image->colors > 0 &&
// image->colors < (1024 * 1024 * 128) &&
image->colors < ((size_t)1024 * 1024 * 128) &&
unit_size > 0 &&
unit_size <= 8)
{
size_t malloc_size = (size_t) image->colors * unit_size;
// image->palette = (unsigned int *)malloc( malloc_size );
image->palette = malloc(malloc_size);
1024 * 1024 * 128
- это проблема, когда INT_MAX < 134217728
(28 бит int
).
См. Есть причины не использовать 1000 *1000* 1000