Недавно столкнулся с такой проблемой - надо было записать в кусок памяти, который имел тип char* переменную типа DWORD.char buf[BUF_LEN];
DWORD dw;я довольно долго соображал, как это сделать, чтобы компилятор не ругался на нестандартное приведение типов и в конце концов у меня получилось так:
*((DWORD*)buf) = dw;
На такую форму приведения типов компилятор наконец ругаться перестал, однако меня терзают смутные сомнения в правильности моих действий.
Хотелось бы узнать ваше мнение по этому вопросу, а также какие у вас возникали трудности при произведении подобных заковыристых операций и как вы их обошли.
>char buf[BUF_LEN];
>DWORD dw;
>
>я довольно долго соображал, как это сделать, чтобы компилятор не ругался на
>нестандартное приведение типов и в конце концов у меня получилось так:
>
>
> *((DWORD*)buf) = dw;
Прям духом старины повеяло. В Internet по поводу таких преобразований горы
материала, Вам стоит почитать, если есть время. О переносимости такого
кода даже на другой компилятор, думаю, мечтать не стоит. Но для чистого C
это обычная практика, разумеется.>Хотелось бы узнать ваше мнение по этому вопросу, а также какие у
>вас возникали трудности при произведении подобных заковыристых операций и как вы
>их обошли.
Я сталкиваюсь с подобными преобразованиями (на C++, естественно, -- на
чистом C программа с необходимостью так делать -- кошмар холожной январской ночи), когда приходится общаться с C библиотеками, с их
read() и write(), например.
В самом печальном случае приходится делать так:
char buf[BUF_SIZE];
u_int64_t dw;
// ...
u_int64_t* pbuf= reinterpret_cast<u_int64_t*>( buf );
(*pbuf)= dw;
Если пишешь в кусок памяти, наверно логично использовать memcpy.
Я использую OpenWatcom, но обязательно попробую под bcc32 и gcc - меня напугали ваши слова о непереносимости. А использовать функцию для того, что можно сделать простой пересылкой reg -> mem у меня рука не поднимается.
>Я использую OpenWatcom, но обязательно попробую под bcc32 и gcc - меня напугали ваши слова о непереносимости. А использовать функцию для того, что можно сделать простой пересылкой reg -> mem у меня рука не поднимается.такой корявый каст вместо memcpy() ? ну вы сам себе злобный буратино.
ps: Аннушка уже разлила подсолнечное масло (c)..
// wbr
по моему ничего корявого - нормальная практика программирования на Cесли из-за каждого DWORD'а memcpy вызывать - программы "летать" не будут (правда, если не быть осторожным, они будут лететь :))
Непереносимого здесь тоже ничего нет - все соответствует ANSI C, любой компилятор ничего против не скажет.
>по моему ничего корявого - нормальная практика программирования на C
>
>если из-за каждого DWORD'а memcpy вызывать - программы "летать" не будутВ пристойных компилятораь memcpy сделан как inline asm, и агрессивно оптимизирован. За скорость бояться нечего.
>(правда,
>если не быть осторожным, они будут лететь :))
>Непереносимого здесь тоже ничего нет - все соответствует ANSI C, любой компилятор
>ничего против не скажет.
Сказать не скажет, а вот buf может выровняет, а может и нет. Вот вам и address error (на мотороле). Или лишние циклы шины (на интеле).
>Непереносимого здесь тоже ничего нет - все соответствует ANSI C, любой компилятор
>ничего против не скажет.В какой части ANSI стандарта разрешается приведение (char*) к (DWORD*)?
>Я использую OpenWatcom, но обязательно попробую под bcc32 и gcc - меня
>напугали ваши слова о непереносимости. А использовать функцию для того, что
>можно сделать простой пересылкой reg -> mem у меня рука не поднимается.
Тут, всё-таки дело именно в "корявости каста" -- исправить это вряд ли
возможно. И делать memcopy() не многим более небезопасно, чем присваивать.
Кстати, надо бы ещё посмотреть, как gcc это всё оптимизирует.
Правильный путь, думаю, -- задаться вопросом, что делается дальше с этим
buf. Зачем потребовалось преобразовать в массив символов, нельзя ли иначе?
Это все хреновый мелкософт и функции подсистемы работы с реестром. Сам бы я ни за что такого барахла не написал. Конечно, этот форум не про мелкософтовские приблуды, однако в данном случае меня интересовало именно приведение типов.
А где там такое нужно? Что-то ты пытаешся не то накрутить?
>А где там такое нужно? Что-то ты пытаешся не то накрутить?Функция перебора значений реестра использует указатель на буфер, чтобы туда записать значение. Тип полученного значения возвращается другим указателем. Почему они это так сделали - это их спросите.
Кстати, gcc ругается на такой фрагмент кода, но программу компилит. А работает она неправильно - printf выдает совершенно левые значения.
Интересно, а как бы вы написали код для подобной работы. Допустим у нас есть какая-то база, содержащая разнотипные значения в одном месте. И нам надо их перебрать, каким-то образом возвращая пользователю результат. Хотелось бы узнать ваши мысли по этому поводу.
>Функция перебора значений реестра использует указатель на буфер, чтобы туда записать значение.Если у тебя указатель на буфер, откуда DWORD берется? Может надо преобразование в другую сторону?
>Тип полученного значения возвращается другим указателем. Почему они это так сделали
>- это их спросите.Наверно в C по-другому сложно.
>Кстати, gcc ругается на такой фрагмент кода, но программу компилит. А работает
>она неправильно - printf выдает совершенно левые значения.Можешь показать код?
>Интересно, а как бы вы написали код для подобной работы. Допустим у
>нас есть какая-то база, содержащая разнотипные значения в одном месте. И
>нам надо их перебрать, каким-то образом возвращая пользователю результат. Хотелось бы
>узнать ваши мысли по этому поводу.В C либо конструкция switch-case, либо ручная поддержка какой-нибудь структуры отображения тип-обработчик.