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

А ни разу не сталкивались, когда при очередной модификации кода (через 10*N месяцев) в 16 бит переменной (поле структуры) нечаянно пытались освоить биты >16?

Ну, да, действительно - гораздо разумнее весь код загромождать избыточной информацией ради гипотетической штучной проблемы с переполнением "через 10*N месяцев".

В таком случае, предлагаю в название переменной добавлять не только ее тип, а еще секцию памяти, где она лежит, область видимости, дату ее создания и еще бог знает что :wacko:

 

Кроме шуток, существует весьма полезная вещь - sizeof, или для более продвинутых: (1 << ( sizeof(...)*8 ) ) - 1

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


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

А ни разу не сталкивались, когда при очередной модификации кода (через 10*N месяцев) в 16 бит переменной (поле структуры) нечаянно пытались освоить биты >16?

нет, ни разу. никогда к битам не обращяюсь напрямую типа a |= (1 << 24); Только через дефайны. a |= STATE_A;

хидере пишу что-то типа такого

#define STATE_A (1<<0)
#define STATE_B (1<<1)
#define STATE_C (1<<2)
...
#define STATE_x (1<<15)

uint16_t state = STATE_C | STATE_B | STATE_F;

определяя новый дефайн всегда помню(проверяю) про размерность переменной. это раз....

 

и второй подход - это битовые поля. например так

typedef union
{
    struct
    {
        uint16_t enterTrip         :1; //
        uint16_t exitTrip         :1;
        uint16_t printTrip         :1;
        uint16_t printCheck1     :1;
        uint16_t printCheck2     :1; //
                uint16_t printCheck3     :1; //
        uint16_t printTest         :1;
        uint16_t setTime         :1;
        uint16_t getTime         :1;
        uint16_t setLine         :1;
        uint16_t getLine         :1;
        uint16_t setColor    :1;
        uint16_t getColor    :1;

        uint16_t rezerv :3;
                //uint16_t rezerv2 :16;//для выравнивания в 32 можно раскоментировать
    } flags;
    uint16_t word;//если раскоментирован флаг rezerv2, то закоментировать
        //uint32_t word;//если раскоментирован флаг rezerv2, то раскоментировать
} FlagsKL;
....
FlagsKL flagsKL;
flagsKl.word = 0;//сброс всех бит в ноль
flagsKL.flags.printCheck2 = 1;//установить бит 4 в 16-ти битной переменной

при таком написании вообще пофиг в каком месте биты стоят.... printCheck2 - 4-ый или 8-ой. при таком подходе... не возможно ошибиться и вылезти за размер 16 бит.

 

бывало такое

uint8_t asd;
.... 
asd = 300;

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

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


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

и второй подход - это битовые поля

А, если еще компилятор поддерживает безымянные объединения, то получается полный феньшуй:

 

typedef struct // Frame
{
    struct // Supported only 11-bit ID (CAN 2.0A)
    {
        UNSIGNED1 nodeId : 7;
        UNSIGNED1 functionCode : 4;
    } cobId;

    bool        isRemoteTransmitionRequest;

    UNSIGNED8    dataLength;
    union
    {
        UNSIGNED8    dataPayload08[8];
        UNSIGNED16    dataPayload16[4];
        UNSIGNED32    dataPayload32[2];
        UNSIGNED64    dataPayload64;
    };
} Frame;

 

nodeId при присвоении проверяется на граничные значения внутри соотв. метода соотв. класса, т.е. в одном месте, а не размазаны по всему коду ...

functionCode вообще может принимать лишь фиксированные значения:

 

// Peer-to-Peer objects of the CANopen Predefined Master/Slave Connection Set
const struct 
{
    UNSIGNED8 nodeControl;
    UNSIGNED8 emergencyAndSynchronize;
    UNSIGNED8 timeStamp;
    UNSIGNED8 TPDO1;
    UNSIGNED8 RPDO1;
    UNSIGNED8 TPDO2;
    UNSIGNED8 RPDO2;
    UNSIGNED8 TPDO3;
    UNSIGNED8 RPDO3;
    UNSIGNED8 TPDO4;
    UNSIGNED8 RPDO4;
    UNSIGNED8 TSDO;
    UNSIGNED8 RSDO;
    UNSIGNED8 errorControl;
} peerToPeerObject = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14};

 

вот так используется:

    
void CANopenSlave::operator << (Frame & rxFrame)
{
    // Broadcast Message
    if (rxFrame.cobId.nodeId == 0)
    {
        if (rxFrame.cobId.functionCode == peerToPeerObject.nodeControl)
        {
            processNodeControl(rxFrame);
            ......

 

 

 

зы. это коду выше более 5 лет (если не больше), но по-прежнему легко читается...

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


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

нет, ни разу. никогда к битам не обращяюсь напрямую типа a |= (1 << 24); Только через дефайны. a |= STATE_A;

 

Счастливчик.

Только увы, биты можно освоить и простым сложением величин... А потом долго не втыкать, почему же с = a+b не работает...Или с = a - b, если b > a...

А все было бы гораздо прозрачней, если usC = iA - iB

 

Еще интересней случаи, когда

Data = N;

вместо

*Data = N;

 

а с

*pData = N;

сделать ошибку куда сложней.

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


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

А все было бы гораздо прозрачней, если usC = iA - iB

© "Ежики кололись, но все равно ели кактус" :)

 

*pData = N;

сделать ошибку куда сложней.

 

Только что попробовал такую конструкцию:

 

int value = 10;
int * pointer;
....
pointer = value;

Тут же получил от компилятора (keil) по носу:

 

error: #513: a value of type "int" cannot be assigned to an entity of type "int *"

 

Но это проглатывает:

int * pointer;
pointer = 0;

Хотя я никогда так не пишу, а использую вместо нуля эту штуку (ее нет в С++):

#undef NULL
#define    NULL ((void*)0)
.....
pointer = NULL;

 

Тогда при попытке присвоить обычной переменной эту NULL:

int value;
....
value = NULL;

получим от компилятор опять щелчок по носу:

error: #513: a value of type "void *" cannot be assigned to an entity of type "int"

 

 

 

 

 

зы. Честно, прям дикости какие-то вы тут пишите :wacko:

 

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

Может, это связано с тем, что трачу уйму времени на предварительно проектирование кода ... не знаю, но факт в том,

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

 

Хотя раньше указатели я именовал, но не шифровками типа - "p" или "ptr", а с полностью - с припиской "Pointer" в конце названия.

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

Это несложно, т. к. пишу под плюсами, поэтому использую ссылки, а не указатели.

Так безопаснее да и код читается лучше, т.к. нет "->".

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


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

Еще интересней случаи, когда

Data = N;

вместо

*Data = N;

Ха..... Да и без ругони компилятра не допускаю такие ошибки.... Не знаю почему... Такое руки сами не напишут... Это даже детской ошибкой не назвать.... )))

ps а ещё есть ссылки. они более защищены, чем указатель.

 

Честно, прям дикости какие-то вы тут пишите
+100

Только увы, биты можно освоить и простым сложением величин...
какие биты у величин? Биты - это флаги. Вам нужно проверить 3, 6 и 18 флаг по "И", проверяйте if(a & ((1<<3) | (1<<6) | (1<<18)){}

по "ИЛИ" - проверяйте if(a | ((1<<3) | (1<<6) | (1<<18)){} Грамозко, непонятно, требует комента? сделайте дефайн

#define IS_PRESENT_ALL ((1<<3) | (1<<6) | (1<<18))

if(a | IS_PRESENT_ALL){}

а также

a |= (1<<7);//выставить 7-ой бит

a &= ~(1<<19);//сбросить 19-ый бит

Какое у битов сложение? Если нужно переменную в 2 и более бита - используйте битовые поля, обращайтесь к ним как к простым переменным.

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


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

(ее нет в С++):
Там "из коробки" специально для этого есть nullptr.

 

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


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

Forger, juvf, вы сильно зацикливаетесь на своем коде. Я рад за вас, что вы сразу пишете идеальный код.

Не у всех так получается. А люди еще бывает работают в команде. А еще бывает, люди пишут код, который потом будут массово пользовать другие (как те же библиотеки stm32).

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


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

Там "из коробки" специально для этого есть nullptr.

Это относится лишь к компиляторам, которые поддерживают C++11.

 

В ARM-компиляторе (Keil) есть частичная поддержка C++11, nullptr в его редакторе подкрашивается, это удобно ))

"Из коробки" не заработает, нужно обязательно включать опцию компилятора "--cpp11".

 

Но обязательно возьму на вооружение! Спасибо :biggrin:

 

 

Не у всех так получается.
Неправда - у всех это получается, ничего тут сложного нет.

А дело, возможно, в другом - не все хотят учится и переучиваться ;)

 

А люди еще бывает работают в команде.

Тем более!

Логичнее приучить всю команду сразу писать правильно, создав свод правил или использовать готовые, как тут уже писали,.

Ведь на то она и команда, чтобы следовать единым и удобным для всех правилам, а не писать каждый как хочет!

Придется все же выбрать: общие правила (законы) или "ежики кололись, но продолжали есть кактус" (повторяюсь) :smile3046:

 

А еще бывает, люди пишут код, который потом будут массово пользовать другие (как те же библиотеки stm32).

Какое странное оправдание ..

 

.

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


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

Какое странное оправдание ...

Ладно, последняя попытка B)

Не все пишут на С++ и С++11

Те же библиотеки stm32 написаны на С. А ему пофиг на

int value = 10;
int * pointer;
....
pointer = value;

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


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

Не все пишут на С++ и С++11

Это тут ни при чем.

Я использую C-библиотеки stm32 в C++. Неразрешимых проблем не было.

 

Те же библиотеки stm32 написаны на С. А ему пофиг на

int value = 10;
int * pointer;
....
pointer = value;

Так смените свой компилятор на нормальный, которому это не пофиг!

Или покопайтесь в настройках компилятора, чтобы он ругался на такие вещи хотя бы warning-ми.

Честно слово, как дети малые ...

 

зы. Скажите, при сборке всего проекта вы сразу добиваетесь, чтобы не было ни одного warning-а или откладываете это на потом? ;)

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


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

Forger, juvf, вы сильно зацикливаетесь на своем коде. Я рад за вас, что вы сразу пишете идеальный код.

Не у всех так получается. А люди еще бывает работают в команде. А еще бывает, люди пишут код, который потом будут массово пользовать другие (как те же библиотеки stm32).

Я не зациклен. Я предложил свой стаил. Он не единственно верный. Гугл стайл мне не понравился... тип переменной в имя сувать - тоже мне не по вкусу. раньше вроде так писали int *pName; Сечас..... посмотрите другие стайлы.... мой стаил гавно? посмотрите гугл, Qt,.... посмотрите исходники Linux - это пуре СИ.

Те же библиотеки stm32 написаны на С. А ему пофиг на
иаровски СИШНЫЙ компилятр не скомпилировал такое, ругнулся

int *i;
i = 200;

gcc тоже такое не проглотит. Не нужно нормальный компилятор. мне кажется не один компилятор такое не проглотит. Или я ошибаюсь? Какой компиллер такое проглитит?

 

Я не пишу идеальный код сразу и правильно.... но мне эти р не нужны. Более того, они мне мешают. Если вам с ними комфортно, с ними меньше ошибок и быстрее пишется - ни кто вам не запрещяет ставить р.

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


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

иаровски СИШНЫЙ компилятр не скомпилировал такое, ругнулся

int *i;
i = 200;

Отцы, вам самим не смешно такие примеры приводить?

 

Позвольте зацитировать первооснователей (K&R):

int х = 1, у = 2, z[10];

int *ip; /* ip - указатель на int */

ip = &x; /* теперь ip указывает на х */

y = *ip; /* у теперь равен 1 */

*ip =0; /* х теперь равен 0 */

 

выделено мной.

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


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

Отцы, вам самим не смешно такие примеры приводить?
не в тему сказал. войди в тему, начни читать с 109 поста. вместе посмеёмся.

 

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


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

Позвольте зацитировать первооснователей (K&R):

int х = 1, у = 2, z[10];

int *ip; /* ip - указатель на int */

ip = &x; /* теперь ip указывает на х */

y = *ip; /* у теперь равен 1 */

*ip =0; /* х теперь равен 0 */

 

выделено мной.

Такую "кашу" из букв даже при желании сочинить трудно, определенно нужен "талант"! :)

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


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

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

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

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

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

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

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

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

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

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