|
IAR: вопрос типа "глазам не верю" |
|
|
|
Jan 20 2012, 07:08
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Неужели правда в IAR в результате такого кода Код volatile unsigned char v1 = 1; volatile unsigned char v2 = 255; volatile unsigned char v3 = 2;
if (v1 == (v2+v3)) PORTB = 0; else PORTB = 1; в PORTB действительно будет выведен 0? наткнулся на тему на другом форуме - говорят, таки да...
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jan 20 2012, 07:12
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(ARV @ Jan 20 2012, 11:08)  Неужели правда в IAR в результате такого кодав PORTB действительно будет выведен 0? наткнулся на тему на другом форуме - говорят, таки да... А почему бы и нет? 255 + 2 = 1; 1 == 1; PORTB = 0;
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Jan 20 2012, 07:48
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(ARV @ Jan 20 2012, 11:39)  а как же быть с тем, что по стандарту языка Си в выражениях char автоматически преобразуется к int? Озвучьте номер стандарта, где такое описано. Код #if !defined(__STDINT_H_) #define __STDINT_H_
/* * ISO C99: 7.18 Integer types <stdint.h> */
#ifndef __int8_t_defined #define __int8_t_defined typedef signed char int8_t; typedef int int16_t; typedef long int int32_t; __extension__ typedef long long int int64_t;
typedef unsigned char uint8_t; typedef unsigned int uint16_t; typedef unsigned long int uint32_t; __extension__ typedef unsigned long long int uint64_t; # endif Это в mspgcc. Не думаю, что WinAVR сильно отличается. Из другого места: Код #ifndef __INTTYPES_H_ #define __INTTYPES_H_
#ifndef __int8_t_defined #define __int8_t_defined /* Use [u]intN_t if you need exactly N bits. XXX - doesn't handle the -mint8 option. */
typedef signed char int8_t; typedef unsigned char uint8_t;
typedef int int16_t; typedef unsigned int uint16_t;
typedef long int32_t; typedef unsigned long uint32_t;
typedef long long int64_t; typedef unsigned long long uint64_t; #endif Правда, со сложением char-ов тоже какая-то засада была, при вычислении контрольной суммы. По-моему, помогла маска, наложенная на старший байт результата.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Jan 20 2012, 07:59
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
я не супер-знаток стандарта, и тем более его пунктов и подпунктов, но точно помню, что в нем сказано буквально следующее: при вычислении выражений переменные типа char и unsigned char всегда неявно преобразуются к типу int и unsigned int соответственно. именно результат такого преобразования я наблюдаю в WinAVR, который, если не ошибаюсь, декларирует полное соответствие стандарту Си. более того, если упомянутый ранее код слегка видоизменить, то он работает именно так, как вы и говорите: Код volatile unsigned char v1 = 1; volatile unsigned char v2 = 255; volatile unsigned char v3 = 2;
unsigned char v4; v4 = v2 + v3; if (v1 == v4) PORTB = 0; else PORTB = 1; в данном случае на самом деле v4 будет содержать значение 0x01, хотя результат ВЫРАЖЕНИЯ v2+v3 будет равен 0x0101; собственно, я и задал вопрос с целью разобраться в этом вопросе: жду, пока Сергей Борщ или иной специалист, хорошо знающий стандарт, даст пояснения.
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jan 20 2012, 08:14
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(ARV @ Jan 20 2012, 11:59)  я не супер-знаток стандарта, и тем более его пунктов и подпунктов, но точно помню, что в нем сказано буквально следующее: при вычислении выражений переменные типа char и unsigned char всегда неявно преобразуются к типу int и unsigned int соответственно. Ну вот теперь все встало на свои места. Спасибо за разъяснения! То, что у ИАРа своя логика, иногда противоречащая стандартам, и так известно. У меня с ним отношения не сложились, и как раз касательно if()-ов. Столько раз получал граблями в лоб, но постепенно привык. А теперь вот на GCC переполз.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Jan 20 2012, 08:22
|
Частый гость
 
Группа: Свой
Сообщений: 93
Регистрация: 13-01-12
Из: Гатчина
Пользователь №: 69 333

|
Цитата из Шилдта: Цитата Преобразования типов в выражениях
Если в выражении встречаются переменные и константы разных типов, они преобразуются к одному типу. Компилятор преобразует "меньший" тип в "больший". Этот процесс называется продвижением типов (type promotion). Сначала все переменные типов char и short int автоматически продвигаются в int. Это называется целочисленным расширением. (В С99 целочисленное расширение может также завершиться преобразованием в unsigned int.) После этого все остальные операции выполняются одна за другой, как описано в приведенном ниже алгоритме преобразования типов:
IF операнд имеет тип long double THEN второй операнд преобразуется в long double ELSE IF операнд имеет тип double THEN второй операнд преобразуется в double ELSE IF операнд имеет тип float THEN второй операнд преобразуется в float ELSE IF операнд имеет тип unsigned long THEN второй операнд преобразуется в unsigned long ELSE IF операнд имеет тип long THEN второй операнд преобразуется в long ELSE IF операнд имеет тип unsigned int THEN второй операнд преобразуется в unsigned int У вас же случай, когда переменные одинаковых типов - т.е. IAR прав.
Сообщение отредактировал sparcmaster - Jan 20 2012, 08:24
|
|
|
|
|
Jan 20 2012, 08:34
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Сергей Борщ @ Jan 20 2012, 12:22)  Да, все верно вы рассуждаете. Верно ли? Цитата из стандарта Цитата In executing the fragment char c1, c2; /* ... */ c1 = c1 + c2; the ‘‘integer promotions’’ require that the abstract machine promote the value of each variable to int size and then add the two ints and truncate the sum. Provided the addition of two chars can be done without overflow, or with overflow wrapping silently to produce the correct result, the actual execution need only produce the same result, possibly omitting the promotions. Мои знания английского языка - не ахти какие, но, по-моему, стандарт говорит, что в данном случае "promotions" можно не выполнять.
|
|
|
|
|
Jan 20 2012, 09:06
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(ARV @ Jan 20 2012, 12:49)  для варианта С ПРИСВАИВАНИЕМ переменной типа char на самом деле смысла в promotions нет - я приводил пример ранее. ИМХО, стандарт допускает не использовать promotions с переменными типа char не в зависимости от оператора (присваивание или сравнение), а от Цитата ...without overflow, or with overflow wrapping silently... Кроме того, если выражение справа вычислять отдельно (как в вашем примере), то и выполнение оператора сравнения меняет результат. Что, по-моему, слабо согласуется с "correct result", упомянутому в стандарте.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|