реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Пара простых вопросов, Но для меня важных
SasaVitebsk
сообщение Oct 24 2006, 19:13
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Похоже, что компилятор просматривает не отдельные инструкции, а целые фрагменты текста. Об этом говорит вспыхивающие то там то тут топики, про то что изменил порядок следования операндов или ещё что-нибудь не существенное с точки зрения алгоритма, а результирующий код увеличился либо уменьшился весьма существенно. А рекомендаций по данному вопросу нет. Да и как их дашь если это зависит от компилятора и даже от его версии. Тем не менее наверняка каждый выработал для себя такие "оптимальные конструкции". Естественно, что каждый раз не будешь их проверять, но всё же. И вот у меня два вопроса.

1) Имеется переменная 32 бита (X) и 4 байта (b0-b3). Мне необходимо занести значение b0-b3 в X. На первый взгляд напрашивается две конструкции. Хотя может я и не угадал ни разу. smile.gif
а)
X=b0;
X+=(uint32_t)b1<<8; // Или '|='
X+=(uint32_t)b2<<16;
X+=(uint32_t)b3<<24;
б)
X=b0;
X+=b1*0x100;
X+=b2*0x10000;
X+=b3*0x1000000;

2) Необходимо байт 0 многобитной переменной X занести в байт b.
При конструкции
b=X; // Компилятор выдаёт предупреждение, но выполняет правильно
Если использовать
b=X & 0xff; // То компилятор не ругается.

А как записать эффективней.
Go to the top of the page
 
+Quote Post
_artem_
сообщение Oct 25 2006, 03:41
Сообщение #2


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



1)
X = b3;
X = (X<<8) | b2;
X = (X<<8) | b1;
X = (X<<8) | b0;

2)
По моему не имеет разницы - код должен быть одинаков.


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
Joy
сообщение Oct 25 2006, 06:39
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 89
Регистрация: 28-10-05
Из: Киев
Пользователь №: 10 227



Цитата(_artem_ @ Oct 25 2006, 06:41) *
2)
По моему не имеет разницы - код должен быть одинаков.

а по-моему. код разный будет: во втором случае добавляется явно прописанная операция (хотя, возможно, она соптимизируется компилятором), в то время как в первом варианте просто перекопируется младший байт...
а результат точно одинаковый
Go to the top of the page
 
+Quote Post
Old1
сообщение Oct 25 2006, 07:21
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 697
Регистрация: 26-07-05
Из: Могилев
Пользователь №: 7 095



Цитата(SasaVitebsk @ Oct 24 2006, 22:13) *
1) Имеется переменная 32 бита (X) и 4 байта (b0-b3). Мне необходимо занести значение b0-b3 в X. На первый взгляд напрашивается две конструкции. Хотя может я и не угадал ни разу. smile.gif
а)
X=b0;
X+=(uint32_t)b1<<8; // Или '|='
X+=(uint32_t)b2<<16;
X+=(uint32_t)b3<<24;
б)
X=b0;
X+=b1*0x100;
X+=b2*0x10000;
X+=b3*0x1000000;

Если переменные (b0-b3) связаны по смыслу, то ИМХО их удобнее собрать в массив , а дальше можно сделать так:
Код

  typedef union{
  unsigned char DIM[4];
  unsigned long VAR;
  }multivar;

unsigned long X;
multivar Y={1,2,3,4};
...
X=Y.VAR;
...



Цитата
2) Необходимо байт 0 многобитной переменной X занести в байт b.
При конструкции
b=X; // Компилятор выдаёт предупреждение, но выполняет правильно
Если использовать
b=X & 0xff; // То компилятор не ругается.

А как записать эффективней.


Код
b=(unsigned char)X;
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Oct 25 2006, 09:18
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(_artem_ @ Oct 25 2006, 06:41) *
1)
X = b3;
X = (X<<8) | b2;
X = (X<<8) | b1;
X = (X<<8) | b0;


А в этом случае в результирующем коде случайно не будет сдвигов?

Просто хотелось бы получить в результате простых 4 команды mov.

Вариант с наложением массива я уже где-то спрашивал, и мне ответили, что он не коректен, так как в зависимости от реализации непонятно как компилятор хранит: младшим или старшим вперёд.

Вариант b = (uint8_t)X принимается.
Go to the top of the page
 
+Quote Post
Сергей Б
сообщение Oct 25 2006, 09:37
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 80
Регистрация: 14-04-06
Из: Russia, Orel
Пользователь №: 16 115



1) а не проще так

#define LBYTE(w) (*((byte*)&w))
#define HBYTE(w) (*(((byte*)&w)+1))
#define L2BYTE(w) (*(((byte*)&w)+2))
#define H2BYTE(w) (*(((byte*)&w)+3))

LBYTE(X) = b0;
HBYTE(X) = b1;
L2BYTE(X) = b2;
H2BYTE(X) = b3;

&w - берем адрес переменной (адрес первого байта)
((byte*)&w) - это мы говорим что значение выражения *(&w) будет иметь тип byte
далее в зависимости от нужного байта прибавляем адрес
((byte*)&w)
(((byte*)&w)+1)
...
и далее работаем с переменной *((byte*)&w)
Go to the top of the page
 
+Quote Post
Old1
сообщение Oct 25 2006, 17:51
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 697
Регистрация: 26-07-05
Из: Могилев
Пользователь №: 7 095



Цитата(SasaVitebsk @ Oct 25 2006, 12:18) *
Вариант с наложением массива я уже где-то спрашивал, и мне ответили, что он не коректен, так как в зависимости от реализации непонятно как компилятор хранит: младшим или старшим вперёд.

Не совсем понял:младшим или старшим (байтом) вперёд, в зависимости от реализации ЧЕГО? Если не сложно приведите пример, я, честно говоря, думал, что всегда первым в памяти располагается нулевой элемент массива...
Есть еще вариант, в моем примере вместо массива использовать структуру, первым в памяти будет располагаться первый член структуры (по крайней мере в ИАРЕ)...
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 25 2006, 18:12
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Old1 @ Oct 25 2006, 23:51) *
Цитата(SasaVitebsk @ Oct 25 2006, 12:18) *

Вариант с наложением массива я уже где-то спрашивал, и мне ответили, что он не коректен, так как в зависимости от реализации непонятно как компилятор хранит: младшим или старшим вперёд.

Не совсем понял:младшим или старшим (байтом) вперёд, в зависимости от реализации ЧЕГО? Если не сложно приведите пример, я, честно говоря, думал, что всегда первым в памяти располагается нулевой элемент массива...
Есть еще вариант, в моем примере вместо массива использовать структуру, первым в памяти будет располагаться первый член структуры (по крайней мере в ИАРЕ)...

В СИ вроде бы нигде и не определен порядок хранения байтов данных в памяти. Точно также как и данных в структуре. Гарантируется только, что будет соблюден порядок следования членов структуры, но не порядок их размещения в памяти. Тем более когда члены структуры имеют разный тип/размер. Особенно это касается невыровненных структур.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 25 2006, 18:25
Сообщение #9


Гуру
******

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



Цитата(SasaVitebsk @ Oct 24 2006, 22:13) *
1) Имеется переменная 32 бита (X) и 4 байта (b0-b3). Мне необходимо занести значение b0-b3 в X. На первый взгляд напрашивается две конструкции.

А как записать эффективней.
Первый вариант прекрасно компилируется в четыре mov. Второй без оптимизации может вызвать подтягивание библиотечной функции умножения. Использование "+" или " | " по моим наблюдениям на результат не влияли. 10 лет назад влияли, " | " было предпочтительней. По второму вопросу уже ответили.

А что мешает посмотреть листинг?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Oct 25 2006, 21:54
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(Сергей Борщ @ Oct 25 2006, 21:25) *
А что мешает посмотреть листинг?


Пожалуйста не думайте, что я неуважаю Ваше личное время. Учитывая, что я начинающий на Си я просматриваю листинг. Правда всё время это делать не будешь. А задаю вопрос потому что ...

Цитата(Сергей Борщ @ Oct 25 2006, 21:25) *
10 лет назад влияли, " | " было предпочтительней.


У вас накоплен большой опыт применения тех или иных конструкций. И, просто хочу им воспользоваться. Чтобы при переходе с версии на версию, с камня на камень, не вглядываться постоянно в этот листинг.

Цитата( @ Oct 25 2006, 21:25) *
#define LBYTE(w) (*((byte*)&w))
#define HBYTE(w) (*(((byte*)&w)+1))
#define L2BYTE(w) (*(((byte*)&w)+2))
#define H2BYTE(w) (*(((byte*)&w)+3))

LBYTE(X) = b0;
HBYTE(X) = b1;
L2BYTE(X) = b2;
H2BYTE(X) = b3;


До этого не додумался. Спасибо всем ответившим.

И ещё один вопрос.
Имеется структура с битовыми полями к примеру.
__no_init struct
{
uint8_t RXOFF : 1, //Буфер переполнен, загрузка приостановлена
RMaster : 1,// Контроллер в режиме "Мастер"
RLoadActKom : 1,/ Разрешена Загрузка команд в "активную зону"
Color : 3, // цвет
} Flag;

У меня почему-то не работает такая конструкция (компилятор не ругается)
Flag.Color=7;
Flag.Color--;

Что я делаю не так.
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Oct 26 2006, 06:21
Сообщение #11


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(SasaVitebsk @ Oct 26 2006, 00:54) *
Имеется структура с битовыми полями к примеру.
__no_init struct
{
uint8_t RXOFF : 1, //Буфер переполнен, загрузка приостановлена
RMaster : 1,// Контроллер в режиме "Мастер"
RLoadActKom : 1,/ Разрешена Загрузка команд в "активную зону"
Color : 3, // цвет
} Flag;

У меня почему-то не работает такая конструкция (компилятор не ругается)
Flag.Color=7;
Flag.Color--;

Что я делаю не так.

Что значит "не работает"?
Я только что проверил, всё отлично работает.
Разве что после Color : 3 надо не запятую писать, а точку с запятой.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 20:20
Рейтинг@Mail.ru


Страница сгенерированна за 0.01452 секунд с 7
ELECTRONIX ©2004-2016