URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 3665
[ Назад ]

Исходное сообщение
"Трудности при приведении одного типа к другому"

Отправлено dimus , 30-Ноя-04 11:02 
Недавно столкнулся с такой проблемой - надо было записать в кусок памяти, который имел тип char* переменную типа DWORD.

char buf[BUF_LEN];
DWORD dw;

я довольно долго соображал, как это сделать, чтобы компилятор не ругался на нестандартное приведение типов и в конце концов у меня получилось так:

  *((DWORD*)buf) = dw;

На такую форму приведения типов компилятор наконец ругаться перестал, однако меня терзают смутные сомнения в правильности моих действий.
Хотелось бы узнать ваше мнение по этому вопросу, а также какие у вас возникали трудности при произведении подобных заковыристых операций и как вы их обошли.


Содержание

Сообщения в этом обсуждении
"Трудности при приведении одного типа к другому"
Отправлено SergeiZz , 30-Ноя-04 13:08 
>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;


"Трудности при приведении одного типа к другому"
Отправлено Аноним , 01-Дек-04 08:10 
Если пишешь в кусок памяти, наверно логично использовать memcpy.

"Трудности при приведении одного типа к другому"
Отправлено dimus , 01-Дек-04 13:43 
Я использую OpenWatcom, но обязательно попробую под bcc32 и gcc - меня напугали ваши слова о непереносимости. А использовать функцию для того, что можно сделать простой пересылкой reg -> mem у меня рука не поднимается.

"Трудности при приведении одного типа к другому"
Отправлено klalafuda , 01-Дек-04 15:22 
>Я использую OpenWatcom, но обязательно попробую под bcc32 и gcc - меня напугали ваши слова о непереносимости. А использовать функцию для того, что можно сделать простой пересылкой reg -> mem у меня рука не поднимается.

такой корявый каст вместо memcpy() ? ну вы сам себе злобный буратино.

ps: Аннушка уже разлила подсолнечное масло (c)..

// wbr


"Трудности при приведении одного типа к другому"
Отправлено redalert , 01-Дек-04 20:33 
по моему ничего корявого - нормальная практика программирования на C

если из-за каждого DWORD'а memcpy вызывать - программы "летать" не будут (правда, если не быть осторожным, они будут лететь :))
Непереносимого здесь тоже ничего нет - все соответствует ANSI C, любой компилятор ничего против не скажет.



"Трудности при приведении одного типа к другому"
Отправлено vnp , 01-Дек-04 21:21 
>по моему ничего корявого - нормальная практика программирования на C
>
>если из-за каждого DWORD'а memcpy вызывать - программы "летать" не будут

В пристойных компилятораь memcpy сделан как inline asm, и агрессивно оптимизирован. За скорость бояться нечего.

>(правда,
>если не быть осторожным, они будут лететь :))
>Непереносимого здесь тоже ничего нет - все соответствует ANSI C, любой компилятор
>ничего против не скажет.


Сказать не скажет, а вот buf может выровняет, а может и нет. Вот вам и address error (на мотороле). Или лишние циклы шины (на интеле).


"Трудности при приведении одного типа к другому"
Отправлено Murr , 02-Дек-04 18:37 
>Непереносимого здесь тоже ничего нет - все соответствует ANSI C, любой компилятор
>ничего против не скажет.

В какой части ANSI стандарта разрешается приведение (char*) к (DWORD*)?


"Трудности при приведении одного типа к другому"
Отправлено SergeiZz , 02-Дек-04 19:07 
>Я использую OpenWatcom, но обязательно попробую под bcc32 и gcc - меня
>напугали ваши слова о непереносимости. А использовать функцию для того, что
>можно сделать простой пересылкой reg -> mem у меня рука не поднимается.
Тут, всё-таки дело именно в "корявости каста" -- исправить это вряд ли
возможно. И делать memcopy() не многим более небезопасно, чем присваивать.
Кстати, надо бы ещё посмотреть, как gcc это всё оптимизирует.
Правильный путь, думаю, -- задаться вопросом, что делается дальше с этим
buf. Зачем потребовалось преобразовать в массив символов, нельзя ли иначе?


"Трудности при приведении одного типа к другому"
Отправлено dimus , 03-Дек-04 09:32 
Это все хреновый мелкософт и функции подсистемы работы с реестром. Сам бы я ни за что такого барахла не написал. Конечно, этот форум не про мелкософтовские приблуды, однако в данном случае меня интересовало именно приведение типов.

"Трудности при приведении одного типа к другому"
Отправлено Аноним , 03-Дек-04 10:04 
А где там такое нужно? Что-то ты пытаешся не то накрутить?

"Трудности при приведении одного типа к другому"
Отправлено dimus , 06-Дек-04 15:13 
>А где там такое нужно? Что-то ты пытаешся не то накрутить?

Функция перебора значений реестра использует указатель на буфер, чтобы туда записать значение. Тип полученного значения возвращается другим указателем. Почему они это так сделали - это их спросите.

Кстати, gcc ругается на такой фрагмент кода, но программу компилит. А работает она неправильно - printf выдает совершенно левые значения.

Интересно, а как бы вы написали код для подобной работы. Допустим у нас есть какая-то база, содержащая разнотипные значения в одном месте. И нам надо их перебрать, каким-то образом возвращая пользователю результат. Хотелось бы узнать ваши мысли по этому поводу.


"Трудности при приведении одного типа к другому"
Отправлено Аноним , 07-Дек-04 07:15 
>Функция перебора значений реестра использует указатель на буфер, чтобы туда записать значение.

Если у тебя указатель на буфер, откуда DWORD берется? Может надо преобразование в другую сторону?

>Тип полученного значения возвращается другим указателем. Почему они это так сделали
>- это их спросите.

Наверно в C по-другому сложно.

>Кстати, gcc ругается на такой фрагмент кода, но программу компилит. А работает
>она неправильно - printf выдает совершенно левые значения.

Можешь показать код?

>Интересно, а как бы вы написали код для подобной работы. Допустим у
>нас есть какая-то база, содержащая разнотипные значения в одном месте. И
>нам надо их перебрать, каким-то образом возвращая пользователю результат. Хотелось бы
>узнать ваши мысли по этому поводу.

В C либо конструкция switch-case, либо ручная поддержка какой-нибудь структуры отображения тип-обработчик.