Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Re: Вопросы по С/С++ (СИ)

Сообщение Kavka »

pokk писал(а):Это будет так ?
Да. Можно и так. А можно и без структуры.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Реклама
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение YS »

Да. Можно и так. А можно и без структуры.

Да ну? Как по мне, компилятор такое как число не поймет. Правильнее всего сделать через union.

Код: Выделить всё

typedef union {

  int32_t my_long;
  uint8_t my_byte[4];

} my_custom_long;
И далее

Код: Выделить всё

my_custom_long a,b,c;
uint8_t z;

...

a.my_long=1;
b.my_long=2;

...

c.my_long=a.my_long + b.my_long; \\ в 'c' получится 3

...

z=c.my_byte[3]; \\побайтовый доступ к 'c'
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Реклама
Tolmi
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Tolmi »

pokk писал(а): Это будет так ?

Код: Выделить всё

typedef struct {

        char b[3];

} U8long;


U8long *u8 = (U8long*)h;
Нет, скорее так :

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
int main()
{
 float pi=3.141593;
 unsigned char c1,c2,c3,c4;
 unsigned char *cptr=(unsigned сhar*)π
   c1=cptr[0];c2=cptr[1];
   c3=cptr[2];c4=cptr[3];
   printf(" %.02X %.02X %.02X %.02X\n",c1,c2,c3,c4);
 return(0);
}
Это более соответствует смыслу исходного вопроса.
In theory, theory and practice are the same. In practice, they're not.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение aam »

Скажите, а как передать в функцию в качестве параметра массив из EEPROM в IAR AVR?
Допустим, есть массив:

Код: Выделить всё

__eeprom unsigned char eep_RCU_DC[N_BUTTONS]={
               0x00,	//[0] конпка 0
               0x01,	//[1] конпка 1
               0x02,	//[2] конпка 2
               0x03,	//[3] конпка 3
               0x04,	//[4] конпка 4
               0x05,	//[5] конпка 5
               0x06,	//[6] конпка 6
               0x07,	//[7] конпка 7
               0x08,	//[8] конпка 8
               0x09,	//[9] конпка 9};
Объявил функцию:

Код: Выделить всё

unsigned char RCU_Decoder(unsigned char* RCU_DC, unsigned char n_btn);
Но компилятор ругается на несоответствие типов (что и ожидал).

Если я напишу
unsigned char RCU_Decoder(__eeprom unsigned char* RCU_DC, unsigned char n_btn);
Не будет ли компилятор создавать сдуру промежуточный указатель в EEPROM и портить ресурс флешки при каждом вызове функции?

Смысл - будет кнопка типа шифта и хочу сделать разные массивы для двух независимых подфункций устройства, чтобы можно было независимо править коды кнопок.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Re: Вопросы по С/С++ (СИ)

Сообщение Psych »

aam писал(а):Допустим, есть массив:
А квалификатор "const" не толкает в EEPROM??
Реклама
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

Re: Вопросы по С/С++ (СИ)

Сообщение pokk »

Что-то я опять не как понять не могу что это вот за штука ? Это единственное место где uip_udp_new используется.

Код: Выделить всё

struct uip_udp_conn *
uip_udp_new(u16_t *ripaddr, u16_t rport)
{}

struct uip_udp_conn *uip_udp_new(u16_t *ripaddr, u16_t rport);

struct uip_udp_conn {
  u16_t ripaddr[2];   /**< The IP address of the remote peer. */
  u16_t lport;        /**< The local port number in network byte order. */
  u16_t rport;        /**< The remote port number in network byte order. */
};

Полностью struct uip_udp_conn * uip_udp_new(u16_t *ripaddr, u16_t rport)
Спойлер

Код: Выделить всё

struct uip_udp_conn *
uip_udp_new(u16_t *ripaddr, u16_t rport)
{
  register struct uip_udp_conn *conn;

  /* Find an unused local port. */
 again:
  ++lastport;

  if(lastport >= 32000) {
    lastport = 4096;
  }

  for(c = 0; c < UIP_UDP_CONNS; ++c) {
    if(uip_udp_conns[c].lport == lastport) {
      goto again;
    }
  }


  conn = 0;
  for(c = 0; c < UIP_UDP_CONNS; ++c) {
    if(uip_udp_conns[c].lport == 0) {
      conn = &uip_udp_conns[c];
      break;
    }
  }

  if(conn == 0) {
    return 0;
  }

  conn->lport = HTONS(lastport);
  conn->rport = HTONS(rport);
  conn->ripaddr[0] = ripaddr[0];
  conn->ripaddr[1] = ripaddr[1];

  return conn;
}
И используют это всё тоже как-то не сильно понятно я понял тут идёт цикл по адресам. Началу цикла присваивается адрес потом его увеличиваем пока не дойдём до конца структуры(uip_udp_conns[UIP_UDP_CONNS]) только вот не понятно как при следующей итерации uip_udp_conn->lport изменится

Код: Выделить всё

 for(uip_udp_conn = &uip_udp_conns[0];
      uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
      ++uip_udp_conn) {
    if(uip_udp_conn->lport != 0 &&
       UDPBUF->destport == uip_udp_conn->lport &&
       (uip_udp_conn->rport == 0 ||
        UDPBUF->srcport == uip_udp_conn->rport) &&
       BUF->srcipaddr[0] == uip_udp_conn->ripaddr[0] &&
       BUF->srcipaddr[1] == uip_udp_conn->ripaddr[1]) {
         GPIO_ResetBits(GPIOC,GPIO_Pin_13);
      goto udp_found;
    }
  }
Реклама
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение aam »

Что-то запутался как объявлять...
Массив я объявляю так:

Код: Выделить всё

const __eeprom unsigned char eep_RCU_Light[N_BUTTONS]={0, 1....};
Тогда функцию надо объявлять так:

Код: Выделить всё

unsigned char RCU_Decoder(unsigned char const __eeprom * RCU_DC, unsigned char n_btn);
Или куда этот const писать? Я помню, там и так и так можно, но смысл будет разный - в одном случае константный указатель, в другом - указатель на константу. А с учетом "странного" модификатора __eeprom без пол литра не разберешься :facepalm:
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Re: Вопросы по С/С++ (СИ)

Сообщение Psych »

__eeprom убрать надо. Iar константный массив кидает во флешь, можно посмотреть в map файле. Можно еще через pragma location, но через const и так норм фурычит.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение aam »

А я в EEPROM именно хотел - ато потом искать этот массив по всей проге. А тут четко ясно где лежит таблица кнопок и нет опасности повредить прогу если просчитаешься.
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Re: Вопросы по С/С++ (СИ)

Сообщение Psych »

aam писал(а):А я в EEPROM именно хотел
Psych писал(а):Iar константный массив кидает во флешь
Или я чет не понимаю??
aam писал(а): ато потом искать этот массив по всей проге
Зачем искать? eep_RCU_Light -адрес первого элемента.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение aam »

Написал:

Код: Выделить всё

unsigned char RCU_Decoder( unsigned char const* RCU_DC, unsigned char n_btn);
const __eeprom unsigned char eep_RCU_Light[]={...};
Не катит:
Error[Pe167]: argument of type "unsigned char const __eeprom *" is incompatible with parameter of type "unsigned char const *"

Когда было

Код: Выделить всё

unsigned char RCU_Decoder( unsigned char const __eeprom* RCU_DC, unsigned char n_btn);
прокатывало без ошибок
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Re: Вопросы по С/С++ (СИ)

Сообщение Psych »

Я имел ввиду так:

Код: Выделить всё

unsigned char RCU_Decoder( unsigned char const* RCU_DC, unsigned char n_btn);
const  unsigned char eep_RCU_Light[]={...};
Так тоже должно канать.


На счет:
aam писал(а):если я напишу
unsigned char RCU_Decoder(__eeprom unsigned char* RCU_DC, unsigned char n_btn);
Не будет ли компилятор создавать сдуру промежуточный указатель в EEPROM и портить ресурс флешки при каждом вызове функции?
Имя массива это константный указатель(адресс известен), при вызове функции компилятор просто передаст число(адресс) в функцию.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение aam »

Ну так вот не канает
aam писал(а):Написал:
Код:
unsigned char RCU_Decoder( unsigned char const* RCU_DC, unsigned char n_btn);
const __eeprom unsigned char eep_RCU_Light[]={...};
Не катит
:(

Насчет
Psych писал(а):при вызове функции компилятор просто передаст число(адресс) в функцию
было интересно, насколько "законна" такая запись с точки зрения спецификации Си. Ато иногда компиляторы "имеют свое мнение", в частности, CodeVision этим славится в плане вычисления арифметических выражений дефайнов (правда там речь идет о препроцессоре)
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Re: Вопросы по С/С++ (СИ)

Сообщение Psych »

Код: Выделить всё

unsigned char RCU_Decoder( unsigned char const* RCU_DC, unsigned char n_btn);
const __eeprom unsigned char eep_RCU_Light[]={...};

Код: Выделить всё

unsigned char RCU_Decoder( unsigned char const* RCU_DC, unsigned char n_btn);
const  unsigned char eep_RCU_Light[]={...};
Че прям нет разницы??!!
aam писал(а):было интересно, насколько "законна" такая запись с точки зрения спецификации Си
Си не причем, это:
aam писал(а): компиляторы "имеют свое мнение"
К примеру:
const int x=10; и #define x 10
Одно и тоже(памяти не выделяется), только в первом случае подставит компилятор, во втором препроцессор. вот только рекомендуют компилятор предпочитать препроцессору...это я так на всякий случай :lol:
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение aam »

Psych писал(а):Че прям нет разницы??!!
А, все, понял...
В этом случае компилятор пихнет массив во флеш. А я (или не я) буду отыскивать этот массив по всей флеше если захочу назначить функциям устройства другие кнопки другого пульта. Собственно поэтому я и засунул массив в EEPROM, т. к. там видно где он лежит, чисто эргономически.
Иначе я вообще забил бы на массивы и тупо вбил бы коды кнопок в кейсы свича.

Насчет препроцессора - это я к слову. Была у меня 1 раз тема, когда препроцессор CVAVR правильно, но "незаконно" вычислял константное выражение, которое неправильно вычислил бы "законный" Сишный компилятор, четко следующий правилам раскрытия скобок и размерам чисел в байтах. Грубо говоря, там просто вышло бы переполнение и неправильный результат, т. к. все переменные были 8-разрядные, константа - тоже, но при вычислении константы на этапе компиляции могло быть "переполнение".
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение aam »

Скажите, а как в IAR можно производить запись в EEPROM по указателю?

Допустим, у меня объявлены переменные в EEPROM:

__eeprom unsigned char eep_a;
__eeprom unsigned char eep_b;
__eeprom unsigned char eep_c;
...

В программе у меня увеличивается или уменьшается значение параметров пока удерживается кнопка пульта. Естественно, запись произведенной настройки в EEPROM надо производить после отпускания.
Как правильно написать функцию, которой передаю адрес переменной (например, eep_b) и значение, а функция выкидывает его по указанному адресу?
Могу ли я получить адрес переменной написав &eep_b ?
Что из себя представляет указатель вида
unsigned char __eeprom * Adress ?

Как передавать значение переменной?
Допустим пишу так:

Код: Выделить всё

unsigned char __eeprom * Adress;
unsigned char b;                           //параметр
__eeprom unsigned char eep_b;     //его копия в EEPROM

Adress=&eep_b;
*Adress=b;
Это правильно? Переменная Adress в этом случае будет представлять из себя unsigned int ?
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение YS »

По-моему, IAR берет запись в EEPROM на себя. Т.е., можно просто присваивать значение, как обычной переменной. Но лучше уточнить в документации.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

Re: Вопросы по С/С++ (СИ)

Сообщение aam »

Да я знаю, что присваивать можно, но мне то надо писать конкретную переменную, а не все сразу по событию отпускания одной кнопки.
***
Закончилась моя прога(
До этого смотрел в листинг - вроде памяти еще оставалось. А щас стал в очередной раз компилить, а линкер пишет:

Код: Выделить всё

Error[e16]: Segment TINY_ID (size: 0x2a align: 0) is too long for segment definition. At least 0x2 more bytes needed.  
The problem occurred while processing the segment placement command  
"-Z(CODE)TINY_ID=_..X_FLASH_BASE-_..X_FLASH_END", where at the moment of placement the available memory  
ranges were "CODE:7d8-7ff" 
   Reserved ranges relevant to this placement: 
   CODE:26-2e           NEAR_F 
   CODE:2f-32           INITTAB 
   CODE:33-7d7          CODE 
   CODE:7d8-7ff         TINY_ID 
Error while running Linker 
Открыл HEX - Тинька под завязку забита(( Открыл листинг, а там фраза:

Код: Выделить всё

    20 bytes in segment ABSOLUTE
 1 374 bytes in segment CODE
    31 bytes in segment EEPROM_I
     4 bytes in segment INITTAB
     6 bytes in segment INTVEC
     9 bytes in segment NEAR_F
    38 bytes in segment TINY_I
    38 bytes in segment TINY_ID
 
 1 421 bytes of CODE  memory (+ 10 bytes shared)
    38 bytes of DATA  memory (+ 20 bytes shared)
    31 bytes of XDATA memory

Errors: none
Warnings: none
Т. е. выходит, по результатам компиляции занято 1421 байта во флэш, которая 2048. А прога не лезет
Как так?? :shock:

Оптимизацию на максимум поставил по размеру. Прога еще далека от завершения. Вот теперь не знаю что делать...
***


Скажите, а как заставить компилятор гарантированно подставлять inline-функцию?
Либо как объявить дефайнами макрос на много строк?
Просто некоторые куски кода для логичности и модульности я оформил как функции. Но эти куски вызываются в программе только в одном месте, т. е. фактически могут быть заменены на код из тела этих функций. Соответственно, так можно избавиться от всякой лабуды со стеком, которую компилятор обязан пихать в "настоящую" функцию.
Как так сделать?
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение YS »

как заставить компилятор гарантированно подставлять inline-функцию?
Ну, можно попробовать выбрать в настройках (у Вас же IAR?) опцию agressive inlining (кажется, так называется).
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Re: Вопросы по С/С++ (СИ)

Сообщение Psych »

force inline что-то типо такого
Ответить

Вернуться в «Разные вопросы по МК»