sprintf()
От: Аноним  
Дата: 27.09.07 08:35
Оценка:
Всем привет!

Хочется примерно следующее:

— есть простая структура

__declspec(align(1)) struct MyStruct {
T value; // !!! T — произвольный простой тип (int, char*, pointer и т.д.)
U another_value; // !!! U — тоже простой произвольный тип, может отличаться от T
};

MyStruct s;
...
sprintf(szBuf, "%d", s); // или
sprintf(szBuf, "%X", s);

Вот так вот хотелось бы!!! Т.е. если например T unsigned short, то вывести 2 байта...

Копирующий конструктор при вызове sprintf не вызывается(?), т.к. понятия не имеет о типе (см. сигнатуру sprintf)...

P.S. Да, не хочется делать явное приведение!!!

Подскажите как лучше сделать?

Спасибо!
Re: sprintf()
От: Erop Россия  
Дата: 27.09.07 09:09
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Копирующий конструктор при вызове sprintf не вызывается(?), т.к. понятия не имеет о типе (см. сигнатуру sprintf)...


Вообще-то передача объектов в функцию с переменным числом параметров UB, но конкретно майкрософтовский компилятор делает так.
Он кладёт копии объектов в стек, а потом их разрушает.
Например, можно печатать, как строчку CString, потому, что внутри CString есть только одно поле, которое является указателем на строку (все служебные поля, вроде длины, числа владельцев и т. п. в MFC'ишной строке лежат перед буфером, в котором лежит строка)

А>P.S. Да, не хочется делать явное приведение!!!


А>Подскажите как лучше сделать?


Лучше всего объяснить зачем тебе это понадобилось и на каком языке ты пишешь...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: sprintf()
От: ajanov  
Дата: 27.09.07 09:34
Оценка:
Здравствуйте, Erop, Вы писали:

E>Вообще-то передача объектов в функцию с переменным числом параметров UB, но конкретно майкрософтовский компилятор делает так.

E>Он кладёт копии объектов в стек, а потом их разрушает.
E>Например, можно печатать, как строчку CString, потому, что внутри CString есть только одно поле, которое является указателем на строку (все служебные поля, вроде длины, числа владельцев и т. п. в MFC'ишной строке лежат перед буфером, в котором лежит строка)

А>>P.S. Да, не хочется делать явное приведение!!!


А>>Подскажите как лучше сделать?


E>Лучше всего объяснить зачем тебе это понадобилось и на каком языке ты пишешь...

А лучше всего конкретно указывать то что ты хочешь:
sprintf(szBuf, "%d", s.value);
Re: sprintf()
От: Кодт Россия  
Дата: 27.09.07 09:43
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>__declspec(align(1)) struct MyStruct {
А>  T value;  // !!! T - произвольный простой тип (int, char*, pointer и т.д.)
А>  U another_value; // !!! U - тоже простой произвольный тип, может отличаться от T
А>};

А>MyStruct s;
А>...
А>sprintf(szBuf, "%d", s); // или
А>sprintf(szBuf, "%X", s);

А>Вот так вот хотелось бы!!! Т.е. если например T unsigned short, то вывести 2 байта...

В общем виде (не специально заточенном под конкретную платформу) фокус не выйдет.
Дело в том, что,

1) Когда ты передаёшь аргументы-числа, компилятор расширяет их до int, long, long long (если это целые) и double, long double (если это вещественные).
Поэтому short всегда представлен как int. И printf об этом знает, и может как-то учитывать при переводе из двоичного числа в строку.
А в структуре short представлен как short, и что там в оставшихся двух байтах — неизвестно. (С точки зрения printf — там мусор).

Причём если платформа big endian, то value окажется в старшей (якобы ненужной) части int, а младшая часть int совпадёт со старшей частью another_value.

2) Даже если ты укажешь выравнивание структуры такое же, как у элементов стека, — всё равно зазоры структуры будут заполнены мусором.

Ну а цена трюков может оказаться сравнимой с ценой явной передачи элементов структуры.
Скажем
// traits по определению подходящего типа

template<class T> struct stacked { typedef T type; };

template<> struct stacked<char> { typedef int type; };
template<> struct stacked<short> { typedef int type; };
template<> struct stacked<signed char> { typedef int type; };

template<> struct stacked<unsigned char> { typedef unsigned int type; };
template<> struct stacked<unsigned short> { typedef unsigned int type; };

template<> struct stacked<float> { typedef double type; };

template<class T, class U>
__declspec(align(1)) struct MyStruct
{
    typename stacked<T>::type value;
    typename stacked<U>::type another_value;
};

В этом случае можно понадеяться, что
printf(fmt, s);
// то же самое, что
printf(fmt, s.value, s.another_value);

(разумеется, только в том случае, когда стек растёт в сторону убывания адресов).
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: sprintf()
От: Аноним  
Дата: 27.09.07 09:56
Оценка:
Да понятно что можно указывать прям мембер...

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

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


E>>Вообще-то передача объектов в функцию с переменным числом параметров UB, но конкретно майкрософтовский компилятор делает так.

E>>Он кладёт копии объектов в стек, а потом их разрушает.
E>>Например, можно печатать, как строчку CString, потому, что внутри CString есть только одно поле, которое является указателем на строку (все служебные поля, вроде длины, числа владельцев и т. п. в MFC'ишной строке лежат перед буфером, в котором лежит строка)

А>>>P.S. Да, не хочется делать явное приведение!!!


А>>>Подскажите как лучше сделать?


E>>Лучше всего объяснить зачем тебе это понадобилось и на каком языке ты пишешь...

A>А лучше всего конкретно указывать то что ты хочешь:
A>sprintf(szBuf, "%d", s.value);
Re[2]: sprintf()
От: Аноним  
Дата: 27.09.07 10:08
Оценка:
Спасибо большое! Думаю, затея не оправдывает себя...

Еще раз спасибо за подробное разъяснение!

Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, <Аноним>, Вы писали:


К>
А>>__declspec(align(1)) struct MyStruct {
А>>  T value;  // !!! T - произвольный простой тип (int, char*, pointer и т.д.)
А>>  U another_value; // !!! U - тоже простой произвольный тип, может отличаться от T
А>>};

А>>MyStruct s;
А>>...
А>>sprintf(szBuf, "%d", s); // или
А>>sprintf(szBuf, "%X", s);
К>

А>>Вот так вот хотелось бы!!! Т.е. если например T unsigned short, то вывести 2 байта...

К>В общем виде (не специально заточенном под конкретную платформу) фокус не выйдет.

К>Дело в том, что,

К>1) Когда ты передаёшь аргументы-числа, компилятор расширяет их до int, long, long long (если это целые) и double, long double (если это вещественные).

К>Поэтому short всегда представлен как int. И printf об этом знает, и может как-то учитывать при переводе из двоичного числа в строку.
К>А в структуре short представлен как short, и что там в оставшихся двух байтах — неизвестно. (С точки зрения printf — там мусор).

К>Причём если платформа big endian, то value окажется в старшей (якобы ненужной) части int, а младшая часть int совпадёт со старшей частью another_value.


К>2) Даже если ты укажешь выравнивание структуры такое же, как у элементов стека, — всё равно зазоры структуры будут заполнены мусором.


К>Ну а цена трюков может оказаться сравнимой с ценой явной передачи элементов структуры.

К>Скажем
К>
К>// traits по определению подходящего типа

К>template<class T> struct stacked { typedef T type; };

К>template<> struct stacked<char> { typedef int type; };
К>template<> struct stacked<short> { typedef int type; };
К>template<> struct stacked<signed char> { typedef int type; };

К>template<> struct stacked<unsigned char> { typedef unsigned int type; };
К>template<> struct stacked<unsigned short> { typedef unsigned int type; };

К>template<> struct stacked<float> { typedef double type; };

К>template<class T, class U>
К>__declspec(align(1)) struct MyStruct
К>{
К>    typename stacked<T>::type value;
К>    typename stacked<U>::type another_value;
К>};
К>

К>В этом случае можно понадеяться, что
К>
К>printf(fmt, s);
К>// то же самое, что
К>printf(fmt, s.value, s.another_value);
К>

К>(разумеется, только в том случае, когда стек растёт в сторону убывания адресов).
от модератора
От: Кодт Россия  
Дата: 27.09.07 10:53
Оценка:
Здравствуйте, <Аноним>, Вы делаете оверквотинг и топпостинг.
Не делайте так больше.
http://www.rsdn.ru/Info/rules.xml
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.