Russian Qt Forum

Программирование => С/C++ => Тема начата: Vld2 от Декабря 11, 2006, 23:26



Название: Можно ли преобразовать struct в const char*?
Отправлено: Vld2 от Декабря 11, 2006, 23:26
Можно ли преобразовать struct (или указатель на структуру) в const char*?


Название: Можно ли преобразовать struct в const char*?
Отправлено: Dendy от Декабря 11, 2006, 23:32
А Qt как ето касается?
Вообще всё можно, но только складьІвается мнение, что здесь ошибка на етапе проектирования. Какая задача-то?


Название: Можно ли преобразовать struct в const char*?
Отправлено: Вячеслав от Декабря 12, 2006, 00:59
загнать структуру куда-нибудь ? и это куда-нибудь хочет const char* на входе?
Перегнать через void * ..... но не красиво и грабли кладем .....хотя работать будет..
Код:

struct a { char c;};
a *ptr;
const char *cPtr= (const char*)(void *)ptr;


Название: Можно ли преобразовать struct в const char*?
Отправлено: Admin от Декабря 12, 2006, 09:04
вы еще про выравнивание структуры в памяти не забывайте


Название: Можно ли преобразовать struct в const char*?
Отправлено: QCasper от Декабря 12, 2006, 14:40
Цитата: "Вячеслав"
загнать структуру куда-нибудь ? и это куда-нибудь хочет const char* на входе?
Перегнать через void * ..... но не красиво и грабли кладем .....хотя работать будет..
Код:

struct a { char c;};
a *ptr;
const char *cPtr= (const char*)(void *)ptr;


Чисто майкрософтовский подход ;)
И потом, даже если это "куда-нибудь" хочет на входе чар пойнтер, представляю что оно вывалит на выходе, если передать ему структуру :D


Название: Можно ли преобразовать struct в const char*?
Отправлено: Steven_Orko от Декабря 12, 2006, 22:22
Цитата: "Admin"
вы еще про выравнивание структуры в памяти не забывайте

присоединяюсь, а вообще есть reinterpret_cast


Название: Можно ли преобразовать struct в const char*?
Отправлено: Vld2 от Декабря 12, 2006, 23:29
Виноват, вернее надо преобразовать struct в const void*.


Название: Можно ли преобразовать struct в const char*?
Отправлено: Вячеслав от Декабря 13, 2006, 00:01
Цитата: "QCasper"
Цитата: "Вячеслав"
загнать структуру куда-нибудь ? и это куда-нибудь хочет const char* на входе?
Перегнать через void * ..... но не красиво и грабли кладем .....хотя работать будет..
Код:

struct a { char c;};
a *ptr;
const char *cPtr= (const char*)(void *)ptr;


Чисто майкрософтовский подход ;)
И потом, даже если это "куда-нибудь" хочет на входе чар пойнтер, представляю что оно вывалит на выходе, если передать ему структуру :D

Гы ;) Хош покажу серьезную железяку продающуюся за неслабые килоевры(итальянского производства) хде обмен сообщениями между частями комплекса построен именно так ;)
ie первое поле структуры - тип,далее размер , а дальше - че бог на
Собственно для конкретных реализаций IMHO это возможный вариант работы ... но грабли уже лежат .... Хотя - "глупый наступает на грабли дабы получить по лбу, а умный - чтоб их поднять ;) " (c) непомню
И кстати- подход IBM'овский ;) времен 360-ых ;)


Название: Можно ли преобразовать struct в const char*?
Отправлено: bigirbis от Декабря 13, 2006, 10:48
Если не ошибаюсь, такие вещи в плюсах решаются наследованием. А такой подход еще с С растет.


Название: Можно ли преобразовать struct в const char*?
Отправлено: Вячеслав от Декабря 14, 2006, 00:31
ПОдход имеет ноги более ранние чем С ;) Временами имеет место быть так-как плюсов нема,а С есть .... В общем - каждый сходит с ума по своему :(
Ради хохмы - тут одни вумники железку свою притаскивали ( типа дафайте дружить ) - так вот - у них обмен однокристалки с компом идет на скорости 300 бод ;) причем 1) сам кристалл летает на 7.32 Mhz 2) обмен построен на ХМL с кучей рющечек в виде namespac'ов и dtd - конфигурация заливалась примерно 4 минуты :( 3) Самое веселое :( IHMO парсер XML занимает 80% кода ;)) Так-что вот ;)


Название: Можно ли преобразовать struct в const char*?
Отправлено: Vld2 от Декабря 14, 2006, 07:38
Конвертация прошла успешна, за исключением того что в char записывает лишний символ.
struct mine
{ int i;
   char[50];
}
Посылаю например "qt", а получаю "qtA" , где А - любой символ. Бывает дописывает даже 2 или 3 символа. Хотя посылаемый и получаемый размер одинаков. В чем может быть проблема? И как выравнивать структуру в памяти.


Название: Можно ли преобразовать struct в const char*?
Отправлено: Вудруф от Декабря 14, 2006, 07:49
В таком варианте вам точно надо помнить про выравнивание.
Про \0 не забыли?


Название: Можно ли преобразовать struct в const char*?
Отправлено: Vld2 от Декабря 14, 2006, 22:18
Вудруф, Понятно что в конец чаровского массива дописывает \0. Но как это дело можно выровнять?


Название: Можно ли преобразовать struct в const char*?
Отправлено: bigirbis от Декабря 14, 2006, 22:43
Выравнивание всегда происходит в большую сторону и нуль никуда не денется, если он там был


Название: Можно ли преобразовать struct в const char*?
Отправлено: Вудруф от Декабря 15, 2006, 08:47
Приведи код


Название: Можно ли преобразовать struct в const char*?
Отправлено: Vld2 от Декабря 18, 2006, 21:19
Код работает под виндой, для линуха небольшие исправления в сетевой части.


Название: Можно ли преобразовать struct в const char*?
Отправлено: Вудруф от Декабря 19, 2006, 08:11
Receive.cpp
Код:

char *Ptr = new char; //выделили один символ из кучи (указатель Ptr)
struct black_ice          //объявляем структуру, имеющую размер не менее 1002-х байт
{
  char str[MAX_LEN];
  short int  len;
};

black_ice* ptr= new black_ice;  //теперь выделяем эти самые 1002 байта из кучи (указатель ptr)
ptr = (black_ice*)(void*)Ptr;  //Оп-па! Ошибка! Мы присваиваем указателю ptr новый адрес, указывающий на место, где выделен всего 1 (один!) байт, а пользуемся аж 1002-мя. Иными словами, не гарантируется, что 1001 байт не затрётся в другом месте программы.


Надеюсь, всё понятно?

добавлено спустя 13 минут:

 Ну и к тому же, налицо утечка памяти. В receive.cpp это black_ice (1002 байта потеряно), в send.cpp это char (один байт).
Зачем вообще его выделять из кучи, для указателя вовсе не требуется инициализатор.

Поскольку единственное преобразование в send.cpp, это send (sock, Ptr2,ptr2->len, 0)), то вообще не имеет смысла определять новый указатель. Делаем так:
Код:
send (sock, ptr2->str, ptr2->len, 0);


Аналогично и в receive.cpp. Тут вообще не надо преобразовывать указатель на структуру к char *.
Далее, если действительно при вызове какой-то функции нужно преобразовывать указатели, то и делай это в месте вызова, пользуясь cast-стилем приведения.

P.S. Действительно, а причём здесь Qt?


Название: Можно ли преобразовать struct в const char*?
Отправлено: Vld2 от Декабря 20, 2006, 20:03
Вудруф,
Цитировать

Зачем вообще его выделять из кучи, для указателя вовсе не требуется инициализатор.

По другому в этой программе не пашет.
Цитировать

send (sock, ptr2->str, ptr2->len, 0);

не понял на счёт ptr2->str, Мне нужно передать структуру ( то есть поля int и char). Как можно обойтись только ptr2->str?
Цитировать

P.S. Действительно, а причём здесь Qt?

На Qt графическая часть, пока до неё не дошел.
Цитировать
char buf[1];
strcpy(buf, "123456789");

Самое интересное что в buf будет лежать 123456789, хотя он расчитан для 2 элементов. Не усекается почемуто.
Код работает, но возможны утечки памяти.


Название: Можно ли преобразовать struct в const char*?
Отправлено: Dendy от Декабря 20, 2006, 21:21
Мне вот одного непонятно...
На кой чёрт юзать помесь Си с плюсами и WinAPI, если гуёвая часть всё равно на Qt. Qt Desktop Edition содержит в себе Network. Так почему бьІ не заюзать вьІсокоуровневьІе QTcpSocket, QDataStream, QByteArray и прочие елементарньІе классьІ для работьІ с сетью? Код получился бьІ в три раза короче, в 5 раз понятней для любого китайца и в N (где N стремится к M) функциональней. А проблемьІ с "возможны утечки памяти" отпали бьІ сами собой.


Название: Можно ли преобразовать struct в const char*?
Отправлено: Вудруф от Декабря 20, 2006, 21:47
Так, поехали:
Цитировать
По другому в этой программе не пашет.

Не аргумент! Ошибка в другом месте, иначе это приводит к работоспособности только здесь и сейчас.
Цитировать
Мне нужно передать структуру ( то есть поля int и char). Как можно обойтись только ptr2->str?

Тебе, похоже, нужно передать только строку? Зачем в этом случае передавать всю структуру?
Далее, если тебе нужно передать действительно класс, то делается это так:
Код:
send (sock, static_cast <void *> (ptr), sizeof (black_ice), 0);

Где ptr - указатель на структуру.

Но и это неправильно! Ты не можешь быть уверенным, что на клиенте структура будет в памяти представлена таким же образом. Иными словами, ты сам должен придумать формат обмена, и заполнять передаваемый буфер ручками.
Обычно такой гемор не нужен, так что делают обёртки (см. ООП).

Цитировать
На Qt графическая часть, пока до неё не дошел.

Вот когда дошёл бы, тогда и писал бы на разделе Qt. А такие вопросы надо было задавать в разделе C++.
Или ты собрался все вопросы задавать в одной теме? Тебе никто не будет тогда отвечать.

Цитировать
char buf[1];
strcpy(buf, "123456789");
Самое интересное что в buf будет лежать 123456789, хотя он расчитан для 2 элементов. Не усекается почему-то.

Логично, чёрт побери. strcpy объявлена так:
Код:
void strcpy (char *, const char *)

Ты копируешь в память по указателю. Откуда компилятор должен знать размер памяти, в которую ты копируешь?
Не надо говорить про то, что ты объявил массив. Объявлением массива ты всего лишь выделяешь локальную память. Если бы встроенные массивы отслеживали длину, то здесь бы терялась производительность.
Если нужны расширяемые контейнеры - смотри в сторону STL. Например, std::vector.

Цитировать
Код работает, но возможны утечки памяти.

Это тебе не Java, здесь сборки мусора нет. Учись писать сразу правильно.

По твоему коду:
RECEIVE.cpp
Код:
char *Ptr = new char[sizeof(black_ice)];

Ещё раз говорю, просто
Код:
char * Ptr;
Аналогично и в SEND.CPP

Код:
char *Ptr = new char[sizeof(black_ice)];
black_ice* ptr= new black_ice;
memset(ptr->str,0,81);    
ptr = (black_ice*)(void*)Ptr;

Мы выделяем память, инициализируем её, а потом просто выбрасываем!
Может, надо
Код:
Ptr = (black_ice*)(void*)ptr;

Вот ещё один пример, что переменные надо нормально называть. Впрочем, в данном случае инициализация вообще не нужна.

Код:
QString tut;

Зачем?

У тебя в коде слишком много лишнего. Лишние указатели, лишние строки (память, память!), лишние действия.
Извини, но на работе мы с сотоварищами просто по столу катались. Ты уж не обижайся.

P.S. Ей-богу, прочитай сначала любую книгу по Си++. Лучше всего - Страуструпа. А ты и Си толком не знаешь.
P.P.S. Если ты собрался GUI делать на Qt, то зачем тогда пользоваться низкоуровневыми средствами для работы с сетью?
P.P.P.S. Глупых вопросов больше не задавай. Как говорят, RTFM! Хотя бы чего-нибудь по Си++...


Название: Можно ли преобразовать struct в const char*?
Отправлено: Vld2 от Декабря 21, 2006, 21:17
Вудруф,
Цитировать

Ты не можешь быть уверенным, что на клиенте структура будет в памяти представлена таким же образом. Иными словами, ты сам должен придумать формат обмена, и заполнять передаваемый буфер ручками.

А если я делаю клиент и сервер, то соответсвенно сам и размещаю структуру. проблем не должно быть.
Цитировать

У тебя в коде слишком много лишнего. Лишние указатели, лишние строки (память, память!), лишние действия.
Не спорю некотрые факты передернул.
Цитировать

Если ты собрался GUI делать на Qt, то зачем тогда пользоваться низкоуровневыми средствами для работы с сетью?
На одном qt нельзя останавливаться, должен быть всесторонний охват в смежных языках. Сегодня на Qt работаешь, а завтра неизвестно на чем?
Цитировать

send (sock, static_cast <void *> (ptr), sizeof (black_ice), 0);

тут или два раза надо использовать static_cast, так как нам нужен char * (для wind).  И намного ли хуже использовать обычное приведение (void *), статическое ?


Название: Можно ли преобразовать struct в const char*?
Отправлено: Вудруф от Декабря 22, 2006, 08:17
Цитировать
А если я делаю клиент и сервер, то соответсвенно сам и размещаю структуру. проблем не должно быть.

Проблемы могут быть, т.к. ты компилируешь сервер и клиент раздельно. Чуть изменил настройки оптимизации, перешёл на другую версию компилятора - всё перестанет работать!

Цитировать
должен быть всесторонний охват в смежных языках

Qt - это не язык :) Это библиотека.
А низкоуровневые средства для работы с сетью применять не обязательно. Уже существует достаточно много высокоуровневых обёрток над сетевым кодом.

Цитировать
Сегодня на Qt работаешь, а завтра неизвестно на чем?

А завтра изучишь. Невозможно изучить всё, лучше хорошо знать что-то одно. Если умеешь программировать, изучить новые библиотеки/языки программирования не составит большой проблемы.

Цитировать
И намного ли хуже использовать обычное приведение (void *) вместо статического

Приведение требуется достаточно редко. Именно поэтому в Си++ сделан такой "неудобный" стиль приведения.
Используя Си-стиль (со скобочками), нельзя быть уверенным, какое именно приведение будет выбрано (static, reinterpret...).

Цитировать
нам нужен char *

Тут я смотрел man send, а там указатели void * :)
Да, в таком случае действительно будет два static_cast. И такая "неудобная" запись будет обращать внимание на потенциально опасный участок кода.


Название: Можно ли преобразовать struct в const char*?
Отправлено: Vld2 от Декабря 25, 2006, 11:32
Вудруф,
Цитировать

Проблемы могут быть, т.к. ты компилируешь сервер и клиент раздельно. Чуть изменил настройки оптимизации, перешёл на другую версию компилятора - всё перестанет работать!

Если в клиенте задать структуру:
struct
{ char
 int
}
а на сервере:
str
{int
char} , то конечно не пашет правильно.
Но я все-таки вначале ложу большее по размеру значение, а потом меньшее. В итоге выравнивания памяти не происходит. Нет выравнивания, нет проблем. Ради интереса проверю этот код ещё и под solaris и linux.
Цитировать

Qt - это не язык  Это библиотека.
А низкоуровневые средства для работы с сетью применять не обязательно. Уже существует достаточно много высокоуровневых обёрток над сетевым кодом.

Начинать надо снизу, чтобы прийти вверх.
Цитировать

Используя Си-стиль (со скобочками), нельзя быть уверенным, какое именно приведение будет выбрано (static, reinterpret...).

В доках написано, что static и reinterpret ничего не гарантируют. Зачем они нужны если нет гарантии?


Название: Можно ли преобразовать struct в const char*?
Отправлено: Dendy от Декабря 25, 2006, 12:20
Задашь тьІ одинаковую структуру, а размер int на системах будет стоять разньІй. Дальше - вьІравнивание там 1 байт, здесь 8 байт. А для полного екстаза скомпилируй всё ето под PowerPC на Макинтоше, где подяток байт BigEndian, в структуре получишь лапшу. И будешь долго искать какие костьІли ещё прикрутить.

Задачу нужно решать максимально еффективньІм способом. А не по принципу: заюзаю здесь библиотеку А, потому что она пригодится в другом проекте. А в другом проекте заюзать всё таки Б, потому что неплохо изучить для применения в проекте ЬІ. И так далее. Задачи нужно решать. Чтоб работали и есть не просили.

Когда понадобится - тогда и изучишь. На примере "Hello, World!". Конечно же если то, что тьІ сейчас делаешь и есть изучение сети, то вопросов нет. Тренируйся наступать на грабли.

Но советую посмотреть в сторону QDataStream, потому как содержит правильную идеологию и реализацию передачи данньІх между платформами.


Название: Можно ли преобразовать struct в const char*?
Отправлено: Вудруф от Декабря 25, 2006, 12:31
Кроме того, мне кажется, что компиляторы могут менять порядок следования членов в структуре/классе...


Название: Можно ли преобразовать struct в const char*?
Отправлено: kotofay от Декабря 25, 2006, 13:41
Цитата: "Vld2"
Конвертация прошла успешна, за исключением того что в char записывает лишний символ.
struct mine
{ int i;
   char[50];
}
Посылаю например "qt", а получаю "qtA" , где А - любой символ. Бывает дописывает даже 2 или 3 символа. Хотя посылаемый и получаемый размер одинаков. В чем может быть проблема? И как выравнивать структуру в памяти.


Попробуй перед использованием массива очистить память.