Разве это плохо, чтобы переполнить и переполнить неподписанную переменную?
Kraaa.
Я учусь в школе программирования, которая требует, чтобы мы написали C-функции с менее чем 25 строками кода. Итак, в основном, каждая строка имеет значение. Иногда мне нужно укорачивать задания примерно так:
#include <stddef.h>
#include <stdio.h>
#define ARRAY_SIZE 3
int main(void)
{
int nbr_array[ARRAY_SIZE] = { 1, 2, 3 };
size_t i;
i = -1;
while (++i < ARRAY_SIZE)
printf("nbr_array[%zu] = %i\n", i, nbr_array[i]);
return (0);
}
Важной частью этого кода является size_t
счетчик имени i
, Чтобы сэкономить несколько строк кода, я хотел бы предварительно увеличить его в условии цикла. Но, поскольку стандарт C определяет size_t
как тип без знака, то, что я в основном делаю здесь i
переменная (от 0 до очень большого значения), затем переполняет его один раз (от этого большого значения до 0).
Мой вопрос заключается в следующем: независимо от плохой практики сокращения нашего кода, безопасно ли устанавливать unsigned
( size_t
) переменная до -1, а затем предварительно увеличивать его на каждой итерации, чтобы просмотреть массив?
Спасибо!
3 ответа
i = -1;
часть вашей программы в порядке.
преобразование -1
к целому типу без знака определяется в C и приводит к значению, которое, если увеличивается, приводит к нулю.
Тем не менее, вы не получаете никакой строки кода в отношении идиоматического for (i=0; i<ARRAY_SIZE; i++) …
,
Ваш %zi
формат должен быть наверное %zu
,
Арифметика без знака никогда не "переполняется / переполняется" (по крайней мере в том смысле, в котором стандарт говорит о неопределенном поведении переполнения арифметики со знаком). Вся арифметика без знака на самом деле является модульной арифметикой и, как таковая, является безопасной (то есть она не будет вызывать неопределенное поведение само по себе).
Чтобы быть точным, стандарт C гарантирует две вещи:
- Любое целочисленное преобразование в
unsigned
тип хорошо определен (как будто число со знаком было представлено как 2-дополнение) - переполнение / недостаток
unsigned
целые числа хорошо определены (модульная арифметика с 2^n)
поскольку size_t
это неподписанный тип, вы не делаете ничего плохого.