Могу ли я сохранить значение выхода sizeof типа size_t в неподписанном объекте int? - PullRequest
1 голос
/ 06 марта 2020

sizeof - стандартный оператор C.

sizeof возвращает размер (в байтах) своего операнда в типе size_t, цитата из ISO / IEC 9899 : 2018 (С18), 6.5.3.4/5. Фразы, окруженные --, являются моим дополнением для пояснения контекста:

Значение результата обоих операторов - (sizeof и _Alignof) - определяется реализацией, а его тип ( целочисленный тип без знака) size_t, определенный в <stddef.h> (и других заголовках).

Неявно, если я хочу, чтобы моя программа соответствовала стандарту и использовал sizeof, мне нужно включить один из заголовочных файлов, в которых определен size_t, потому что значение, которое он дает, имеет тип size_t, и я хочу сохранить значение в соответствующем объекте.

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

Могу ли я использовать неподписанный объект int для хранения выходных данных size_t value sizeof без явного приведения?

Как, например,

char a[19];
unsigned int b = sizeof(a);

Я скомпилировал это с опцией gcc и -Wall и -Werror, но на это не на что было жаловаться.

Но соответствует ли это стандарту?

Ответы [ 4 ]

4 голосов
/ 06 марта 2020

Это полностью соответствует, хотя, если у вас очень большой объект (обычно 4 ГБ или больше), его размер может не вписаться в unsigned int. Иначе не о чем беспокоиться.

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

3 голосов
/ 06 марта 2020

Это разрешено. Это неявное преобразование («как по присваиванию»). См. Раздел «Целочисленные преобразования»:

Значение любого целочисленного типа может быть неявно преобразовано в любой другой целочисленный тип. За исключением случаев, когда это распространяется на акции и булевы преобразования выше, действуют следующие правила:

  • , если целевой тип может представлять значение, значение остается неизменным
  • , в противном случае, если целевой тип не подписан значение 2 ^ (b-1), где b - количество битов в целевом типе, многократно вычитается или добавляется к исходному значению, пока результат не будет соответствовать целевому типу. Другими словами, целые числа без знака реализуют по модулю арифметику c.

Другими словами, это всегда определенное поведение, но если размер слишком велик, чтобы поместиться в unsigned int, оно будет усечено.

3 голосов
/ 06 марта 2020

Допустимо, но вы обязаны убедиться, что не будет переполнения, хранящего значение типа size_t в объекте типа unsigned int. Для целочисленных типов без знака переполнение является четко определенным поведением.

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

Обычно тип size_t является псевдонимом для типа unsigned long. В некоторых 64-разрядных системах тип unsigned long имеет тот же размер, что и тип unsigned long long, что составляет 8 байтов вместо 4 байтов, в которых может храниться unsigned int.

1 голос
/ 06 марта 2020

В принципе это нормально. unsigned int может обрабатывать почти любые sizeof, кроме искусственно созданных экзотических c вещей.

PS Я видел код, похожий на ваш, даже в Linux модулях ядра.

...