|
Понятие стандартного типа и тип операндов..., 16/32битный Cи компилятор. Хочу раз и на всегда уточнить. |
|
|
|
Nov 28 2009, 00:06
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Имеем код Код 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 и его длиной бывают приколы, как я понял....
--------------------
The truth is out there...
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Nov 28 2009, 04:23
|

Гуру
     
Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515

|
Цитата Компилятор будет трактовать операнды 320 и 240 как имеющие тип int? Как uint32_t. А вот что такое uint32_t - надо смотреть где это тип определяется. Интуитивно можно догадаться, что это некий UNSIGNED тип.
--------------------
On the road again (Canned Heat)
|
|
|
|
|
Nov 28 2009, 08:59
|
Частый гость
 
Группа: Участник
Сообщений: 92
Регистрация: 23-12-08
Из: Кишинёв
Пользователь №: 42 680

|
Цитата(sigmaN @ Nov 28 2009, 02:06)  А что,если так? Код 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.
|
|
|
|
|
Nov 28 2009, 09:39
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(sigmaN @ Nov 28 2009, 06:06)  Имеем код Код 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;
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Nov 28 2009, 11:03
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
На самом деле смысл там такой - если все операнды помещаются в int, то операция и производится как int (а если калибр операндов меньше, чем int, они к нему приводятся, это называется integer promotion) . Калибр int'а, естественно, зависит от платформы.
Соответственно, оба операнда (320 и 240) в int помещаются и операция производится в калибре int, только вот результат произведения не лезет. Достаточно указать, что один из операндов 32хбитный и все будет хорошо.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Nov 28 2009, 11:03
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Ну 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; Как вообще по стандарту? Что сказано о таких случаях?
--------------------
The truth is out there...
|
|
|
|
|
Nov 28 2009, 11:12
|
.NET developer
  
Группа: Свой
Сообщений: 218
Регистрация: 20-10-07
Из: Новосибирск
Пользователь №: 31 532

|
Цитата Ну так а на другом компиляторе, где long будет 64бит - будет уже оверхед? в компиляторов для настольных ПК 64 бита - это long long)) а long = int = 32 бита... uint32_t a = 320 * 240; компилятор будет рассматривать обе константы как типа int. если int 16 бит - будет переполнение... если операндов несколько... компилятор определяет самый "длинный" или "сложный" тип среди операндов и все приводит к нему. После выполнения операции он начинает думать, как его привести к переменной, которой ему нужно присвоить результат.
|
|
|
|
|
Nov 28 2009, 12:05
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Цитата в компиляторов для настольных ПК 64 бита - это long long)) oops, чё-то я малёк запутался уже  Цитата если операндов несколько... компилятор определяет самый "длинный" или "сложный" тип среди операндов и все приводит к нему. После выполнения операции он начинает думать, как его привести к переменной, которой ему нужно присвоить результат. Вооот. Вот это то, что хотелось знать. СПАСИБО!  А ещё вопросик: если в выражении есть скобки это что-то меняет? Я имею ввиду выбирать самый длинный и сложный он будет не смотря на скобки? А то был у меня один странный случай, я там вроде указал самого жирного, а чё-т не работало, пока всёх явно к 32бит типу не привёл.... Щас уже не вспомню толком где это было... Показал бы конкретное выражение. Там были скобки, точно помню. Ещё тогда подумал, что что-то я не понял в этой жизни
--------------------
The truth is out there...
|
|
|
|
|
Nov 28 2009, 12:23
|

Профессионал
    
Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634

|
Цитата если операндов несколько... компилятор определяет самый "длинный" или "сложный" тип среди операндов Неправильно. В указанном порядке (например, для операции умножения - сдева направо) вычисляются выражения над двумя операндами. И, соответственно, promotion выполняется для первой пары операндов. К вычислению второго умножения приходит в качестве левого операнда то, что получилось в результате умножения (с наиболее "старшим" типом из операндов), затем делается "продвижение" среди пары ыторых. То есть, в выражении 2 * 3L * 4.0 сперва 2 делается long, потом умножается на 3, затем результат делается float и умножается на 4. Скобки, естественно, меняют порядок вычислений.
Сообщение отредактировал Genadi Zawidowski - Nov 28 2009, 12:28
|
|
|
|
|
Nov 28 2009, 14:54
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(DpInRock @ Nov 28 2009, 06:23)  А вот что такое uint32_t - надо смотреть где это тип определяется.
Интуитивно можно догадаться, что это некий UNSIGNED тип. Этот тип определен в stdint.h, означает 32-битовое беззнаковое целое и вместе со всем содержимым stdint.h описан в стандарте C99. Цитата(sigmaN @ Nov 28 2009, 14:05)  Я имею ввиду выбирать самый длинный и сложный он будет не смотря на скобки? Еще раз уточним. Операции бывают унарные (один операнд, x = ~y), бинарные (два операнда, x = y * z) и тернарные (такая только одна: x = y ? z : i). Все выражение разбивается на эти примитивы в соответствии с приоритетом операций. Естественно, скобки влияют на приоритет. Т.е. выражение a = b * c * d - это на самом деле три выражения: tmp1 = b * c; tmp2 = tmp1 * d; operator = (a, tmp2); И для каждого из них отдельно применяются правила неявных приведений типов.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 28 2009, 20:47
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(dxp @ Nov 28 2009, 12:39)  Но я бы сделал так: .... Так будет корректней: Код static const uint32_t X_SIZE = 320UL; static const uint32_t Y_SIZE = 240UL; uint32_t a = X_SIZE * Y_SIZE; Без статика возможны "игры разума" компиляторов... И ещё, никакого оверхеда быть не может, т.к. константные выражения вычислятся при компиляции.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Nov 28 2009, 20:57
|

Частый гость
 
Группа: Участник
Сообщений: 149
Регистрация: 29-04-08
Из: Петербург
Пользователь №: 37 142

|
Код 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: На случай, если они перестанут быть константными или поучаствуют ещё-где-нибудь.
Сообщение отредактировал Злодей - Nov 28 2009, 21:05
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|