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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Определение указателя
ISK2010
сообщение Sep 2 2011, 13:05
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



Использую Keil....

Есть переменная a. Теперь каким-то образом хочу указатель на int "b" не просто определить как адрес переменной "а", а используя некое константное выражение:

CODE
u32 a;

u32 *b = (u32*)(((u32)(&a) - 0x40000000)*32 + 0x42000000);


Но компилятор выдает ошибку типа "не константное выражение". Но я то знаю, что константное.

Что делать? Вариант проинициализировать этот указатель b перед использованием отпадает, т.к. он уже используется)

P.S. Это мне нужно для побитовых операций с некоторыми переменными в STM32F1xx.




Go to the top of the page
 
+Quote Post
GetSmart
сообщение Sep 2 2011, 13:38
Сообщение #2


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата
Что делать? Вариант проинициализировать этот указатель b перед использованием отпадает, т.к. он уже используется)

Непонятно, как уже используется?


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
xemul
сообщение Sep 2 2011, 13:47
Сообщение #3



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(ISK2010 @ Sep 2 2011, 17:05) *
Но компилятор выдает ошибку типа "не константное выражение". Но я то знаю, что константное.

Вы можете на этапе компиляции сказать, по какому адресу живёт a? Вот и компилятор не может.
Цитата
Вариант проинициализировать этот указатель b перед использованием отпадает, т.к. он уже используется)

"П-п-прведи". (С)
Если что-то до такой степени мешает инициализировать b перед первым использованием, напишите свой init().
Go to the top of the page
 
+Quote Post
777777
сообщение Sep 2 2011, 14:19
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(ISK2010 @ Sep 2 2011, 17:05) *
Есть переменная a. Теперь каким-то образом хочу указатель на int "b" не просто определить как адрес переменной "а", а используя некое константное выражение:
<...>

Ничченепонимаю. Ты можешь словами объяснить, куда должен указывать b?
Go to the top of the page
 
+Quote Post
ISK2010
сообщение Sep 2 2011, 17:13
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



Цитата(GetSmart @ Sep 2 2011, 17:38) *
Непонятно, как уже используется?
Я вас запутал. Имел в виду, что вариант этот уже используется.

Цитата(xemul @ Sep 2 2011, 17:47) *
Вы можете на этапе компиляции сказать, по какому адресу живёт a? Вот и компилятор не может.
Я не могу, а keil может. Например, определение: "u32 *b = (u32*)(((u32)(&a) - 0x40000000) + 0x42000000);" работает. А вот стоит добавить что-то сложнее вычитания или сложения, то ошибка.
Цитата(xemul @ Sep 2 2011, 17:47) *
"П-п-прведи". (С) Если что-то до такой степени мешает инициализировать b перед первым использованием, напишите свой init().
Я свой инит итак использую, но это не по феншую, и я думаю, что есть более хитрое решение.


Цитата(777777 @ Sep 2 2011, 18:19) *
Ничченепонимаю. Ты можешь словами объяснить, куда должен указывать b?
b должен указывать туда, куда мы определим с помощью мегаформулы из адреса &а. Если конкретно, то в моем случае b указывает на начало a в битбенд области ОЗУ.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Sep 2 2011, 20:49
Сообщение #6


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Цитата
u32 *b = (u32*)(((u32)(&a) - 0x40000000)*32 + 0x42000000);

Мисье знает толк в извращениях )))

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


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Sep 3 2011, 05:26
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Цитата
А вот стоит добавить что-то сложнее вычитания или сложения, то ошибка.


Почитайте стандарт (или любую книжку по Си).
С указазателями можно выполнять ТОЛЬКО следущие операции:
  • & - взятие адреса
  • * - взятие значения
  • присвоение указателей
  • сложение/вычитание указателя и целого числа
  • сравнение указателей
  • присвоение нуля и сравнение с ним
  • Может что еще забыл!?!?


И ВСЕ!!!!
В этом списке нету ни умножения, ни деления, ни даже возведения в степень.
А теперь посмотрите на свой код и скажите какая операция лишняя??
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Sep 3 2011, 05:48
Сообщение #8


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



В рунтайме любые операции работают. На этапе компиляции ограниченное кол-во.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Палыч
сообщение Sep 3 2011, 07:05
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(GetSmart @ Sep 3 2011, 09:48) *
В рунтайме любые операции работают. На этапе компиляции ограниченное кол-во.

Какие операции "не работают" на этапе компиляции в примере ТС ? Я понимаю, что значение адреса переменной на этапе компиляции неизвестно, будет определено позже линковщиком, а в примере ТС значение этого адреса на что-то там умножается... В общем, я бы с Вами согласился, о том, что не все операции "работают" при компиляции, но (!) давайте упростим пример ТС до такого
Код
u32 * b = (u32 *)( (u32)(&a) );
Что мы видим? Компилятор считает это неконстантным выражением. Пробуем найти: какая часть этого выражения - "не константа" с точки зрения компилятора?
Код
u32   c = (u32)(&a);
Здесь всё нормально. Выходит, что преобразование u32 в указатель делает выражение неконстантным? Пробуем:
Код
u32 * d= (u32 *)( 0x200UL );
Тоже - всё нормально. Так почему же не "работает" u32 * b = (u32 *)( (u32)(&a) ) ? Кто может объяснить?

P.S. А, таким образом извращатся с адресами я бы ТС не рекомендавал - нужно искать друкое решение Вашей залачи.
Go to the top of the page
 
+Quote Post
ISK2010
сообщение Sep 3 2011, 08:15
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



Цитата(Палыч @ Sep 3 2011, 11:05) *
Какие операции "не работают" на этапе компиляции в примере ТС ? Я понимаю, что значение адреса переменной на этапе компиляции неизвестно, будет определено позже линковщиком, а в примере ТС значение этого адреса на что-то там умножается... В общем, я бы с Вами согласился, о том, что не все операции "работают" при компиляции, но (!) давайте упростим пример ТС до такого
Код
u32 * b = (u32 *)( (u32)(&a) );
Что мы видим? Компилятор считает это неконстантным выражением. Пробуем найти: какая часть этого выражения - "не константа" с точки зрения компилятора?


Не работает умножение 32. А пример u32 * b = (u32 *)( (u32)(&a) ); работает в keil.


С помощью этой формулы я получаю адрес начала структуры флагов в битбенд области ОЗУ. И обращаюсь к каждому флагу в отдельности. На данный момент это очень оказалось кстати. Например, раньше я работал с флагами через маски или флаги делал 8битными. И к этом флагам добавлял флаги "занятости флагов", дабы не произошло ошибок чтения-модификации-записи. А с битбендом отказался от всего этого. Никаких масок и проблем.

Сейчас адрес начала флагов в битбенд области ОЗУ расчитываю в функции инициализации флагов. и к любому флагу обращаюсь так:
Код
*(u32*)((u32)Addr_BB_Flags + NumberOfFlag<<2) = 1; //установка флага
*(u32*)((u32)Addr_BB_Flags + NumberOfFlag<<2) = 0; //сброс
и все замечательно работает.

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

Сообщение отредактировал ISK2010 - Sep 3 2011, 08:18
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Sep 3 2011, 08:28
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Код
Тоже - всё нормально. Так почему же не "работает" u32 * b = (u32 *)( (u32)(&a) ) ? Кто может объяснить?


У меня все работает. Компилируется без ошибок. Правда не в Keil.
И синтаксически это правильное выражение.

Для ТС.
Уберите умножение из выражения работы с указателями. Ни один компилятор не должен поддерживать операцию умножения с указателями.



Сообщение отредактировал alexeyv - Sep 3 2011, 08:29
Go to the top of the page
 
+Quote Post
ISK2010
сообщение Sep 3 2011, 08:44
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 21-09-10
Из: г.Зеленоград
Пользователь №: 59 631



Нашел еще одно решение) Тупо заставил запихнуть мои флаги по конкретному адресу ОЗУ 0x20004000 и на калькуляторе рассчитал адрес зеркала в бидбенд области = 0x220C8000. Но это опять не по феншую
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Sep 3 2011, 09:34
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



У вас в начале топика в корне не правильная формула расчета

д.б. примерно так:
Код
// в  начале файла, если этипеременные глобальные:
u32 a;
u32 *b;

// в теле какой-либо функции, перед использованием b:
b = (u32 *)( 0x22000000 + ((u32)(&a)- 0x20000000)*32);


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

Если же вы хотите задать значение "b" на этапе компиляции, то возможно вам надо расположить "a" по строго определенному адресу. Для этого изучайте директивы линковщика и компилятора.

Цитата
A mapping formula shows how to reference each word in the alias region to a corresponding
bit in the bit-band region. The mapping formula is:
bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number × 4)
where:
bit_word_addr is the address of the word in the alias memory region that maps to the
targeted bit.
bit_band_base is the starting address of the alias region
byte_offset is the number of the byte in the bit-band region that contains the targeted bit
bit_number is the bit position (0-7) of the targeted bit.
Example:
The following example shows how to map bit 2 of the byte located at SRAM address
0x20000300 in the alias region:
0x22006008 = 0x22000000 + (0x300*32) + (2*4).
Writing to address 0x22006008 has the same effect as a read-modify-write operation on bit
2 of the byte at SRAM address 0x20000300.
Reading address 0x22006008 returns the value (0x01 or 0x00) of bit 2 of the byte at SRAM
address 0x20000300 (0x01: bit set; 0x00: bit reset).


Сообщение отредактировал alexeyv - Sep 3 2011, 09:35
Go to the top of the page
 
+Quote Post
skripach
сообщение Sep 3 2011, 10:02
Сообщение #14


■ ■ ■ ■
*****

Группа: Свой
Сообщений: 1 100
Регистрация: 9-08-06
Пользователь №: 19 443



Цитата
А пример u32 * b = (u32 *)( (u32)(&a) ); работает в keil.

Я бы на месте компилятора такое глотать не стал sm.gif, хотя в IAR тоже работает, вернее компилится, а работает или нет не проверял.


--------------------
Делай что должен и будь что будет.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Sep 3 2011, 10:40
Сообщение #15


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(alexeyv @ Sep 3 2011, 12:34) *
Дело в том что на этапе компиляции, еще не известны все адреса и компилятор не может вычислить такое сложное выражение
Это, вообще говоря, не компиляторово дело, а линкерово. Компилятор и &a может только записать как «а туда затолкай адрес вон того» (особенно при extern u32 a).
Если линкер не позволяет задать ему сложные выражения (из известных на этапе линковки величин!), то ничего и не выйдет.

Цитата(alexeyv @ Sep 3 2011, 12:34) *
Но в теле какой-либо функции можно схитрить, вычислив адрес как простое арифметическое выражение и преобразовать его в адрес.
В режиме С++ катит и строка из корневого сообщения -- компилятор просто создаст функцию-инициализатор для b и затолкает её в таблицы на правах конструктора.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

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

 


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


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