sigmaN 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба Имеем код 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 и его длиной бывают приколы, как я понял.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба Компилятор будет трактовать операнды 320 и 240 как имеющие тип int? Как uint32_t. А вот что такое uint32_t - надо смотреть где это тип определяется. Интуитивно можно догадаться, что это некий UNSIGNED тип. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
baralgin 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба А что,если так?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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 65 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба Имеем код 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба Но я бы сделал так: а я бы просто uint32_t a = 320L * 240L; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба На самом деле смысл там такой - если все операнды помещаются в int, то операция и производится как int (а если калибр операндов меньше, чем int, они к нему приводятся, это называется integer promotion) . Калибр int'а, естественно, зависит от платформы. Соответственно, оба операнда (320 и 240) в int помещаются и операция производится в калибре int, только вот результат произведения не лезет. Достаточно указать, что один из операндов 32хбитный и все будет хорошо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба Ну 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; Как вообще по стандарту? Что сказано о таких случаях? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andron_ 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба Ну так а на другом компиляторе, где long будет 64бит - будет уже оверхед? в компиляторов для настольных ПК 64 бита - это long long)) а long = int = 32 бита... uint32_t a = 320 * 240; компилятор будет рассматривать обе константы как типа int. если int 16 бит - будет переполнение... если операндов несколько... компилятор определяет самый "длинный" или "сложный" тип среди операндов и все приводит к нему. После выполнения операции он начинает думать, как его привести к переменной, которой ему нужно присвоить результат. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба Ну так а на другом компиляторе, где long будет 64бит - будет уже оверхед? Не будет оверхеда, так как результат все равно обкоцают до uint32, и оптимизатор, понимая это, воткнет константу наиболее оптимального для платформы типа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба в компиляторов для настольных ПК 64 бита - это long long))oops, чё-то я малёк запутался уже :) если операндов несколько... компилятор определяет самый "длинный" или "сложный" тип среди операндов и все приводит к нему. После выполнения операции он начинает думать, как его привести к переменной, которой ему нужно присвоить результат.Вооот. Вот это то, что хотелось знать. СПАСИБО! :) А ещё вопросик: если в выражении есть скобки это что-то меняет? Я имею ввиду выбирать самый длинный и сложный он будет не смотря на скобки? А то был у меня один странный случай, я там вроде указал самого жирного, а чё-т не работало, пока всёх явно к 32бит типу не привёл.... Щас уже не вспомню толком где это было... Показал бы конкретное выражение. Там были скобки, точно помню. Ещё тогда подумал, что что-то я не понял в этой жизни :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 28 ноября, 2009 Опубликовано 28 ноября, 2009 (изменено) · Жалоба если операндов несколько... компилятор определяет самый "длинный" или "сложный" тип среди операндов Неправильно. В указанном порядке (например, для операции умножения - сдева направо) вычисляются выражения над двумя операндами. И, соответственно, promotion выполняется для первой пары операндов. К вычислению второго умножения приходит в качестве левого операнда то, что получилось в результате умножения (с наиболее "старшим" типом из операндов), затем делается "продвижение" среди пары ыторых. То есть, в выражении 2 * 3L * 4.0 сперва 2 делается long, потом умножается на 3, затем результат делается float и умножается на 4. Скобки, естественно, меняют порядок вычислений. Изменено 28 ноября, 2009 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andron_ 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба гмммммм... ну ваще-то да... как-то оно так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 141 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба А вот что такое 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); И для каждого из них отдельно применяются правила неявных приведений типов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 · Жалоба Но я бы сделал так: ....Так будет корректней: static const uint32_t X_SIZE = 320UL; static const uint32_t Y_SIZE = 240UL; uint32_t a = X_SIZE * Y_SIZE; Без статика возможны "игры разума" компиляторов... И ещё, никакого оверхеда быть не может, т.к. константные выражения вычислятся при компиляции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Pjotar 0 28 ноября, 2009 Опубликовано 28 ноября, 2009 (изменено) · Жалоба 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: На случай, если они перестанут быть константными или поучаствуют ещё-где-нибудь. Изменено 28 ноября, 2009 пользователем Злодей Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться