Re[2]: Странный memcpy
От: BitField Украина http://lazy-bitfield.blogspot.com
Дата: 25.12.14 07:26
Оценка: +3
Здравствуйте, kov_serg, Вы писали:

_>Действительно странный. Зачем лишние команды.

_>
_>BYTE *ptr;

_>// позже, в цикле
_>*(DWORD*)ptr=123;
_>


А потом на ARM или PowerPC программа упадет, ибо не все процессоры поддерживают unaligned r/w.
Re: Странный memcpy
От: johny5 Новая Зеландия
Дата: 24.12.14 10:58
Оценка: 6 (1) +1
Здравствуйте, Lonely Dog, Вы писали:

LD>Меня он смущает. Является ли он эквивалентом следующему:

LD>
LD>BYTE *ptr;
LD>DWORD buf;

Да. Если смущает - перепиши.


LD>// позже в цикле
LD>buf = 123;
LD>memcpy(ptr, &buf, sizeof(buf));
LD>


LD>Нет ли тут UB?


Нет, т.к. результатом оператора = является l-value ссылка.
Re[5]: Странный memcpy
От: uzhas Ниоткуда  
Дата: 24.12.14 14:14
Оценка: -1 :)
Здравствуйте, smeeld, Вы писали:

S>параметр buf есть lvalue reference на buf, инфа 100%

убедил
Re[3]: Странный memcpy
От: kov_serg Россия  
Дата: 20.01.15 21:53
Оценка: -2
Здравствуйте, BitField, Вы писали:

BF>Здравствуйте, kov_serg, Вы писали:


_>>Действительно странный. Зачем лишние команды.

_>>
_>>BYTE *ptr;

_>>// позже, в цикле
_>>*(DWORD*)ptr=123;
_>>


BF>А потом на ARM или PowerPC программа упадет, ибо не все процессоры поддерживают unaligned r/w.

Вот за это надо руки отрывать тем кто пишет компиляторы C++. Почему я должен решать проблеммы
архетектуры конкретной платформы. Этой ерундой должен заниматься компилятор.
Странный memcpy
От: Lonely Dog Россия  
Дата: 24.12.14 10:49
Оценка:
Добрый день!

Есть следующий код:
BYTE *ptr;
DWORD buf;

// позже, в цикле
memcpy(ptr, &(buf = 123), sizeof(buf));


Меня он смущает. Является ли он эквивалентом следующему:
BYTE *ptr;
DWORD buf;

// позже в цикле
buf = 123;
memcpy(ptr, &buf, sizeof(buf));


Нет ли тут UB?
Re[2]: Странный memcpy
От: smeeld  
Дата: 24.12.14 11:42
Оценка:
Здравствуйте, johny5, Вы писали:

J>Нет, т.к. результатом оператора = является l-value ссылка.


buf это тоже lvalue ссылка. buf=777; func(&buf), это то же самое, что func(&(buf=777));
По крайней мере в дизассемлерном листинге, гарантирую, код в обоих случаях будет одинаковым.
Re[3]: Странный memcpy
От: uzhas Ниоткуда  
Дата: 24.12.14 13:36
Оценка:
Здравствуйте, smeeld, Вы писали:

S>buf это тоже lvalue ссылка.


утверждение не к месту и не верно. это и не lvalue и не ссылка
Отредактировано 24.12.2014 14:43 uzhas . Предыдущая версия .
Re[4]: Странный memcpy
От: smeeld  
Дата: 24.12.14 13:58
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, smeeld, Вы писали:


S>>buf это тоже lvalue ссылка.


U>утверждение не к месту и не верно. это и не lvalue и не ссылка


Если у нас есть некоторая int buf, аналог (наверно) DWORD-a, то для func(int& b) и её вызове func(buf),
параметр buf есть lvalue reference на buf, инфа 100%. И для func(int* b) и int buf, вызов func(&buf)
эквивалентен func(addressof(buf)), а addressof работает с ссылкой, и здесь, в addressof, buf есть
lvalue reference на buf, инфа 100%.
Re: Странный memcpy
От: visual_wind  
Дата: 24.12.14 14:38
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>Добрый день!


LD>Есть следующий код:

LD>
LD>BYTE *ptr;
LD>DWORD buf;

LD>// позже, в цикле
LD>memcpy(ptr, &(buf = 123), sizeof(buf));
LD>


LD>Меня он смущает. Является ли он эквивалентом следующему:

LD>
LD>BYTE *ptr;
LD>DWORD buf;

LD>// позже в цикле
LD>buf = 123;
LD>memcpy(ptr, &buf, sizeof(buf));
LD>


LD>Нет ли тут UB?


Насколько я понимаю, речь идет о чистом Си. Существенных отличий от a = b = c не заметно, только в качестве a выступает временный указатель, который инициализируется значением адреса b.

Возможно, это было сделано для какой-то хитрой оптимизации на специфической архитектуре, в которой, например, инициализация локальной переменной как-то связана (через аккумулятор или вспомогательный регистр) с взятием ее адреса без пенальти. Тогда при последовательном сохранении переменных в стек такая совмещенная инициализация даст выигрыш в сравнении с вариантом, когда мы сначала инициализируем, потом сохраняем и загружаем в аккумулятор другую переменную, теряя драгоценный контекст для взятия адреса. Другой вопрос, что сам вызов memcpy для побайтного разбиения 4-байтового числа выглядит на этом фоне оверхедом.
Re[2]: Странный memcpy
От: Lonely Dog Россия  
Дата: 24.12.14 17:01
Оценка:
Здравствуйте, visual_wind, Вы писали:

_>Насколько я понимаю, речь идет о чистом Си. Существенных отличий от a = b = c не заметно, только в качестве a выступает временный указатель, который инициализируется значением адреса b.

Нет, это C++. Просто вот так написано. Студентом
ptr на самом деле указывает на начало std::vector<BYTE>)

_>Возможно, это было сделано для какой-то хитрой оптимизации на специфической архитектуре, в которой, например, инициализация локальной переменной как-то связана (через аккумулятор или вспомогательный регистр) с взятием ее адреса без пенальти. Тогда при последовательном сохранении переменных в стек такая совмещенная инициализация даст выигрыш в сравнении с вариантом, когда мы сначала инициализируем, потом сохраняем и загружаем в аккумулятор другую переменную, теряя драгоценный контекст для взятия

адреса. Другой вопрос, что сам вызов memcpy для побайтного разбиения 4-байтового числа выглядит на этом фоне оверхедом.
Это винда. Т.ч. x64. Код выполняет сериализацию std::map<INT, std::vector<BYTE>> в TLV. И таким образом записывается размер данных. Т.е. в коде написано &(buf = it->second.size())

Короче, код правильный (судя по комментам), но дико не симпатичный. Перепишу его пожалуй
Re: Странный memcpy
От: Mr.Delphist  
Дата: 24.12.14 17:38
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>Нет ли тут UB?


Ну, Вас же не смущает код вида
if (buf=123)

или
while ((buf = 123) > 0)

А то и широко известное в узких кругах
while ( *d++ = *s++ );


Да, грязноватенько, по рукам бы за такое в продуктовом репозитории. Но... оно валидно ещё со времён бородатого plain C
Re[2]: Странный memcpy
От: Lonely Dog Россия  
Дата: 24.12.14 19:15
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>Здравствуйте, Lonely Dog, Вы писали:


LD>>Нет ли тут UB?


MD>Ну, Вас же не смущает код вида

MD>
MD>if (buf=123)
MD>

MD> или
MD>
MD>while ((buf = 123) > 0)
MD>

MD>А то и широко известное в узких кругах
MD>
MD>while ( *d++ = *s++ );
MD>


MD>Да, грязноватенько, по рукам бы за такое в продуктовом репозитории. Но... оно валидно ещё со времён бородатого plain C

Не смущает только потому, что часто такое видел в статьях. А мой пример попался в первый раз . По рукам уже некого бить, код писался очень давно.
Re: Странный memcpy
От: kov_serg Россия  
Дата: 25.12.14 06:06
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>Добрый день!


LD>Есть следующий код:

LD>
LD>BYTE *ptr;
LD>DWORD buf;

LD>// позже, в цикле
LD>memcpy(ptr, &(buf = 123), sizeof(buf));
LD>


LD>Меня он смущает. Является ли он эквивалентом следующему:

LD>
LD>BYTE *ptr;
LD>DWORD buf;

LD>// позже в цикле
LD>buf = 123;
LD>memcpy(ptr, &buf, sizeof(buf));
LD>


Действительно странный. Зачем лишние команды.
BYTE *ptr;

// позже, в цикле
*(DWORD*)ptr=123;
Re[3]: Странный memcpy
От: Lonely Dog Россия  
Дата: 16.01.15 13:07
Оценка:
Здравствуйте, BitField, Вы писали:

BF>А потом на ARM или PowerPC программа упадет, ибо не все процессоры поддерживают unaligned r/w.

Это виндовый код, живущий в сервисе. Т.ч. ARM/PowerPC не мой случай. Но все равно, спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.