сомнения относительно операций над "int" ароматами - PullRequest
4 голосов
/ 13 июля 2010

У меня возникают следующие сомнения в отношении типов int (unsigned int, long int, long long int).

Когда мы выполняем некоторые операции (*, /, +, -) между int и его ароматами(допустим, long int) в 32-битной и 64-битной системах неявная типизация происходит для "int"

, например: -

int x;long long int y = 2000;

x = y;(Чем выше назначено, тем ниже может произойти усечение данных) Я ожидаю, что компилятор выдаст предупреждение за это, но я не получаю такого предупреждения.Это происходит из-за неявной передачи типов для "x" здесь.Я использую gcc с опцией -Wall.Это поведение изменится для 32-битных и 64-битных.

Спасибо Arpit

Ответы [ 5 ]

7 голосов
/ 13 июля 2010

-Wall не активирует все возможные предупреждения. -Wextra включает другие предупреждения. В любом случае, то, что вы делаете, является совершенно «законной» операцией, и поскольку компилятор не всегда может знать во время компиляции значение элемента данных, который может быть «усечен», это нормально, он не предупреждает: программист должен уже знать из-за того, что «большое» целое число не может вписаться в «маленькое» целое число, так что обычно дело за программистом. Если вы думаете, что ваша программа написана не осознавая этого, добавьте -Wconversion.

3 голосов
/ 13 июля 2010

Приведение без явного оператора приведения типа совершенно допустимо в C, но может иметь неопределенное поведение.В вашем случае int x; подписано, поэтому, если вы попытаетесь сохранить в нем значение, выходящее за пределы диапазона int, ваша программа будет иметь неопределенное поведение.С другой стороны, если x было объявлено как unsigned x;, поведение четко определено;приведение происходит через уменьшение по модулю UINT_MAX+1.

Что касается арифметики, когда вы выполняете арифметику между целыми числами разных типов, «меньший» тип переводится в «больший» тип до арифметики.Разумеется, компилятор может оптимизировать это повышение, если оно не влияет на результаты, что приводит к таким идиомам, как приведение 32-разрядного целого к 64-разрядному перед умножением для получения полного 64-разрядного результата.Продвижение становится немного запутанным и может привести к неожиданным результатам, когда значения со знаком и без знака смешаны.Вам следует поискать это, если вы хотите знать, потому что это трудно объяснить неофициально.

2 голосов
/ 13 июля 2010

Ваш код действителен (как уже сказали другие). Если вы хотите программировать переносимым способом, в большинстве случаев вам не следует использовать простые типы C int, long или unsigned int, но типы, которые немного лучше говорят о том, что вы планируете делать с ним.

Например, для индексов массивов всегда используйте size_t. Независимо от того, используете ли вы 32- или 64-разрядную систему или нет, это будет правильный тип. Или, если вы хотите взять целое число максимальной ширины на платформе, вы случайно окажетесь при использовании intmax_t или uintmax_t.

2 голосов
/ 13 июля 2010

Если вы беспокоитесь, вы можете включить <stdint.h> и использовать типы с определенной длиной, например, uint16_t для 16-разрядного целого числа без знака.

1 голос
/ 13 июля 2010

См. http://gcc.gnu.org/ml/gcc-help/2003-06/msg00086.html - код является совершенно допустимым C / C ++.

Возможно, вы захотите взглянуть на инструменты статического анализа (sparse, llvm и т. Д.), Чтобы проверить этот типусечение.

...