Страница 236 из 386

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

Добавлено: Пт май 13, 2016 14:17:13
Apparatchik

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

typedef struct {
   uint8_t pole_1 :1;
   uint8_t pole_2 :4;
   uint8_t pole_3 :3;
} my_struct_type;


my_struct_type my_struct = {
   1,
   13,
   255
};
так будет правильно? несмотря на 255 я получу в третьем поле 7.

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

Добавлено: Пт май 13, 2016 14:26:25
WiseLord
Да, с соответствующим предупреждением компилятора:

Изображение

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

Добавлено: Пт май 13, 2016 16:38:41
Аlex
Apparatchik писал(а):так будет правильно? несмотря на 255 я получу в третьем поле 7.
Где логика, записывать в 3 бита, число, превышающее 7 ? :dont_know:

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

Добавлено: Вт май 24, 2016 21:14:31
Darkmaster
Доброго времени.Может кто то пояснить следующую запись

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

 #define  Maycount               ((unsigned char) 0x22) 
в частности что дает Unsigned char..и где подобное можно использовать ?

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

Добавлено: Вт май 24, 2016 22:45:13
Siarzhuk
Darkmaster писал(а):в частности что дает Unsigned char..
ЕМНИП если знаковость типа не указана явно - то предполагается signed. Если нужен беззнаковый - тогда и осуществляем вот такой акт насилия над компилятором, выражающийся в явном приведении. Шестнадцатиричная константа имеет тип int. Напрямую скормить её, например, функции, ожидающей параметром unsigned char, уважающий себя компилятор не позволит. Приведение-же типа позволяет без помех "прострелить себе ногу".
Darkmaster писал(а):и где подобное можно использовать ?
Там где ждут именно unsigned char. Ну ешё в восьмибитном ембединге существует поверье, что если все целочисленные объявлять байтовыми - то будет всё работать легко и приятно. По крайней мере изучение соответствуюших продуктов жизнедеятельности обитателей оной области оставляет подобное ощущение. ;)

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

Добавлено: Вт май 24, 2016 23:00:42
Darkmaster
Siarzhuk с этим понятно давно)
уточню..интересует именно макрос .Который я написал выше.
Ведь можно написать

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

#define Maycount     0x25 

мы же добавили ишо и '(unsigned char)'

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

Добавлено: Ср май 25, 2016 08:42:54
Siarzhuk
Darkmaster писал(а):с этим понятно давно) .... мы же добавили ишо и '(unsigned char)'
Чтобы привести константу 0х22, имеющую тип int, к типу unsigned char. Для чего - тут уж по коду смотреть надо в какие "физиологические полости" программы глубокоуважаемый автор эту подстановку пристраивает. Видать там, в этих местах, были не очень рады int-у - вот и заткнули рот компилятору, чтобы не вякал.

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

Добавлено: Ср май 25, 2016 09:07:41
Darkmaster
Siarzhuk пасибки.примерно так я думал ,что ничего интересного это не несет
строка кстати из кода под STM8..
Странно конечно

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

Добавлено: Сб май 28, 2016 06:03:23
WiseLord
Вроде уже давно на C пишу, но вчера попался на достаточно забавный "крючок" с приведением типов.

Реализовывал NEC протокол пульта ДУ, там передаются 32 бита данных (16 бит адрес, команда и команда инверсно). Получился такой вод код (исходники структуры и проверки принятого на валидность):

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

...
typedef union {
	uint32_t raw;
	struct {
		uint8_t laddr;
		uint8_t haddr;
		uint8_t cmd;
		uint8_t ncmd;
	};
} NECCmd;
...
...
if ((uint8_t)(~necCmd.ncmd) == necCmd.cmd) {
  // команда валидна, можно обрабатывать
}
...
Тонкость заключалась в том, что без приведения типов в условии if оно не отрабатывало. То есть, несмотря на то, что вроде как и cmd, и ncmd - оба uint8_t, но результат инверсии битов получался не 8-битный. То есть, если объяснить более простым кодом, то

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

uint8_t a = 0b11001010;
uint8_t b = 0b00110101;
условие

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

if (~a == b) {
  ...
}
Не отработает, и будет вообще при оптимизиации выброшено, ибо фактически компилятор будет делать следующее

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

if (0b11111111 00110101 == 00110101) {
  ...
}
То есть результат побитовой инверсии 8-бит числа вовсе даже не 8-битен.

Вот такое вот неочевидное поведение компилятора, в которое никак не мог въехать.

P. S. "Большой" компилятор выдаёт предупреждение (решил сейчас проверить, уже после написания сообщения), avr-gcc же молчал как партизан:

Изображение

С знаковыми int8_t такого предупреждения нет и всё отрабатывает, как ожидалось.

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

Добавлено: Сб май 28, 2016 08:34:23
Siarzhuk
WiseLord писал(а):фактически компилятор будет делать следующее

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

if (0b11111111 00110101 == 00110101) {
  ...
}
То есть результат побитовой инверсии 8-бит числа вовсе даже не 8-битен.
Подозреваю, что справа там тоже не 00110101 а 00000000 00110101 - т.е. полновесный int как результат implicit conversion в контексте if. PS: И как по мне 0xFF & результата инверсии менее парадоксально выглядит в глазах потомков чем приведение. :)
WiseLord писал(а):Вот такое вот неочевидное поведение компилятора, в которое никак не мог въехать.
О да, тоже люблю такие случаи - как повод залезть в писания святых отцов и приобшиться к ещё одной крупице тайного знания, которое в беглом прочтении может быть понято лишь [практическими] шишками на определённых местах лобной стенки черепной коробки. PS: Заодно и повод разобраться с integer promotions - если ещё не. ;)

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

Добавлено: Сб май 28, 2016 09:12:40
WiseLord
Что самое забавное, так то, что будь это x86 - 32-разрядной архитектуре, то ладно. Но ведь это на 8-битном AVR происходило, вот в чём прикол.

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

Добавлено: Сб май 28, 2016 10:36:40
Apparatchik
Я, для простоты, плюсую прямую и инверсную часть команды если получаю 0xFF значит все верно можно обрабатывать. Пока работает без збоев.

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

Добавлено: Сб май 28, 2016 11:55:56
Siarzhuk
WiseLord писал(а):Но ведь это на 8-битном AVR происходило, вот в чём прикол.
Компилятору виднее. Так, глядя на результат инверсии, sizeof(int) небось 2 рапортует.

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

Добавлено: Вт июн 07, 2016 06:00:15
Триод
Задал вопрос здесь, но всё же вопрос ближе к данному топику.

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

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

#include "stm32f2xx_hal.h"

CAN_HandleTypeDef hcan1;
static void MX_CAN1_Init(void);

int main(void)
{

  while (1)
  {
 
//Смотрю значения до присваивания и вывожу в UART. Результат следующий: по идее, там - мусор)
  hcan1.pTxMsg->DLC = 0xF5;
  hcan1.pTxMsg->Data[0] = 0xE1;
  hcan1.pTxMsg->Data[1] = 0x01;
  hcan1.pTxMsg->Data[2] = 0x00;
  hcan1.pTxMsg->Data[3] = 0x08;
  hcan1.pTxMsg->Data[4] = 0x1B;           
  hcan1.pTxMsg->Data[5] = 0x19;           
  hcan1.pTxMsg->Data[6] = 0x00;           
  hcan1.pTxMsg->Data[7] = 0x08; 
  
//Присваиваю значения членам структуры pTxMsg

  hcan1.pTxMsg->DLC = 0x08;
  hcan1.pTxMsg->Data[0] = 0x00;
  hcan1.pTxMsg->Data[1] = 0x01;
  hcan1.pTxMsg->Data[2] = 0x02;
  hcan1.pTxMsg->Data[3] = 0x03;
  hcan1.pTxMsg->Data[4] = 0x04;           
  hcan1.pTxMsg->Data[5] = 0x05;           
  hcan1.pTxMsg->Data[6] = 0x06;           
  hcan1.pTxMsg->Data[7] = 0x07;  
  
//Смотрю значения членов структуры после присваивания и вывожу в UART. Результат -  тот же самый мусор

  hcan1.pTxMsg->DLC = 0xF5;
  hcan1.pTxMsg->Data[0] = 0xE1;
  hcan1.pTxMsg->Data[1] = 0x01;
  hcan1.pTxMsg->Data[2] = 0x00;
  hcan1.pTxMsg->Data[3] = 0x08;
  hcan1.pTxMsg->Data[4] = 0x1B;           
  hcan1.pTxMsg->Data[5] = 0x19;           
  hcan1.pTxMsg->Data[6] = 0x00;           
  hcan1.pTxMsg->Data[7] = 0x08;
  
  
  }


}


/* CAN1 init function */
void MX_CAN1_Init(void)
{

  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 5;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SJW = CAN_SJW_1TQ;
  hcan1.Init.BS1 = CAN_BS1_6TQ;
  hcan1.Init.BS2 = CAN_BS2_5TQ;
  hcan1.Init.TTCM = DISABLE;
  hcan1.Init.ABOM = DISABLE;
  hcan1.Init.AWUM = DISABLE;
  hcan1.Init.NART = DISABLE;
  hcan1.Init.RFLM = DISABLE;
  hcan1.Init.TXFP = DISABLE;
  HAL_CAN_Init(&hcan1);

}

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

* @file    stm32f2xx_hal_can.h
 typedef struct
{
  CAN_TypeDef                 *Instance;  /*!< Register base address          */

  CAN_InitTypeDef             Init;       /*!< CAN required parameters        */

  CanTxMsgTypeDef*            pTxMsg;     /*!< Pointer to transmit structure  */

  CanRxMsgTypeDef*            pRxMsg;     /*!< Pointer to reception structure */

  __IO HAL_CAN_StateTypeDef   State;      /*!< CAN communication state        */

  HAL_LockTypeDef             Lock;       /*!< CAN locking object             */

  __IO uint32_t               ErrorCode;  /*!< CAN Error code                 */

}CAN_HandleTypeDef;

typedef struct
{
  uint32_t Prescaler;  /*!< Specifies the length of a time quantum.
                            This parameter must be a number between Min_Data = 1 and Max_Data = 1024 */

  uint32_t Mode;       /*!< Specifies the CAN operating mode.
                            This parameter can be a value of @ref CAN_operating_mode */

  uint32_t SJW;        /*!< Specifies the maximum number of time quanta
                            the CAN hardware is allowed to lengthen or
                            shorten a bit to perform resynchronization.
                            This parameter can be a value of @ref CAN_synchronisation_jump_width */

  uint32_t BS1;        /*!< Specifies the number of time quanta in Bit Segment 1.
                            This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_1 */

  uint32_t BS2;        /*!< Specifies the number of time quanta in Bit Segment 2.
                            This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */

  uint32_t TTCM;       /*!< Enable or disable the time triggered communication mode.
                            This parameter can be set to ENABLE or DISABLE. */

  uint32_t ABOM;       /*!< Enable or disable the automatic bus-off management.
                            This parameter can be set to ENABLE or DISABLE */

  uint32_t AWUM;       /*!< Enable or disable the automatic wake-up mode.
                            This parameter can be set to ENABLE or DISABLE */

  uint32_t NART;       /*!< Enable or disable the non-automatic retransmission mode.
                            This parameter can be set to ENABLE or DISABLE */

  uint32_t RFLM;       /*!< Enable or disable the receive FIFO Locked mode.
                            This parameter can be set to ENABLE or DISABLE */

  uint32_t TXFP;       /*!< Enable or disable the transmit FIFO priority.
                            This parameter can be set to ENABLE or DISABLE */
}CAN_InitTypeDef;

typedef struct
{
  uint32_t StdId;    /*!< Specifies the standard identifier.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF */

  uint32_t ExtId;    /*!< Specifies the extended identifier.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF */

  uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.
                          This parameter can be a value of @ref CAN_Identifier_Type */

  uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.
                          This parameter can be a value of @ref CAN_remote_transmission_request */

  uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 8 */

  uint8_t Data[8];   /*!< Contains the data to be transmitted.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */

}CanTxMsgTypeDef

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

Добавлено: Пт июн 10, 2016 11:47:52
Триод
Свой вопрос снимаю

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

Добавлено: Чт июн 16, 2016 18:06:10
uldemir
У меня тоже есть снова вопрос. Пишу в Keil-е. Есть функция для посылки данных через i2c описанная так:

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

t_i2c_status i2c_wr_reg(unsigned char address, unsigned char reg_addr, char * data, unsigned char length);
Так вот, если я хочу в data передать длинную инициализационную последовательность. последовательность не меняется и потому в ОЗУ держать нет смысла. Значит объявляю константой:

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

const char init_sequence[] = {
        // Init sequence for 128x64 OLED module
    SSD1306_DISPLAYOFF,
....
    SSD1306_DISPLAYON //--turn on oled panel
}
В результате получаю ошибку:

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

main.c(178): error:  #167: argument of type "const char *" is incompatible with parameter of type "char *"
        i2c_wr_reg(SD1306_I2C_ADDRESS, 0x00, init_sequence, sizeof(init_sequence));
main.c: 0 warnings, 1 error
Потом, почему-то, не позволет объявление этого массива сделать непосредственно рядом с вызовом этой функции (хотя IAR на это не возражал). Самое интересное, если бы инициализационные коды были бы печатные, то конструкция

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

i2c_wr_reg(SSD1306_I2C_ADDRESS, 0x00, "start_sequence", sizeof(init_sequence)); 
пороходит, несмотря на то, что ему в данном случае передаётся константная строка.

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

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

Добавлено: Чт июн 16, 2016 20:33:40
WiseLord
А если в аргументах функции передавать не прямо init_sequence, а с приведением типа: (char *)init_sequence?

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

Добавлено: Чт июн 16, 2016 20:43:27
uldemir
Да, спасибо, этот вариант прокатил.

Ах! вот если бы еще была возможность передавать эти последовательности неименованными...

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

Добавлено: Чт июн 16, 2016 23:09:05
Siarzhuk
uldemir писал(а):Потом, почему-то, не позволет объявление этого массива сделать непосредственно рядом с вызовом этой функции (хотя IAR на это не возражал).
А что говорит? Попробуйте static - это выпихнет локальную переменную в глобальную область, сохранив её видимость локальной.
uldemir писал(а):Самое интересное, если бы инициализационные коды были бы печатные, то конструкция
В строковый литерал можно запихать всё что угодно: "\x00\xFFHalli\xCCHallo!\x1F", ещё можно каждый код задефайнить как строчку
#define AGA "\xFF"
#define OGO "\x00"
#define UGU "\xCC"

i2c_wr_reg( ..., AGA OGO UGU AGA, ...);

компилятор её склеит в один литерал и подставит при оформлении вызова.
uldemir писал(а):пороходит, несмотря на то, что ему в данном случае передаётся константная строка.
константная строка и массив константных символов - судя по всему для него [компилятора] различные типы. Гораздо интереснее, что он не ругается на снятие const при такой передаче - ведь внутри функции это обычный указатель - в который функция может нагадить.
uldemir писал(а):Вопрос собственно и состоит, как эту инициализационную последовательность изящно засунуть в память программ не куроча функцию.
Вопрос в том, что семантика функции предполагает модификацию передаваемого буффера - мол, не огорожен указатель const-ом - не говорите что вас не предупреждали. ;) У прожжёного дизайнера библиотек в определении отдаваемого на передачу буфера обязательно const будет.

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

Добавлено: Пт июн 17, 2016 05:39:58
uldemir
Siarzhuk писал(а):А что говорит?

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

main.c(211): error:  #268: declaration may not appear after executable statement in block
        char start_col[] = {SSD1306_COLUMNADDR, 0, SSD1306_LCDWIDTH-1, SSD1306_PAGEADDR, 0, 7};
main.c: 0 warnings, 1 error
т.е. совершенно это неприемлет. Хотя, помнится, в IARе такое делал. Сейчас не могу найти тот кусок, потому как я его переписал иначе (без таблиц).
Siarzhuk писал(а):В строковый литерал можно запихать всё что угодно: "\x00\xFFHalli\xCCHallo!\x1F",
Способ интересный, но тогда снова придётся делать два комплекта дефайнов - для констант и для строк. Ладно, попробую обойтись.
Siarzhuk писал(а):У прожжёного дизайнера библиотек в определении отдаваемого на передачу буфера обязательно const будет.
О! это хорошо решает проблему. Спасибо. жаль только, не могу найти хорошую библиотеку для мастера I2C для stm32f0. Приходится дёргать огрызки из разных источников.