реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> sizeof и указатель на структуру! Проблема!
Demeny
сообщение Mar 6 2008, 13:52
Сообщение #16


Знающий
****

Группа: Свой
Сообщений: 648
Регистрация: 11-02-06
Из: Санкт-Петербург
Пользователь №: 14 237



Цитата(Samodelkin @ Mar 6 2008, 12:54) *
struct {
unsigned char KontursStatus[16];
}TX_x16_i2c_01;

IndexDataTX = (char*) TX_x16_i2c_01; //делаем IndexDataTX указателем на структуру.

Buff_size = sizeof TX_x16_i2c_01; //если так, то Buff_size равет 16, и это правильно

Buff_size = sizeof(IndexDataTX[0]); //если так, то Buff_size равет 2, и это ЛАЖА!!!

Как у кого, но у меня Ваш пример не компилируется вообще. Ошибка тут
Код
IndexDataTX = (char*) TX_x16_i2c_01; //делаем IndexDataTX указателем на структуру.

Должно быть так.
Код
IndexDataTX = (char*) &TX_x16_i2c_01; //делаем IndexDataTX указателем на структуру.

Теперь правильно с точки зрения синтаксиса. И sizeof (TX_x16_i2c_01) равен 16, а sizeof(IndexDataTX[0]) зависит от того, каким типом указателя я объявлю переменную IndexDataTX. Если это указатель на char, то sizeof(IndexDataTX[0]) == 1, если это указатель на структуру, то и результат равен размеру структуры. В чём несоответствие ?
Цитата(Samodelkin @ Mar 6 2008, 16:37) *
Ну про жесткое указание никто не говорит, но вот получается что и sizeof тоже "врет" в некоторых случаях!!!! Вот и возникает вопрос, как безошибочно выяснить реальный обьем данных в структуре!!!!!????

Ну так подсовывайте sizeof() правильный указатель и будете получать правильный результат.
Код
struct    {
unsigned char KontursStatus[16];
}TX_x16_i2c_01,  *pTX_x16_i2c_01;

pTX_x16_i2c_01 = &TX_x16_i2c_01; //присваиваем pTX_x16_i2c_01 значение ссылки на структуру.

Buff_size = sizeof TX_x16_i2c_01; //если так, то Buff_size равет 16, и это правильно

Buff_size = sizeof(pTX_x16_i2c_01[0]); //если так, то Buff_size равет 16, и это тоже правильно !!!


--------------------
Сделано в Китае. Упаковано в России.
Go to the top of the page
 
+Quote Post
bzx
сообщение Mar 6 2008, 14:08
Сообщение #17


Местный
***

Группа: Свой
Сообщений: 482
Регистрация: 5-07-05
Из: Санкт-Петербург
Пользователь №: 6 528



У тебя путаница с указателями в голове... То что ты хочешь получить должно выглядить так:
Код
typedef struct {
unsigned char KontursStatus[16];
} TXx16;
...
TXx16    TX_x16_i2c_01;
...
IndexDataTX = (char*) &TX_x16_i2c_01;
Buff_size = sizeof (TX_x16_i2c_01);
Buff_size = sizeof(*(TXx16*)IndexDataTX);

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


--------------------
Для связи email: info собака qbit.su
Go to the top of the page
 
+Quote Post
Samodelkin
сообщение Mar 6 2008, 14:40
Сообщение #18


Частый гость
**

Группа: Участник
Сообщений: 102
Регистрация: 29-05-05
Из: Днепропетровск
Пользователь №: 5 520



Цитата(Demeny @ Mar 6 2008, 17:52) *
Теперь правильно с точки зрения синтаксиса. И sizeof (TX_x16_i2c_01) равен 16, а sizeof(IndexDataTX[0]) зависит от того, каким типом указателя я объявлю переменную IndexDataTX. Если это указатель на char, то sizeof(IndexDataTX[0]) == 1, если это указатель на структуру, то и результат равен размеру структуры. В чём несоответствие ?
[/code]


Согласен, так оно и есть! Но КАК обьявить переменную IndexDataTX так чтобы это был указатель на структуру и результат sizeof был равен размеру структуры?????
Чем её обьявить?????
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 6 2008, 15:52
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Qwertty @ Mar 6 2008, 16:29) *
Вот именно из-за возможности выравнивания вариант с жестким указанием размера в первом поле и не годится.

Годится, просто он должен инициализироваться через sizeof() smile.gif

Цитата(Samodelkin @ Mar 6 2008, 16:37) *
что и sizeof тоже "врет" в некоторых случаях!!!!
...
Чем её обьявить?????

Не врет. Никак. Испейте валерианки, и перечитайте топик с начала медленно и печально.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 6 2008, 15:53
Сообщение #20


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Samodelkin @ Mar 6 2008, 16:40) *
Но КАК обьявить переменную IndexDataTX так чтобы это был указатель на структуру и результат sizeof был равен размеру структуры?????
Да никак!!! Указатель содержит ТОЛЬКО адрес. sizeof() выполняется на этапе компиляции, а не выполнения. Компилятор знает, какой тип имеет аргумент size и какой размер имеет объект такого типа. Если вы указателю НАСИЛЬНО через приведение типа присвоили адрес объекта другого типа, то это не значит, что изменился тип указателя. Вы присвоили только адрес, а тип при этом потеряли. Если указатель pTmp был указателем на char, то через этот указатель ваш объект выглядит как char и результат sizeof(*pTmp) будет равен размеру char независимо от того, какой размер имел исходный объект.

Если я правильно понял вашу задумку, у вас есть некая функция передачи, и вы хотите с ее помощью передавать разные объекты. Тогда вам надо использовать sizeof не внутри этой функции, а при ее вызове:
Код
void send(void *pData, uint_fast8_t size)
{  // указатель объявлен как void* чтобы к нему без явных
    // приведений типа преобразовывались указатели любого типа
    uint8_t *pSrc = pData;  // Отсылка идет побайтно, поэтому преобразовываем указатель к указателю на байт
    
    while(size--)
    {
        UART.transmit(*pData++);   // отсылаем байт на который указывает указатель.
    }
}

struct
{
   uint32_t a;
   uint16_t b;
   uint8_t c;
} TipaTest1;

uint8_t TipaTest2[10];

uint32_t TipaTest3;

void main()
{
    send(&TipaTest1, sizeof(TipaTest1));
    send(TipaTest2, sizeof(TipaTest2));  //имя массива само является указателем
    send(&TipaTest3, sizeof(TipaTest3));
    for(;;)
     ;
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Samodelkin
сообщение Mar 6 2008, 17:21
Сообщение #21


Частый гость
**

Группа: Участник
Сообщений: 102
Регистрация: 29-05-05
Из: Днепропетровск
Пользователь №: 5 520



Цитата(Сергей Борщ @ Mar 6 2008, 19:53) *
Да никак!!! Указатель содержит ТОЛЬКО адрес. sizeof() выполняется на этапе компиляции, а не выполнения. Компилятор знает, какой тип имеет аргумент size и какой размер имеет объект такого типа. Если вы указателю НАСИЛЬНО через приведение типа присвоили адрес объекта другого типа, то это не значит, что изменился тип указателя. Вы присвоили только адрес, а тип при этом потеряли. Если указатель pTmp был указателем на char, то через этот указатель ваш объект выглядит как char и результат sizeof(*pTmp) будет равен размеру char независимо от того, какой размер имел исходный объект.

Если я правильно понял вашу задумку, у вас есть некая функция передачи, и вы хотите с ее помощью передавать разные объекты. Тогда вам надо использовать sizeof не внутри этой функции, а при ее вызове:
Код
void send(void *pData, uint_fast8_t size)
{  // указатель объявлен как void* чтобы к нему без явных
    // приведений типа преобразовывались указатели любого типа
    uint8_t *pSrc = pData;  // Отсылка идет побайтно, поэтому преобразовываем указатель к указателю на байт
    
    while(size--)
    {
        UART.transmit(*pData++);   // отсылаем байт на который указывает указатель.
    }
}

struct
{
   uint32_t a;
   uint16_t b;
   uint8_t c;
} TipaTest1;

uint8_t TipaTest2[10];

uint32_t TipaTest3;

void main()
{
    send(&TipaTest1, sizeof(TipaTest1));
    send(TipaTest2, sizeof(TipaTest2));  //имя массива само является указателем
    send(&TipaTest3, sizeof(TipaTest3));
    for(;;)
    ;
}


Спасибо. Я все понял. Я примерно так уже и сделал. Чуть по другому, но смысл тот-же.
Хотя Ваш пример более красив по исполнению!!!! smile.gif
Go to the top of the page
 
+Quote Post
InvisibleFed
сообщение Mar 6 2008, 23:50
Сообщение #22


Местный
***

Группа: Свой
Сообщений: 401
Регистрация: 18-11-06
Из: Хабаровск
Пользователь №: 22 469



Это все хорошо, но как тогда быть с тем, что sizeof, пусть даже теоретически, но "ВРЕТ"!? Вам известен размер структуры, запихиваете его в поле size этой структуры. И запихиваете, не то что выдает sizeof, а то что Вы как программист наверняка знаете. Вариант zltigo может обломиться опять же по причине того, что могут получиться реально разные по размеру переменные типа структуры с одним и тем же значением в поле size. В функцию передаете указатель на структуру. Теперь уместный вопрос: а как тогда определить внутри вызываемой функции конкретный тип структуры, ее размер? У меня нет ответа. =) Я примерно год назад разбирал код одной библиотеки (Jasper, JPEG2000). Код большой и красивый (коментариев мало, но структурированность хорошая для чистого C). Так вот там встретил вариант от которого плевался. Принцип на Ваш случай такой. Делать поле size первым полем структуры (всех) и, зная это, обращаться к этому полю, начиная с первого байта указаеля. Т.е. если size это 32 разряда int, то вот первых четыре байта и выдергивать из области памяти по указателю. Понимаю, выглядит ОООчень коряво, но так, как оказалось, делают даже крутые разработчики (тот кто написал Jasper для меня крут, достаточно чуток над кодом посидеть, чтобы это понять).
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 7 2008, 00:52
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(InvisibleFed @ Mar 7 2008, 04:50) *
Понимаю, выглядит ОООчень коряво, но так, как оказалось, делают даже крутые разработчики (тот кто написал Jasper для меня крут, достаточно чуток над кодом посидеть, чтобы это понять).
Я не крутой программист, скорее даже наоборот smile.gif Но столкнувшись первый раз с проблемами применения incomplete array в структурах, я решил проблему подобным же образом.
Объявлял массив структур разного (заранее не известного) размера как простой одномерный массив байт с одновременной инициализацией его данными описания. Первым элементом в каждой структуре был байт, описывающий размер данной структуры. В самой программе имеется только указатель на этот массив структур. Обрабатывается массив последовательно и поэтому особых проблем с разбором его нет. Уже пару лет сопровождаю этот проект и проблем при составлении описания такой структуры под конкретную конфигурацию устройства я не испытываю.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Mar 7 2008, 05:16
Сообщение #24


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(InvisibleFed @ Mar 7 2008, 02:50) *
Это все хорошо, но как тогда быть с тем, что sizeof, пусть даже теоретически, но "ВРЕТ"!? Вам известен размер структуры, запихиваете его в поле size этой структуры. И запихиваете, не то что выдает sizeof, а то что Вы как программист наверняка знаете.

Я не могу понять - что значит "ВРЕТ"? sizeof возвращает размер структуры с учетом выравнивания. Этот размер может отличаться от суммы sizeof всех элементов структуры.
Цитата
Вариант zltigo может обломиться опять же по причине того, что могут получиться реально разные по размеру переменные типа структуры с одним и тем же значением в поле size.

Ну так у двух разных структур могут быть одинаковые размеры... Ну и что? По размеру можно определить не тип структуры, а скорее ее "версию" - типа того как это сделано в winapi.
Цитата
В функцию передаете указатель на структуру. Теперь уместный вопрос: а как тогда определить внутри вызываемой функции конкретный тип структуры, ее размер? У меня нет ответа. =)

Очень просто - первым элементом структуры идет что-то типа:
Код
typedef struct _TTypeAndSize
{
   int type;
   int size;
} TTypeAndSize;

typedef struct _TMyStruct
{
  TTypeAndSize ts;
  int a;
  float b;
} TMyStruct;

#DEFINE TYPE_MYSTRUCT 1

TMyStruct a;
a.ts.type = TYPE_MYSTRUCT;
a.ts.size = sizeof(a);
a.a = 100;
a.b = 200;

void func(void *p)
{
  TTypeAndSize *pTS = (TTypeAndSize *)p;
  switch(pTS.type)
  {
  case TYPE_MYSTRUCT: break;
  }
}

Если размер для каждого типа фиксирован - обойдетесь только полем type. В С++ на этапе выполнения тип определяется по vptr. Затраты сравнимые. Геморроя у вас конечно будет больше. Но с другой стороны, если вы это часто используете - переходите на С++.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 7 2008, 07:32
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(InvisibleFed @ Mar 7 2008, 02:50) *
Это все хорошо, но как тогда быть с тем, что sizeof, пусть даже теоретически, но "ВРЕТ"!?

А как быть с тем, что начет того, что sizeof() врет, "врет" кто-то другой smile.gif? sizeof() четко и ясно выполняет свою функцию.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
amw
сообщение Mar 7 2008, 08:45
Сообщение #26


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847



Цитата(InvisibleFed @ Mar 7 2008, 01:50) *
Это все хорошо, но как тогда быть с тем, что sizeof, пусть даже теоретически, но "ВРЕТ"!?

sizeof() не врет. Он показывает сколько памяти фактически заняла структура.
С учетом выравнивания для конкретной архитектуры.
Например структура:
Код
struct mystruct {
    char a;
    int b;
};

Далее предполагается что если sizeof(int) == 4.

Для 8 битных МК sizeof(struct mystruct) == 5;
Для 16 битных МК sizeof(struct mystruct) == 6;
Для 32 битных МК sizeof(struct mystruct) == 8;

Без специального указания каждое поле поле структуры располагается по адресу, наиболее удобному для процессора.
Так например, для 32 бит МК расположение поля b по адресу 1 (ну со смещением 1) приведек тому, что для работы с ним нужно выполнит 4 команды побайтовой загрузки со сдвигом и OR.
А расположение по адресу кратному четырем - одна команда загрузки 32 бит значения.

Хотите получить точное соответствие - используйте упакованные стрктуры.


--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть.
© Lewis Carroll. Alice's adventures in wonderland.
Go to the top of the page
 
+Quote Post
InvisibleFed
сообщение Mar 7 2008, 12:10
Сообщение #27


Местный
***

Группа: Свой
Сообщений: 401
Регистрация: 18-11-06
Из: Хабаровск
Пользователь №: 22 469



Уважаемые, обратите внимание на ковычки до и после слова "врет". Ясно, что "sizeof возвращает размер структуры с учетом выравнивания". Но Вы посмотрите, что требуется уважаемому Samodelkin! Ему требуется определить фактически тип струткру передаваемых данных по ее размеру. Могут существовать две и более структур, значение которых sizeof вернет одинаковыми (хотя фактически типы и переменные имеют РАЗНЫЕ размеры). Samodelkin в качестве поля структуры приводит массив. Вот пример того, что может случится.

Код
struct {
    char array[3];
} struct_v1; // Размер типа для 32-х разрадной машины: 4

struct {
     char array[4];
} struct_v2; // Размер типа для 32-х разрадной машины: 4


И как теперь определить обработчик для типа данных? Совершенно очевиден смысл sizeof, но человек, задающий вопрос помоему объяснил для чего ему это надо - определить функцию-обработчик по размеру струткруры. Вот и получается, что сделать он это в предложенном варианте zltigo:
Цитата
"Вот именно из-за возможности выравнивания вариант с жестким указанием размера в первом поле и не годится."

Годится, просто он должен инициализироваться через sizeof().


не сможет (sizeof в обоих случаях вернет 4, которое Samodelkin запишет в специальное поле структуры... а что толку? Различить потом struct_v1 и struct_v2 по этому полю уже не сможет).
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 7 2008, 12:32
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(InvisibleFed @ Mar 7 2008, 15:10) *
что требуется уважаемому Samodelkin!

Меня вопросы извлечения "из ничего" сначала размера структуры, а затем еще и типа струтуры не интересуют в принципе. sizeof() делает свою работу и любые рассуждения и упреки, хоть в кавычках, хоть без, к тому, что он чего-то еще комуто не сказал, хотя оооочень надо совершенно бессмысленны.



Цитата(InvisibleFed @ Mar 7 2008, 15:10) *
сделать он это в предложенном варианте zltigo:
не сможет

Я предлагал, то, о чем в том момент шла речь - автоматическое (а не через дивную константу) размещение размера стуктуры в ней самой. Подчеркиваю именно это - не больше и не меньше, а не что либо другое.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
InvisibleFed
сообщение Mar 7 2008, 13:09
Сообщение #29


Местный
***

Группа: Свой
Сообщений: 401
Регистрация: 18-11-06
Из: Хабаровск
Пользователь №: 22 469



Обсуждать по теме тут нечего. Я лично не понял ни назначения первой реплики zltigo, ни основания вырезания из контекста своих собственных слов во втором коментарии. Думаю Samodelkin уже со всем определился. Всем спасибо за дискуссию.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 7 2008, 15:44
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(InvisibleFed @ Mar 7 2008, 16:09) *
Обсуждать по теме тут нечего.

Очень рад, что и Вы это наконец-то поняли.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 02:59
Рейтинг@Mail.ru


Страница сгенерированна за 0.01513 секунд с 7
ELECTRONIX ©2004-2016