Перейти к содержанию
    

struct - непонятка с косвенной адресацией

Господа, что-то не понимаю следующего:

 

Даю описание структуры

 

typedef struct SettingMenu

{

unsigned int

P1,

P2,

...

...

P100;

} Setup;

Где-то в модуле(да неважно где) создаем новую структуру типа Setup

 

Setup LocalSetup;

 

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

Берем адрес структуры и в цикле запихиваем в структуру данные.

 

Setup LocalSetup;// Создаем структуру типа Setup

Setup *sptr;// Указатель

...

...

 

sptr = & LocalSetup;// Определяем адрес структуры

 

for (c=0; c<100; c++)

{

*sptr = c; // Записываем по адресу некое значение

sptr++; // Увеличиваем адрес

}

Это классический пример С, значения пишутся во все поля без проблем

 

В Keil-е номер не проходит - ругается на разные типы данных строки *sptr = c, хотя теоретически я получил в качестве адреса структуры адрес первого поля этой структуры.

Как бы это правильно разрулить???

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Setup *sptr;// Указатель

for (c=0; c<100; c++)

{

*sptr = c; // Записываем по адресу некое значение

sptr++; // Увеличиваем адрес

}

[/b]

Это классический пример С, значения пишутся во все поля без проблем

насчет классики не уверен, особенно в том месте, где Вы указываете имя структуры сперва в стандарте С++ (после struct), а потом еще и в classic - после закрывающей скобки, но в принципе любой уважающий себя современный компилятор не должен разрешать подобные вольности.

1. переменная sptr имеет тип Setup *, соответственно, *sptr - типа Setup, а Вы пытаетесь инициализировать ее с помощью переменной типа (предположительно) int

2. даже если приведенную Вами конструкцию скомпилировать путем явного приведения типа (то есть, написав

*(( int *)sptr) = c;

все равно инструкция sptr++ выполнится неправильно (Вы, очевидно, ожидаете инкремента на размер int, а получите - на размер Setup)

Не могу сказать, что это пример хорошего кода, но очевидно Вы в классическом примере упустили тот факт, что там, думаю, было написано так:

int *sptr = (*int)&LocalSetup; // Указатель
...

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

Изменено пользователем sergik_vrn

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хотите массив - используйте!!!

typedef struct SettingMenu

{

unsigned int P[100];

} Setup;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо sergik_vrn , попробую...

А насчет массива:

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

Проще указать каждой переменной адрес, где она будет лежать в RAM, а не использовать массив.

 

Спасибо за ответы...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо sergik_vrn , попробую...

А насчет массива:

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

Проще указать каждой переменной адрес, где она будет лежать в RAM, а не использовать массив.

 

Спасибо за ответы...

1. тот вариант, что я привел - вовсе не оптимальный, просто в нем исправлены Ваши ошибки

2. адрес элемента массива это <имя_массива>+<номер элемента>

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

 

пассаж насчет указания адресов "лежания" для переменных до моего понимания не дошел

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

2. адрес элемента массива это <имя_массива>+<номер элемента>

...

 

Я так понял, что Andrei_S говорит о том, что в структуре каждой переменной он может задать осмысленное имя, в то время как для массива потребуется некий список на "бумажке", чтоб знать какой элемент что означает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. тот вариант, что я привел - вовсе не оптимальный, просто в нем исправлены Ваши ошибки

2. адрес элемента массива это <имя_массива>+<номер элемента>

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

 

пассаж насчет указания адресов "лежания" для переменных до моего понимания не дошел

 

Пояснение по адресам "лежания":

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

Если будет сделан массив, как Вы предлагаете, то мне придется помнить, какой из элементов массива за что отвечает.

Да, будет очень удобно в этот массив переписывать данные, например, из ПЗУ в одном единственном цикле

for(a=0;a<Lengh;a++){Array[a]=Read_Eprom(a);}

,

но в программе помнить о том, какая ячейка чему соответствует - весьма тяжело, и не исключены ошибки.

Используя прямую адресацию в RAM, типа

 

unsigned int P1x __at(0x00000000000000000)
unsigned int P2x __at(0x00000000000000001)

 

я смогу в одном цикле выполнить действия аналогичные примеры выше, но только с косвенной адресацией

 

unsigned int *sptr;

sptr = & P1x;
for(a=0;a<Lengh;a++;sptr++){*sptr=Read_Eprom(a);}

 

Значения из Eprom автоматом перепишутся по нужным адресам.

Только для этого я предполагаю явное указание адреса.

А в теле программы читать и писать, например, пункт меню Baud_Rate гораздо понятнее и приятнее чем, например, Array[64]

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

присоединяюсь к sergik_vrn

 

Структура, все элементы которой имеют одинаковый тип, явно напрашивается на то, чтобы быть массивом. Тем более, автор сам использует цикл для перебора элементов.

 

Сложно запомнить? Хорошо. А для чего тогда используются комментарии?

 

Комирование структуртоже никто не отменял

 

__eeprom Setup eeSetup;
...
Setup LocalSetup;// Создаем структуру типа Setup
Setup *sptr;// Указатель

LocalSetup = eeSetup;
...
*sptr = eeSetup;

Изменено пользователем zhevak

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Используя прямую адресацию в RAM, типа

 

unsigned int P1x __at(0x00000000000000000)
unsigned int P2x __at(0x00000000000000001)

 

я смогу в одном цикле выполнить действия аналогичные примеры выше, но только с косвенной адресацией

 

unsigned int *sptr;

sptr = & P1x;
for(a=0;a<Lengh;a++;sptr++){*sptr=Read_Eprom(a);}

 

Интересно, ну и что Вы хотели этим пояснить:

unsigned int P1x __at(0x00000000000000000)
unsigned int P2x __at(0x00000000000000001)

:07:

 

Это не скомпилиться без явного приведения типа в нормальном компиляторе:

sptr = & P1x;

если P1x - структура.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почитайте про перечислимый тип (enum).

Именно он напрашивается в качестве индекса массива. Вы получите и массив, допускающий последовательный перебор, и мнемонические имена элементов этого массива.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Сложно запомнить? Хорошо. А для чего тогда используются комментарии?

...

 

Согласитесь, что работать всеже удобнее, когда имя переменной сразу дает полное представление о ней без необходимости плодить пачками комментарии возле строк типа:

array[12] = 9600; // здесь я установил BaudRate

 

К тому же в случае необходимости есть возможность легко ввести в структуру данные других типов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Интересно, ну и что Вы хотели этим пояснить:

unsigned int P1x __at(0x00000000000000000)
unsigned int P2x __at(0x00000000000000001)

:07:

 

Это не скомпилиться без явного приведения типа в нормальном компиляторе:

sptr = & P1x;

если P1x - структура.

 

 

unsigned int  P111 __at (0x40003000);
unsigned int  P112 __at (0x40003002);


int main(void){

unsigned int *aptr;

aptr = & P111;
for(hhh=0;hhh<10;hhh++)
{
  *aptr=hhh;
  aptr++;
} 



}

 

Пардон, скомпилилось без вопросов...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пардон, скомпилилось без вопросов...

Ага, только работать не будет (int по адресу 0x40003002).

Честное слово, не могу понять, что Вам нужно получить в результате - структуру меню с возможностью загрузки из EEPROM? Зачем эти фиксированные адреса и прочие извращения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пардон, скомпилилось без вопросов...

 

Пардон, почему то решил что P1x ранее объявлена как некая структура. Но не понял зачем Вы так делаете, что мешает просто объявить

STRUCT_TYPE P1x;

 

и работать с указателем на нее, чем укладывать все в определенном месте RAM, а потом все арвно придется создавать указатель типа структуры на этот адрес :wacko:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

А в теле программы читать и писать, например, пункт меню Baud_Rate гораздо понятнее и приятнее чем, например, Array[64]

убедился, что все понял правильно, просто формулировка про адреса меня смутила.

посмотрите в треде Вам кто-то уже советовал использовать enum, присоединяюсь. наиболее правильно собирать однотипные элементы в массив, а для адресации на уровне идентификатора использовать enum

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...