Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: структуры в С
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Страницы: 1, 2
tolik_zp
Имеется структура с элементами различных типов и массив типа char
вопрос: как все содержимое структуры скопировать в массив?

попробовал инициализировать указатель типа char на структуру и в цикле переписать - не проходит
o-henry
код в студию
v_shamaev
Цитата(tolik_zp @ Apr 26 2007, 17:05) *
Имеется структура с элементами различных типов и массив типа char
вопрос: как все содержимое структуры скопировать в массив?

попробовал инициализировать указатель типа char на структуру и в цикле переписать - не проходит

Поподробнее чуть - что не проходит?
И может union использовать?
zltigo
Цитата(tolik_zp @ Apr 26 2007, 16:05) *
попробовал инициализировать указатель типа char на структуру и в цикле переписать - не проходит

Если-бы пробовали, то получилось-бы.
Дополнительно:
Побайтно копировать никчему - memcpy() есть. Структуру, предполагаю, придется паковать, если конечно контроллер не 8-битовый.
tolik_zp
Цитата(o-henry @ Apr 26 2007, 16:10) *
код в студию


вот кусочек, прошу:

unsigned char *ptr;
struct BootSectorStruct
{
unsigned char JmpCmd[3];
unsigned char OEMName[8];
};

struct BootSectorStruct BootSector = {0xEB, 0x00, 0x90, "HaloWrld"};

ptr = &BootSector;
for (i=0;i<11;i++)
{
MMCWRData[i] = *ptr;
ptr++;
}

ИАР ругается на присваивании указателю адреса структуры
o-henry
а приведение типов кто делать будет?

ptr = (char*) &BootSector;
dxp
Цитата(tolik_zp @ Apr 26 2007, 20:16) *
вот кусочек, прошу:

unsigned char *ptr;
struct BootSectorStruct
{
unsigned char JmpCmd[3];
unsigned char OEMName[8];
};

struct BootSectorStruct BootSector = {0xEB, 0x00, 0x90, "HaloWrld"};

ptr = &BootSector;
for (i=0;i<11;i++)
{
MMCWRData[i] = *ptr;
ptr++;
}

ИАР ругается на присваивании указателю адреса структуры

Естественно, указатель на тип char, а Вы ему пихаете адрес объекта совершенно другого типа. Если так делать, то нужно применять явные преобразования типа:

ptr = (char*)&BootSector;

или, если включен С++, то лучче использовать

ptr = reinterpret_cast<char*>(&BootSector);

А вообще, как посоветовал уважаемый zltigo, тут правильнее использовать стандартную memcpy.
lks
Попробуйте указать на переменную JmpCmd - т.е. амперсанд от этой переменной присвоить указателю ptr.
Я давно с ИАРом не работал, но думаю что когда будете указывать не на структуру, а на первую переменную в структуре - проблемы снимуться.
Сергей Борщ
Цитата(lks @ Apr 26 2007, 19:30) *
Попробуйте указать на переменную JmpCmd - т.е. амперсанд от этой переменной присвоить указателю ptr.
Замечательный совет! А если первый элемент структуры будет не unsigned char? Опять бежать на форум с криком "раньше работало а теперь компилятор виноват"?
lks
Цитата(Сергей Борщ @ Apr 26 2007, 23:25) *
Замечательный совет! А если первый элемент структуры будет не unsigned char? Опять бежать на форум с криком "раньше работало а теперь компилятор виноват"?


Вопрос глубже может оказаться чем вы подумали.
То что я предлагаю работает - а что вы предложили - я не понял.
Присваете тип указателю такой же как первая переменная структуры - и все дела.
zltigo
Цитата(lks @ Apr 26 2007, 20:30) *
а на первую переменную в структуре - проблемы снимуться.

Ничем не обоснованный поступок ни к чему, кроме как к возникновению потенциальных ошибок при изменении структуры и дополнительных неясностей при разнообразных паковках структуры не приводящий. Никаких проблем при работе с именем структуры нет и "сняться" они не могут.
Сергей Борщ
Цитата(lks @ Apr 26 2007, 22:10) *
Вопрос глубже может оказаться чем вы подумали.
Вопрос простой как трехлинейная винтовка. И ответ на него рассматривается в любой книжке по С в разделе "приведение типов".
Цитата(lks @ Apr 26 2007, 22:10) *
То что я предлагаю работает - а что вы предложили - я не понял.
То, что вы предложили работает только в одном конкретном случае - когда тип первого элемента структуры совпадает с типом желаемого указателя (в данном случае - unsigned char). Предложить я ничего не мог - выше было дано три (два про приведение и один про memcpy) совершенно правильных ответа. Я лишь указал на опасность следования вашему неправильному совету.
Цитата(lks @ Apr 26 2007, 22:10) *
Присваете тип указателю такой же как первая переменная структуры - и все дела.
А если первый элемент массива - unsigned long long а структура кроме него содердит еще всего один unsigned char? И как при этом объявлять массив, в который надо скопировать?
rezident
Об чем сыр-бор? Явное приведение типов всяко лучше, чем неявное упование на особенности конкретной структуры, конкретного компилятора и разрядности конкретного МК.
tolik_zp
всем спасибо, работает. век живи - век rtfm
lks
Цитата(tolik_zp @ Apr 27 2007, 13:23) *
всем спасибо, работает. век живи - век rtfm


Приведите пожалуйста фрагмент кода который заработал в ИАР.
zltigo
Цитата(lks @ Apr 27 2007, 18:45) *
Приведите пожалуйста фрагмент кода который заработал в ИАР.

Для справок: От IAR/ не IAR это совершенно не зависит.
Код
BYTE dummy_buff[100];
ENC_Header   xxx_header;
memcpy( dummy_buff, &xxx_header, sizeof(xxx_header) );
lks
Цитата(zltigo @ Apr 27 2007, 19:57) *
Для справок: От IAR/ не IAR это совершенно не зависит.
Код
BYTE dummy_buff[100];
ENC_Header   xxx_header;
memcpy( dummy_buff, &xxx_header, sizeof(xxx_header) );


Ну может быть амперсанд структуры и покажет на структуру - а может и выдаст ошибку не совпадения типов данных.
То что товарищ приводил в качестве кода - действительно описано в учебнике, но не работает в некоторых компиляторах.
Про это и речь шла.
Мне в этой теме интересен вопрос как совместить адрес начала структуры с адресом начала массива.
Допустим чтобы работало как union - внутри: массив + структура.
Тогда реально memcpy - как телеге пятое колесо (или очень неэффективный прием).
zltigo
Цитата(lks @ Apr 27 2007, 19:53) *
Ну может быть..

Не может быть. Учите матчасть.
Цитата
Допустим чтобы работало как union - внутри: массив + структура.

union двух структур и используйте - одна стркутура с массивом, вторая со всякой всячиной.
Обычно это не делается, поскольку нагляднее банальное преобразование типов.
Цитата
Тогда реально memcpy - как телеге пятое колесо (или очень неэффективный прием).

Это две совсем разные вещи никак не заменяющие друг друга. Заговариваетесь?
sergeeff
К сведению: union - платформозависимая штука и в плане переносимости - большой вопрос.

Второе наблюдение по жизни: простое приведение одного типа указателя к другому это хорошо, если при этом не рарушается требования по выравниванию адресов (что имеет место в случае ARM'ов, например).

Так что в каждом конкретном случае надо сначала подумать, что ты хочешь, чтобы процессор сделал, а потом уже это реализовать с учетом его архитектурных особенностей (мой приятель в институте говорил в таких случаях: поиграем в компьютер, т.е. посмотрим на программу "глазами" компьютера - очень полезно).
zltigo
Цитата(sergeeff @ Apr 27 2007, 21:01) *
К сведению:

К чьему сведению? Это я спрашиваю по причине того, что Ваш пост несколько выбивается из темы и не совсем понятен.
Цитата
union - платформозависимая штука и в плане переносимости - большой вопрос.

Прошу огласить проблемы с зависимостью и непереносимостью.
Цитата
если при этом не рарушается требования по выравниванию адресов (что имеет место в случае ARM'ов, например).

В плане обсуждаемой "проблемы" это не существенно, поскольку начальные адреса структур и массивов всегда выравнены. Про изощренные способы доступа к элементам речь пока не идет.
lks
Цитата(zltigo @ Apr 27 2007, 22:14) *
В плане обсуждаемой "проблемы" это не существенно, поскольку начальные адреса структур и массивов всегда выравнены. Про изощренные способы доступа к элементам речь пока не идет.


1. Проблемы когда не фсе функции стандарта языка поддерживаются в компиляторах - бывают.
2. Простое совмещение адресного пространства в памяти - массивов и структур - гораздо красивее и правильнее чем примитивное копирование - хотябы с точки зрения экономии ресурсов и памяти программ (процедура memcpy библиотечная и занимает эн-ое количество байт).
Что мы тут из пустого в порожнее-то, а?
zltigo
Цитата(lks @ Apr 27 2007, 22:27) *
Проблемы когда не фсе функции стандарта языка поддерживаются в компиляторах - бывают.

Всему есть предел, те кто не поддерживают чего-то уже не существуют на рынке.
Если есть пример живого компилятора - в студию. Искать его очень просто - у него в прототипе функции memcpy() второй аргумент должен отличаться от (const void *). Я за двадцать с лишним лет таких не встречал.
Цитата
Простое совмещение адресного пространства в памяти - массивов и структур - гораздо красивее и правильнее чем примитивное копирование

Причем здесь красивее/не красивее? Повторяюсь - это две совершенно разные вещи не заменяющие друг друга. Как передача аргумента по значению не лучше/хуже и не красивее/уродливее передачи аргумента по ссылке. Используется то, что нужно в данный момент.
Цитата
Что мы тут из пустого в порожнее-то, а?

Лично я на этом закончил, а разговоры разговаривал исключительно по причине того, что раздел с этой темой называется "В помощь начинающему". И в этом месте мне кажутся особо неуместными мутные повествования о каких-то "некоторых компиляторах" и извращениях.
lks
Цитата(zltigo @ Apr 28 2007, 00:05) *
Лично я на этом закончил,


Могли бы и не начинать.

to all:

А всеже интересно, когда указываете на структуру через амперсанд, какой тип данных должен иметь указатель? (пусть даже на для компилятора ИАР).
Я пробовал сделать это на другом компиляторе у меня тоже не получилось.
Умные люди подсказывают что тип указателя должен быть void.
По идее в момент инициализации данных можно описать массив указателей типа void и потом амперсанд структуры присвоить первому элементу этого массива.
dxp
Цитата(lks @ Apr 28 2007, 12:12) *
А всеже интересно, когда указываете на структуру через амперсанд, какой тип данных должен иметь указатель?

Поясните пожалуйста, что Вы подразумеваете под "указанием на структуру через амперсанд"?

Цитата(lks @ Apr 28 2007, 12:12) *
(пусть даже на для компилятора ИАР).

От компилятора тут ничего зависеть не должно - это правила языка, компилятор, если он соответсвует Стандарту, должен выполнять предсказуемые действия. Иначе такой компилятор фтопку.

Цитата(lks @ Apr 28 2007, 12:12) *
Умные люди подсказывают что тип указателя должен быть void.

Как это? Приведите пожалуйста пример?

Цитата(lks @ Apr 28 2007, 12:12) *
По идее в момент инициализации данных можно описать массив указателей типа void и потом амперсанд структуры присвоить первому элементу этого массива.

Что такое "амперсанд структуры"? Это новый термин в языке? Покажите лучше, код, который имеете в виду, возможно, так будет понятнее и однозначее.
lks
Цитата(dxp @ Apr 28 2007, 10:56) *
Поясните пожалуйста, что Вы подразумеваете под "указанием на структуру через амперсанд"?
От компилятора тут ничего зависеть не должно - это правила языка, компилятор, если он соответсвует Стандарту, должен выполнять предсказуемые действия. Иначе такой компилятор фтопку.
Как это? Приведите пожалуйста пример?
Что такое "амперсанд структуры"? Это новый термин в языке? Покажите лучше, код, который имеете в виду, возможно, так будет понятнее и однозначее.




unsigned char *ptr;
struct BootSectorStruct
{
unsigned char JmpCmd[3];
unsigned char OEMName[8];
};

struct BootSectorStruct BootSector = {0xEB, 0x00, 0x90, "HaloWrld"};

ptr = &BootSector;
for (i=0;i<11;i++)
{
MMCWRData[i] = *ptr;
ptr++;
}

Хорошо, поясняю.

Значок & - называется амперсанд, или оператор указания.
Когда пишу "амперсанд структуры" - подразумеваю - &BootSector, т.е. получение адреса по которому располагается данные описанные в структуре.
Этот пример кода взят (судя по всему) из учебника - автором темы.
Никто не сомневается что он должен работать.
Автор темы попытался применить его в ИАР компиляторе - результат: не работатет.
Вопрос в том: почему он не работатет и развивая мысль дальше - неплохо бы сделать совмещение начала адресов массива и структуры в памяти - тогда необходимость копирования данных из одного места в другое автоматически отпадает.

Так лучше?
o-henry
Цитата(lks @ Apr 28 2007, 10:11) *
Этот пример кода взят (судя по всему) из учебника - автором темы.
Никто не сомневается что он должен работать.


А чего тут сомневаться blink.gif? Разумеется он не должен работать.
В приведенном коде указателю на unsigned char
присваивается адрес структуры BootSectorStruct, т.е адрес объекта совершенно другого типа.
И любой компилятор просто обязан сообщить об ошибке.
А тот факт, что в данном случае структура состоит исключительно из массивов типа unsigned char совершенно никакой роли не играет.
zltigo
Цитата(lks @ Apr 28 2007, 11:11) *
Никто не сомневается что он должен работать.

Я рыдал sad.gif. Прошу вычеркнуть меня из списка "никто не сомневающихся", по причине знания того факта, что "работать" ( молча приводить указатель на структуру к указателю на unsigned char) это не должно. И того, что всегда должно "работать" явное приведение типов указателей и любые неявные преобразования типов указателей с участием указателя на void.
Сергей Борщ
Цитата(lks @ Apr 28 2007, 10:11) *
Вопрос в том: почему он не работатет и развивая мысль дальше - неплохо бы сделать совмещение начала адресов массива и структуры в памяти - тогда необходимость копирования данных из одного места в другое автоматически отпадает.
Выделите наконец полчаса и прочитайте у Кернигана и Ритчи главу про указатели. Тогда вы поймете, что компилятор ругается правильно, узнаете какой тип имеет &BootSector, узнаете почему компилятор проглотит ptr = &BootSector; если ptr объявлен как void*, и узнаете почему в этом случае компилятор выругается на MMCWRData[ i ] = *ptr. Вы поймете что общего у массивов и указателей и как правильно объявив указатель можно получить совмещение начала адресов массива и структуры в памяти. Ведь, судя по вашим сообщениям в этой ветке, вы совершенно не имеете понятия об указателях. Но почему вы хотите, чтобы кто-то потратил гораздо больше времени, пересказывая тут эту главу для вас тут??? Если вам что-то будет непонятно у Кернигана и Ритчи - спрашивайте, с удовольствием объясним. Но сделайте сначала сами элементарное усилие.

P.S. Какой, нафиг, пример из учебника, если судя по названию массива идет работа с MultiMedia Card?
lks
Цитата(o-henry @ Apr 28 2007, 12:53) *
А чего тут сомневаться blink.gif? Разумеется он не должен работать.


Может нужно вместо unsigned char *ptr - написать void *ptr?
Мне кажется это ничего не изменит.
Ошибка будет в момент выполнения операции & от структуры.
Вы серъезно считаете что энциклопедию языка Си писали идиоты?


Цитата(Сергей Борщ @ Apr 28 2007, 13:46) *
Если вам что-то будет непонятно у Кернигана и Ритчи - спрашивайте, с удовольствием объясним. Но сделайте сначала сами элементарное усилие.

P.S. Какой, нафиг, пример из учебника, если судя по названию массива идет работа с MultiMedia Card?


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

А что разве Си нельзя применять для MMC - это такое системное ограничение - типа чернила только для 8 класса?
Сергей Борщ
Цитата(lks @ Apr 28 2007, 11:58) *
Может нужно вместо unsigned char *ptr - написать void *ptr?
Мне кажется это ничего не изменит.
Ваше "кажется" - не указание для компилятора. Еще раз: если вы объявите ptr как void* компилятор скушает ptr = &BootSector. Но прочитайте в учебнике, почему в этом случае нельзя делать *ptr.
Цитата(lks @ Apr 28 2007, 11:58) *
Ошибка будет в момент выполнения операции & от структуры.
Еще раз: если void*, то в другом месте.
Цитата(lks @ Apr 28 2007, 11:58) *
Вы серъезно считаете что энциклопедию языка Си писали идиоты?
Вы серьезно считаете, что вы ее прочитали и поняли?

Цитата(lks @ Apr 28 2007, 11:58) *
А что разве Си нельзя применять для MMC - это такое системное ограничение - типа чернила только для 8 класса?
При чем тут Си? Речь шла про учебник. В учебниках приводятся простые абстрактные примеры.
dxp
Цитата(lks @ Apr 28 2007, 15:11) *
Значок & - называется амперсанд, или оператор указания.

Неверно. & - это оператор взятия адреса, а не оператор указания.

Цитата(lks @ Apr 28 2007, 15:11) *
Когда пишу "амперсанд структуры" - подразумеваю - &BootSector, т.е. получение адреса по которому располагается данные описанные в структуре.

Какие данные? Все, что-ли?

"Амперсанд структуры" - это совершенно неверная терминология, отсюда и путаница, и вопросы. &BootSector - это адрес структуры (а не амперсанд). Употребляйте правильную терминологию и Вас правильно поймут.

Цитата(lks @ Apr 28 2007, 15:11) *
Этот пример кода взят (судя по всему) из учебника - автором темы.
Никто не сомневается что он должен работать.

unsigned char *ptr = &BootSector (где BootSector - структура), работать не должно и не работает.

Цитата(lks @ Apr 28 2007, 15:11) *
Автор темы попытался применить его в ИАР компиляторе - результат: не работатет.

Потому, что не должен он работать. Ни в каком компиляторе, а не только в IAR.

Цитата(lks @ Apr 28 2007, 15:11) *
Вопрос в том: почему он не работатет

Потому, что в этом выражении возникает элементарная несовместимость типов - нельзя указателю на один тип присваивать адрес объекта другого типа. Потому, что в этом случае работать с указателем будет небезопасно - компилятор, зная тип указателя, будет выполнять действия, пригодные к типу этого указателя, а на самом деле будет работать с объектом совершенно другого типа. Вслепую. Это источник очень гадких и трудноуловимых глюков. Статический контроль типов защищает от этой ситуации. Присваивать указателю void* разрешается потому, что с этим указателем ничего делать нельзя - к объекту не доступиться.

Цитата(lks @ Apr 28 2007, 15:11) *
и развивая мысль дальше - неплохо бы сделать совмещение начала адресов массива и структуры в памяти - тогда необходимость копирования данных из одного места в другое автоматически отпадает.

Глубины этой мысли я асилить не смог. biggrin.gif

Цитата(lks @ Apr 28 2007, 15:11) *
Так лучше?

No comments. smile.gif
lks
Цитата(dxp @ Apr 28 2007, 15:01) *
Неверно. & - это оператор взятия адреса, а не оператор указания.


Вот так, да?
Вы меня насмешили.
Тогда указатель на что будет указывать?
Кстати термин не я придумал : Энциклопедия языка Си. Я. Белецкий. М. Мир. Стр 52.

Цитата(dxp @ Apr 28 2007, 15:01) *
&BootSector - это адрес структуры (а не амперсанд). Употребляйте правильную терминологию и Вас правильно поймут.


Вы там это серъезно об этом?
Вот эта хрень "&" - собстно и называется амперсанд.
Так как (всеже) присвоить адрес структуры указателю?


Цитата(dxp @ Apr 28 2007, 15:01) *
нельзя указателю на один тип присваивать адрес объекта другого типа.
Потому, что в этом случае работать с указателем будет небезопасно - компилятор, зная тип указателя, будет выполнять действия, пригодные к типу этого указателя, а на самом деле будет работать с объектом совершенно другого типа.


Ну тогда обясните почему я всегда могу получить адресс массива через амперсанд не зависимо от типа данных, а от структуры не получается.
Я могу привести ссылку где утверждается, что в этом случае возможны ошибки чтения данных (в случае со структурой), и программисту надо быть внимательным.
Т.е. не предполагается что эта функция заблокирована.
Мы говорим о начальном адресе структуры, а не о типе данных.
Вот пример приведен во всех учебниках со структурой - а вы заладили - нельзя, нельзя.



Цитата(dxp @ Apr 28 2007, 15:01) *
Глубины этой мысли я асилить не смог. biggrin.gif
No comments. smile.gif


Чтож тут такого умного?
Полистайте какие-нибудь исходники написанные на языке Си - это типовая операция, вааще-то.
Вам сказать нечего - вот и придумываете разные предлоги.
Нет бы сказали честно - не пишем мы на Си - только на Дэлфи (фортране, или кто на чем).
:-)
o-henry
Уважаемый tolik_zp!
На Ваш вопрос Вы уже получили ответ.
Закрыли бы Вы этот топик, а то тут такой поток бреда начинается - не дай бог другие начинающие программировать на "C" это читать будут.
lks
Цитата(o-henry @ Apr 28 2007, 16:40) *
Уважаемый tolik_zp!
На Ваш вопрос Вы уже получили ответ.
Закрыли бы Вы этот топик, а то тут такой поток бреда начинается - не дай бог другие начинающие программировать на "C" это читать будут.


"Хвост", перед школьниками, будете распускать в другом месте.
А я не начинающий программист, к вашему сведению..
zltigo
Цитата(lks @ Apr 28 2007, 15:47) *
А я не начинающий программист, к вашему сведению..

Тем хуже sad.gif, что Вам так кажется. Мои соболезнования.
lks
Цитата(zltigo @ Apr 28 2007, 16:57) *
Тем хуже sad.gif, что Вам так кажется. Мои соболезнования.


Чем хуже?
Говорим, говорим.
По существу проблемы что сказать можете?
Вы предложили использовать библиотечную процедуру memcpy для копирования данных из структуры в массив.
Это вызовет увеличение кода, время выполнения и ненужное копирование всего массива - это очень плохо, вы согласны?
Я предложил добавить в структуру пременную типа unsigned char (если она там отсутствует)
и использовать присвоение на указатель ее адреса. В остальном все без изменений.
Положительный момент в том что не нужно копировать весь массив, не расходуется память для библиотечной программы memcpy и т.д.
Это работает везде - можете проверить.
Также я предложил обсудить вариант когда адрес массива и структуры совпадают в памяти.
В этом случае не потребуется производить вообще никаких действий с данными.
В ответ слышу только вопли...
Ну разве я виноват, что вы плохо разбираетесь в языке Си?
zltigo
Цитата(lks @ Apr 28 2007, 16:58) *
По существу проблемы что сказать можете?

Позвольте спросить прямо - Вы дурак или прикидываетесь?
Здесь не единожды расказано, как:
1. делать явное приведение типов указателей если не нужно копировать структуру в массив, или как автор первоначального вопроса хотел для дальнейшего побайтного копирования.
2. как эффективно скопировать структуру в массив (что собственно и являлось первоначальным вопросом)
3. как сделать union из массива и структуры (хотя я лично не вижу в этом никакого смысла) ввиду естественности п.1.
dxp
Цитата(lks @ Apr 28 2007, 19:22) *
Вот так, да?
Вы меня насмешили.
Тогда указатель на что будет указывать?
Кстати термин не я придумал : Энциклопедия языка Си. Я. Белецкий. М. Мир. Стр 52.

Не читайте больше эту книжку. Фтопку ее. Серьезно. Читайте Д.Ричи, Б.Керниган "Язык программирования С".

Цитата(lks @ Apr 28 2007, 19:22) *
Вы там это серъезно об этом?
Вот эта хрень "&" - собстно и называется амперсанд.

Да, эта хрень "&" действительно называется амперсандом. А вот эта хрень &BootSector в языках программирования С/С++ называется адресом объекта.

Цитата(lks @ Apr 28 2007, 19:22) *
Так как (всеже) присвоить адрес структуры указателю?

Код
typedef struct { ... } TBootSector;

TBootSector *p;
TBootSector BootSector;

p = &BootSector;


Если же хочется присвоить адрес структуры указателю на ДРУГОЙ тип, что является потенциально опасным, то это тоже можно сделать, но при этом надо сообщить компилятору, чтобы он не возмущался, что мы делаем эту опасную вещь осознанно. Для этого используется ручное преобразование типа:

Код
char *p;

p = (char*)&BootSector;


Я понятно объясняю? smile.gif

Цитата(lks @ Apr 28 2007, 19:22) *
Ну тогда обясните почему я всегда могу получить адресс массива через амперсанд не зависимо от типа данных, а от структуры не получается.

И от структуры взять адрес тоже получается. Вот только пихать его куда попало не получается просто так. И это правильно. С массивом есть одна особенность: про массивы есть правило, что адрес массива является адресом его первого элемента. Это логично и безопасно, т.к. все элементы в массиве одинаковые - т.е. адресная арифметика с указателем, имеющим адрес массива, работает правильно. А вот с другими агрегатными объектами, к которым относится и структура, это не верно. Кстати, адрес массива сунуть, например, в указатель на структуру Вам вряд ли удастся по тем же причинам, почему нельзя адрес структуры сунуть в указатель на char.

Цитата(lks @ Apr 28 2007, 19:22) *
Вот пример приведен во всех учебниках со структурой - а вы заладили - нельзя, нельзя.
Чтож тут такого умного?

Какой пример? Приведите его сюда, плиз. Со ссылкой на учебник.

Цитата(lks @ Apr 28 2007, 19:22) *
Полистайте какие-нибудь исходники написанные на языке Си - это типовая операция, вааще-то.
Вам сказать нечего - вот и придумываете разные предлоги.
Нет бы сказали честно - не пишем мы на Си - только на Дэлфи (фортране, или кто на чем).
:-)

Я уже много всякого полистал насчет и С, и С++, не надо меня отсылать. Не хочу показаться невежливым, но приходится констатировать факт, что Вы не знаете элементарных вещей из ЯП С и, что самое плохое (для Вас) и неприятное (для меня), упорствуете в этом невежестве.

P.S. Дельфи и фортран я почти не знаю, никогда на них ничего серьезного не писал. На Си действительно уже давно не пишу, все больше на С++, но в обсуждаемых аспектах эти языка почти совершенно одинаковы.

P.P.S. Что-то я утомился и желание вести эту дискуссию (в тоне последней Вашей фразы) у меня пропало. Всего Вам хорошего.
rezident
Цитата(lks @ Apr 28 2007, 18:22) *
Ну тогда обясните почему я всегда могу получить адресс массива через амперсанд не зависимо от типа данных, а от структуры не получается.

lks, может вам образный пример поможет? smile.gif
Пускай данные будут гайками, массив данных - ящик с одинаковыми гайками, разложенными по ячеечкам, а структура это автомобиль. Когда вы указываете на массив данных, то даете отмашку в направлении ящика с гайками. Причем все гайки в этом ящике одинаковые и расположение их тоже одинаково. Когда же вы указываете на структуру, то отмашка будет уже на весьма сложное устройство - автомобиль. В этом устройстве тоже есть такие же гайки, как и в ящике, но кроме гаек там еще туева хуча других железок, расположенных и соединенных между собой весьма замысловатым образом.
Если вы указали на данные (гайки) и попросили кого-либо принести третью по счету гайку, то он выполнит это без проблем. А вот с автомобилем, так просто не получится. Чтобы достать из автомобиля третью гайку, этому "кому-либо" понадобится как минимум список деталей автомобиля (описание структуры) и инструмент для его разборки/сборки и извлечения этой третьей гайки (механизм доступа к структуре).
Надеюсь, такая аналогия отличий указателя на данные и структуру вам будет понятна? biggrin.gif
Vladimir Chekin
Дежа-вю...
Юзер: - Я решил сварить яйцо в микроволновке - оно взорвалось. Что я сделал не так?
Суппорт: - Читайте инструкцию. Яйца в микроволновке готовить нельзя.
Юзер: - Я завернул его в фольгу - оно всё равно взорвалось. Что я сделал не так?
Ну и т.д.

lks, несколько уважаемых тут человек с многолетним стажем попытались тебе доступно, с примерами объяснить, что желаемое тобой - это ошибка, описана в стандарте, по которому пишуться компиляторы. Ты с этим не согласен и продолжаешь убеждать присутсвующих в своей правоте, вводя свою новую терминологию и новые сущности на общепринятые понятия и термины. Ладно, право на заблуждение - это тоже твой законное право, никто на него не посягает. И люди, потратившие своё жизненное время на твои заблуждения, не павлины, распушающие хвосты перед новичками, они бестолковые бараны, т.к. сразу не врубились что их усилия и потраченное время тщетны на корню. Я, наверное такой же баран, раз трачу время и пишу это.

Давай попробую попроще объяснить. Чисто по ситуации.
Любой компилятор, написанный по существующим стандартам, в том числе и ИАР, будет выдавать ошибку на неявное приведение типов. Это сущность, данность, факт, фича (выбрать понятный термин), которая есть и от непонимания/неприятия тобой этой сущности она НЕ изменится, данный компилятор НЕ перестанет выдавать ошибку на этот код.

Как в рекламе в метро, выход есть! Их два:
1) Исправить код для соответсвия правилам и не трах... себе и людям мозги,
2) Написать или заказать написание компилятора под свои требования. И будет тебе счастье. Адрес московской фирмы, пишущей компиляторы, дам, если надо.

(lks @ Apr 28 2007, 15:47) >> А я не начинающий программист, к вашему сведению..

Тем более, раз плюнуть LKS-компилер написать. А кстати, звучит!
rezident
Цитата(Vladimir Chekin)
Написать или заказать написание компилятора под свои требования. И будет тебе счастье. Адрес московской фирмы, пишущей компиляторы, дам, если надо.

bb-offtopic.gif У вас есть адрес Доктора ТуамОсеса??? blink.gif Оба-на! Это интересно! biggrin.gif
lks
Цитата(dxp @ Apr 28 2007, 18:21) *
P.P.S. Что-то я утомился и желание вести эту дискуссию (в тоне последней Вашей фразы) у меня пропало. Всего Вам хорошего.


Извините если чем обидел - в мыслях не было ничего плохого.

typedef struct { ... } TBootSector;
TBootSector *p;
TBootSector BootSector;
p = &BootSector;

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


Цитата(rezident @ Apr 28 2007, 18:48) *
Надеюсь, такая аналогия отличий указателя на данные и структуру вам будет понятна? biggrin.gif


С гайками то это вы круто завернули!
Аналагии отличий указателей на данные и структуру в гаечном варианте принимаются.
Если бы я сначала не попробовал этот фрагмент на компиляторе и не загружал бы его потом в демоплату - может быть тут умные излияния "богоподобных титанов программирования" пропустил бы мимо ушей.
Мы не говорим о теории программирования.
Как должно быть кого интересует? Разработчиков компиляторов?
Тут товарищ знает адрес. Это к нему.

Цитата(Vladimir Chekin @ Apr 28 2007, 20:00) *
Давай попробую попроще объяснить.


Давайка я тебе тоже попроще объясню.
Есть компиляторы, а есть компиляторы.
На одних твоя фича идет, на других нет.
Трудно понять?
rezident
Цитата(lks @ Apr 29 2007, 00:34) *
typedef struct { ... } TBootSector;
TBootSector *p;
TBootSector BootSector;
p = &BootSector;

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

А что у вас в "такой конструкции" вызывает удивление? Еще с 6 класса в школе нас приучали, что при вычислениях все величины должны быть приведены к одной размерности и системе единиц. Если этого не делать, то возможна ситуация как на автозаправках, принимают бензин по весу (в тоннах), а продают в литрах (по объему). Цифры прихода/расхода вроде одинаковы, а но откуда-то вдруг возникает "левая" прибыль wink.gif
lks
Цитата(dxp @ Apr 28 2007, 18:21) *
Какой пример? Приведите его сюда, плиз. Со ссылкой на учебник.


Еще один пример.

struct S {...}s;
struct S *ps;
ps=&s;

Программирование в среде Си для ПЭВМ ЕС. авторы. Стр 125.
Тоже в топку?


Цитата(rezident @ Apr 28 2007, 23:19) *
А что у вас в "такой конструкции" вызывает удивление?


Непонятно пока где описать этот тип данных - TBootSector *p;
Этот адрес потом непереписать в обычный указатель?
Ну и как на эту "баламутину" отреагирует Keil допустим.

И все же читал где-то, сейчас не могу вспомнить, не должно быть запрета на получение адреса структуры. Указатель на структуру должен быть всеже адресом первого байта в выделенном адресном пространстве, точно также как и в массивах - тип тут ни при чем.
Тут что-то с компиляторами.
Legotron
Цитата(lks @ Apr 28 2007, 23:26) *
И все же читал где-то, сейчас не могу вспомнить, не должно быть запрета на получение адреса структуры. Указатель на структуру должен быть всеже адресом первого байта в выделенном адресном пространстве, точно также как и в массивах - тип тут ни при чем.
Тут что-то с компиляторами.

Я делал когда-то таким образом:
Был массив, который представлял собой файл EMF формата. Там структуры записаны.
У меня было несколько разных типов структур и 1 указатель, который я каждый раз приводил к типу той структуры, которая мне нужна. И получал доступ к их полям. Тока с упаковкой структур (надо/ненадо) нужно быть внимательнее.
rezident
Цитата(lks @ Apr 29 2007, 01:26) *
Непонятно пока где описать этот тип данных - TBootSector *p;

Тип TBootSector задается в typedef, см. исходный пример у dxp. Если вопрос: где именно объявить этот тип, то однозначного ответа у меня нет. Это зависит от стиля программирования. Я, например, создаю типы переменных и структур в хидерах, которые потом включаю к общий хидер проекта. В свою очередь общий хидер проекта включаю во все модули, которые этого требуют. Чтобы не было недоразумений все новые типы обрамляю условной компиляцией #ifdef/#endif.
Цитата(lks @ Apr 29 2007, 01:26) *
Этот адрес потом непереписать в обычный указатель?
Ну и как на эту "баламутину" отреагирует Keil допустим.

Извините, но я не понимаю термина "обычный указатель".
Цитата(lks @ Apr 29 2007, 01:26) *
И все же читал где-то, сейчас не могу вспомнить, не должно быть запрета на получение адреса структуры. Указатель на структуру должен быть всеже адресом первого байта в выделенном адресном пространстве, точно также как и в массивах - тип тут ни при чем.
Тут что-то с компиляторами.

Дык, а с чего вы взяли что есть такой запрет? Я же вроде доступную аналогию с гайками и автомобилем привел. Указатель это отмашка в сторону объекта. Но без дополнительного пояснения о том, как именно извлекать части (элементы структуры) этого объекта (структуры), он не имеет смысла и даже опасен. О чем компиляторы вас и предупреждают.
Цитата(lks @ Apr 29 2007, 01:26) *
Указатель на структуру должен быть всеже адресом первого байта в выделенном адресном пространстве, точно также как и в массивах - тип тут ни при чем.
Тут что-то с компиляторами.

Вы все время забываете о реальном железе в котором работает программа. Минимальная адресуемая единица зависит от разрядности CPU и способа его доступа к памяти. Если минимальная адресуемая единица байт, то да - указатель на структуру будет указывать на первый байт структуры. А если минмимальная адресуемая единица слово или 32-разрядное слово? Или наоборот, CPU с байтовым доступом к памяти, но первый элемент структуры не байт, а длинное длинное целое? Впрочем здесь я уже вслед за другими начинаю все повторять то же самое по третьему разу. Неужели вы до сих пор не поняли/не осознали? blink.gif
Понятие структуры в ЯВУ аналогично описанию объекта. Например, про детский мяч можно сказать что он:
- круглый (описание формы)
- даже шарообразный (описание формы)
- красного цвета (описание цвета)
- с двумя синими полосками (описание цвета)
- упругий (описание реакции на внешнее воздействие)
- резиновый (описание материала)
- не тонет в воде (описание плотности)
и т.п.
каждое свойство в отдельности не дает полного описания объекта, но если их объединить, то получим полное описание мяча. Проблема в том, что все описания имеют разный тип/размерность. Объединив их в одно общее описание объекта, нельзя все свойства описания менять одинаково, т.к. они имеют разный тип и разный диапазон. Форме нельзя указать цвет, а реакции на внешнее воздействие нельзя назначить свойство формы. В противном случае мы можем получить такое описание мяча: форма - синяя, цвет - пирамидальный, упругость - тонет в парах ртути, плотность - тверже алмаза. biggrin.gif
Вам до сих пор еще не понятно?
lks
Цитата(Legotron @ Apr 28 2007, 23:58) *
Я делал когда-то таким образом:
Был массив, который представлял собой файл EMF формата. Там структуры записаны.
У меня было несколько разных типов структур и 1 указатель, который я каждый раз приводил к типу той структуры, которая мне нужна. И получал доступ к их полям. Тока с упаковкой структур (надо/ненадо) нужно быть внимательнее.


Возможно, что это и вариант. Непонял пока.
Тут вопрос у меня очень похож - как у автора этой темы.
В корневом каталоге SD - FAT16 дискрипторы файлов по 32 байта.
Читаем данные секторами по 512 в буфер.
Само собой напрашивается путь чтобы таскать структуру с описанием переменных (дискриптор) - по буферу. Что-то вроде маски должно получиться.
По идее, нужно адрес байта в массиве - который легко извлекается - &BUFFER[i]; - присвоить началу структуры. Даже с получением адреса начала структуры проблемы нарисовались.
Пока не получилось.


Цитата(rezident @ Apr 29 2007, 01:35) *
Извините, но я не понимаю термина "обычный указатель".


Когда вы извлекаете адрес переменной с помощью оператора амперсанд - вы получаете адрес переменной. Вы знаете тип переменной?
Простая процедура.
Этот тип не требует описание его в "хидере".
Это не термин - это просто обычный указатель, поддерживаемый стандартными процедурами.


Цитата(rezident @ Apr 29 2007, 01:35) *
Если минимальная адресуемая единица байт, то да - указатель на структуру будет указывать на первый байт структуры.
Неужели вы до сих пор не поняли/не осознали? blink.gif


Что я не понял/ не осознал?

Цитата(rezident @ Apr 29 2007, 01:35) *
Например, про детский мяч можно сказать что он:
- круглый (описание формы)
- даже шарообразный (описание формы)
- красного цвета (описание цвета)
- с двумя синими полосками (описание цвета)
- упругий (описание реакции на внешнее воздействие)
- резиновый (описание материала)
- не тонет в воде (описание плотности)
и т.п.


Вы блещете интеллектом, мне прямо не удобно...


Цитата(rezident @ Apr 29 2007, 01:35) *
Вам до сих пор еще не понятно?


Что мне еще до сих пор не понятно?
rezident
Цитата(lks)
Когда вы извлекаете адрес переменной с помощью оператора амперсанд - вы получаете адрес переменной. Вы знаете тип переменной?
Простая процедура.
Этот тип не требует описание его в "хидере".
Это не термин - это просто обычный указатель, поддерживаемый стандартными процедурами.

Ну я уже не знаю как вам объяснять. huh.gif На гайках и автомобилях не понимаете, на яблоки, арбузы и семячки перейти что ли? smile.gif
Указатель в СИ это такая же абстракция как и структура. Поведение указателя после компиляции программы в машинные коды, выполняемые CPU, зависит от конкретного CPU. Если CPU обращается к памяти побайтно, то нет никаких проблем, чтобы адресовать каждый байт. Но если разрядность шины памяти шире 8 бит, то возникают нюансы. На языке ассемблера разница выразится, например в том, что вместо команды MOV.W 0x8(R10), R14 будет использоваться команда MOV.B 0x8(R10), R14. В 16-битной архитектуре такая команда позволяет получить доступ к байту, в отличие от доступа к слову "по-умолчанию". Если в такой системе структура будет иметь выравнивание на байт, то есть вероятность 50/50, что вы обязательно налетите на глюки при использовании "словного" (16-битного) доступа к такой структуре. Причем это даже при доступе к массиву однородных данных относится. Пример.
unsigned char mas[5]={0x00, 0x01, 0x02, 0x03, 0x04};
Вне зависимости от архитектуры и способа доступа к памяти байты могут расположится в памяти в порядке как 0x00, 0x01, 0x02, 0x03, 0x04, это нам гарантирует стандарт СИ. Однако извлечение их из памяти будет зависеть от описания способа доступа к памяти, т.к. в физической памяти первый байт массива может расположиться по нечетному адресу, который 16-разрядный CPU напрямую адресовать не может, т.к. у него счетчик (PC) кратно слову (2 байтам) инкрементируется, а не кратно 1 байту. Тогда при извлечении из физической памяти такого массива с 16-разядным доступом мы можем получить двоякий результат 0x00XX, 0x0201, 0x0403 или 0x0100, 0x0302, 0xXX04. Вот к чему может привести свободное манипулирование типами данных.
zltigo
Цитата(lks @ Apr 29 2007, 14:26) *
Возможно, что это и вариант. Непонял пока.

Слава Богу, что хоть зародилась мысль, что что-то "Непонял", а то до этого момента складывалось впечатление, что просто какой-то мессия удостоил нас своим присутсутствием smile.gif. С попыткой встать на путь истинный, Вас!
Цитата
Читаем данные секторами по 512 в буфер.
Само собой напрашивается путь чтобы таскать структуру с описанием переменных (дискриптор) - по буферу. Что-то вроде маски должно получиться.
По идее, нужно адрес байта в массиве - который легко извлекается - &BUFFER[i]; - присвоить началу структуры.

Подсказка - байты не нужны. Массивы могут быть не только байтовые, но массивами структур.
Цитата
Когда вы извлекаете адрес переменной с помощью оператора амперсанд - вы получаете адрес переменной. Вы знаете тип переменной?

Прочитайте медленно и по слогам, что писал, например, dxp по поводу указателя на void.
Преред этим постарайтесь забыть, что Вы "опытный программист" на усеченном (стуктуры данных явно не использовали sad.gif )диалекте ASM под исключительно 8bit, контроллеры.
Legotron
Цитата(Legotron @ Apr 28 2007, 23:58) *
У меня было несколько разных типов структур и 1 указатель, который я каждый раз приводил к типу той структуры, которая мне нужна. И получал доступ к их полям. Тока с упаковкой структур (надо/ненадо) нужно быть внимательнее.

Б.Р.Е.Д!
Ой каюсь-каюсь я был в перегреве, когда писал это сообщение! blush.gif
Лучше поздно чем никогда!

Уважаемый dxp писал:
"чтобы можно было работать с объектом класса, указатель на него должен "знать" о строении (структуре) класса." тут

Также и со структурой:

Код
struct A {...}a;
int * Ptr;
struct A * Ptr2;

Ptr = (struct A *)&a;  // сделать можно (и даже 1 поле структуры можно получить, если типы совпадут) :))))
Ptr->(поле);    // так сделать нельзя (будет ругаться компилятор)

Ptr2 = &a;      // всё тип-топ
Ptr2->(поле);   // анологично
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.