Перейти к содержанию
    

Понятие стандартного типа и тип операндов...

Имеем код

uint32_t a = 320 * 240;

Компилятор будет трактовать операнды 320 и 240 как имеющие тип int? Результат будет зависеть от разрядности int(16/32), правильно я понимаю?

И вообще, когда говорят "16ти битный компилятор" имеют ввиду именно разрядность int?

На C2000 int 16ти битный и a получается == 11264, хотя на самом деле должно быть 76800.

А что,если так?

uint32_t a = (uint32_t)320 * 240;

чё получим?

 

или так

uint32_t a = 320 * (uint32_t)240;

 

ну так то понятно, что всё будет OK

uint32_t a = (uint32_t)320 * (uint32_t)240;

 

Сбивает ещё то, что в какой-то книге довелось прочитать, что тип будет взят от первого операнда... потом на форуме видел, что такие вещи компилятор трактует как имеющие стандартный тип(есть вообще такое понятие?).

 

Копнуть ISO/IEC 9899:1999 пытался, но без привычки это достаточно сложно....

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Компилятор будет трактовать операнды 320 и 240 как имеющие тип int?

Как uint32_t.

А вот что такое uint32_t - надо смотреть где это тип определяется.

 

Интуитивно можно догадаться, что это некий UNSIGNED тип.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что,если так?
uint32_t a = (uint32_t)320 * 240;

чё получим?

или так

uint32_t a = 320 * (uint32_t)240;

ну так то понятно, что всё будет OK

uint32_t a = (uint32_t)320 * (uint32_t)240;

Ну очевидно, что все эти варианты будут работать правильно. Кстати тулз 5.2.1 для первого примера( 320 * 240 ) выдаёт warning: "integer operation result is out of range". Значит он их определяет как int. В данном случае можно писать красивее:

uint32_t a = 320L * 240;

Как там в стандарте сам не знаю :) .

 

ps: uint32_t тут должен определяться как unsigned long.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имеем код
uint32_t a = 320 * 240;

Компилятор будет трактовать операнды 320 и 240 как имеющие тип int? Результат будет зависеть от разрядности int(16/32), правильно я понимаю?

Да, int - платформеннозависимый тип. Для определенности вы можете, например, написать:

uint32_t a = 320ul * 240;

 

Но я бы сделал так:

 

const uint32_t X_SIZE = 320;
const uint32_t Y_SIZE = 240;
uint32_t a = 320 * 240;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На самом деле смысл там такой - если все операнды помещаются в int, то операция и производится как int (а если калибр операндов меньше, чем int, они к нему приводятся, это называется integer promotion) . Калибр int'а, естественно, зависит от платформы.

 

Соответственно, оба операнда (320 и 240) в int помещаются и операция производится в калибре int, только вот результат произведения не лезет. Достаточно указать, что один из операндов 32хбитный и все будет хорошо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну uint32_t я намеренно использовал для того, чтобы однозначно определить, что это именно unsigned 32бита.

 

uint32_t a = 320L * 240L;

 

Ну так а на другом компиляторе, где long будет 64бит - будет уже оверхед?

 

Ну с const'ами то ясно, что самый правильный вариант.

 

Ну а вообще, как оно в стандарте то?

Да, int - платформеннозависимый тип. Для определенности вы можете, например, написать:

Код

uint32_t a = 320ul * 240;

А почему достаточно первый определить как ul и всё работает? А если операнда три? А если не левый, а крайний правый сделать ul

ну типа uint32_t a = 320 * 240 * 2ul;

 

Как вообще по стандарту? Что сказано о таких случаях?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну так а на другом компиляторе, где long будет 64бит - будет уже оверхед?

в компиляторов для настольных ПК 64 бита - это long long))

 

а long = int = 32 бита...

 

 

uint32_t a = 320 * 240;

 

компилятор будет рассматривать обе константы как типа int. если int 16 бит - будет переполнение...

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну так а на другом компиляторе, где long будет 64бит - будет уже оверхед?

Не будет оверхеда, так как результат все равно обкоцают до uint32, и оптимизатор, понимая это, воткнет константу наиболее оптимального для платформы типа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в компиляторов для настольных ПК 64 бита - это long long))
oops, чё-то я малёк запутался уже :)

 

если операндов несколько... компилятор определяет самый "длинный" или "сложный" тип среди операндов и все приводит к нему. После выполнения операции он начинает думать, как его привести к переменной, которой ему нужно присвоить результат.
Вооот. Вот это то, что хотелось знать. СПАСИБО! :)

 

А ещё вопросик: если в выражении есть скобки это что-то меняет? Я имею ввиду выбирать самый длинный и сложный он будет не смотря на скобки? А то был у меня один странный случай, я там вроде указал самого жирного, а чё-т не работало, пока всёх явно к 32бит типу не привёл.... Щас уже не вспомню толком где это было... Показал бы конкретное выражение. Там были скобки, точно помню. Ещё тогда подумал, что что-то я не понял в этой жизни :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если операндов несколько... компилятор определяет самый "длинный" или "сложный" тип среди операндов

Неправильно.

 

В указанном порядке (например, для операции умножения - сдева направо) вычисляются выражения над двумя операндами.

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

То есть, в выражении

 

2 * 3L * 4.0

 

сперва 2 делается long, потом умножается на 3, затем результат делается float и умножается на 4.

 

Скобки, естественно, меняют порядок вычислений.

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот что такое uint32_t - надо смотреть где это тип определяется.

 

Интуитивно можно догадаться, что это некий UNSIGNED тип.

Этот тип определен в stdint.h, означает 32-битовое беззнаковое целое и вместе со всем содержимым stdint.h описан в стандарте C99.

 

Я имею ввиду выбирать самый длинный и сложный он будет не смотря на скобки?
Еще раз уточним. Операции бывают унарные (один операнд, x = ~y), бинарные (два операнда, x = y * z) и тернарные (такая только одна: x = y ? z : i). Все выражение разбивается на эти примитивы в соответствии с приоритетом операций. Естественно, скобки влияют на приоритет. Т.е. выражение a = b * c * d - это на самом деле три выражения:

tmp1 = b * c;

tmp2 = tmp1 * d;

operator = (a, tmp2);

И для каждого из них отдельно применяются правила неявных приведений типов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но я бы сделал так: ....
Так будет корректней:

static const uint32_t X_SIZE = 320UL;
static const uint32_t Y_SIZE = 240UL;
uint32_t a = X_SIZE * Y_SIZE;

Без статика возможны "игры разума" компиляторов...

И ещё, никакого оверхеда быть не может, т.к. константные выражения вычислятся при компиляции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

const uint32_t X_SIZE = 320;
const uint32_t Y_SIZE = 240;
uint32_t a = X_SIZE * Y_SIZE;

 

А можно как-нибудь так, чтобы 240 хранилось в int8 или int16, а то int32 как-то накладно выглядит.

 

P.S: На случай, если они перестанут быть константными или поучаствуют ещё-где-нибудь.

Изменено пользователем Злодей

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...