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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

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

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

По поводу более сложных нежели простой return функций - никто не запрещает передавать результаты работы функций через её параметры (по ссылке в C++ или по указателю в C/C++). По большому счёту, тот же return - это лишь особым образом записанный обычный параметр функции.

То есть, это:

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

int sum(int a, int b) {
  return a + b;
}
- фактически более понятная и наглядная для человека запись

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

void sum(int a, int b, int &s) {
  s = a + b;
}
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

WiseLord писал(а):Свои достоинства у глобальных переменных есть, но и недостатков хватает. Скажем, некое значение переменной можно передать в функцию и делать с ним что угодно, не боясь, что исходная переменная изменится. А вот с глобальной переменной надо быть более осторожным.

Да, чем меньше область видимости переменной - тем понятнее, предсказуемее и безопаснее её использование. Особенно если команда разработчиков на несколько десятков лбов, треть из которых свежеиспеченные/самоучки, развившиеся лишь до уровня "запинать компилер любой ценой, абы программа работала", четверть - ленивые толстые твари, вешающие сопли и ставящие подпорки вместо назревшего рефакторинга, пяток непризнанных "гениев", пишущих так что через месяц с воплями "да какой козёл это писал!?" не могут разобраться в собственном коде и т.д. А потом этот табор снимается к чертям в светлые дали и поделка ложится на плечи парня, назначенного сопровождать и поддерживать эту бочку с макаронами. И поди догадайся почему и откуда раз в две недели прилетает некий таинственный дятел, тюкающий эту глобальную переменную своим железным клювом. А так да, объявили её статической, выдали коллегам наружу модуля интерфейс для её использования/изменения и спим спокойно. ;-)
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

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

Сообщение DX168B »

kalobyte писал(а):написано непонятно для кого и слишком много матана и египетских закорючек

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

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


Где-то я находил цикл статей по шифрованию. Не помню точно, где. Там расписывались формулы и алгоритмы на самом понятном уровне. То есть, на пальцах. Объяснялось, для чего были применены те или иные приемы в шифровании. Все очень доходчиво.
Попробуйте поискать в Гугле по запросу "Шифрование на пальцах"
Там все просто. Для шифрования и дешифровки используется одна и та же функция. При шифровании сертификаты не обязательны.
Сертификаты используются в качестве удостоверения (подписи), что расшифровываемый блок данных не подделан и повышает криптостойкость.
Для пароля хватит и MD5. Но алгоритм MD5 не прост:
СпойлерMD5.h

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



#ifndef __MD5_H
#define __MD5_H

#ifdef __alpha
typedef unsigned int UINT4;
#else
typedef unsigned long int UINT4;
#endif

#define UCHAR unsigned char
#define BYTE UCHAR
#define ULONG unsigned long int
#define UINT unsigned int
#define DWORD ULONG

#define MD5_INIT_STATE_0 0x67452301
#define MD5_INIT_STATE_1 0xefcdab89
#define MD5_INIT_STATE_2 0x98badcfe
#define MD5_INIT_STATE_3 0x10325476


#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

#define FF(a, b, c, d, x, s, ac) \
{ \
    (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
    (a) = ROTATE_LEFT ((a), (s)); \
    (a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) \
{ \
    (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
    (a) = ROTATE_LEFT ((a), (s)); \
    (a) += (b); \
 }
#define HH(a, b, c, d, x, s, ac) \
{ \
    (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
    (a) = ROTATE_LEFT ((a), (s)); \
    (a) += (b); \
}

#define II(a, b, c, d, x, s, ac) \
{ \
    (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
    (a) = ROTATE_LEFT ((a), (s)); \
    (a) += (b); \
}

void MD5Update(unsigned char *bug, unsigned int len);
void MD5Init(void);
void MD5Final(char* cReturnStr);
void Transform(UINT4 *buf, UINT4 *in);
void GetMD5(char* pBuf, UINT nLength,char* cReturnStr);

#endif
 


MD5.c

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

/////////////////////////////////////////////////////////////
// MD5 hash calculate 

#include <stdio.h>
#include <string.h>

#include "md5.h"


////////////////////////////////////////////////////////////
//
BYTE  m_lpszBuffer[64];
ULONG m_nCount[2];
ULONG m_lMD5[4];

static unsigned char PADDING[64] =
{
    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

////////////////////////////////////////////////////////////
void ByteToDWord(DWORD* Output, ULONG* Input, UINT nLength)
{
    UINT i=0;
    UINT j=0;
    for (; j < nLength; i++, j += 4)
    {
        Output[i] = (ULONG)Input[j]   | 
                    
(ULONG)Input[j+1] << 8 | 
                    
(ULONG)Input[j+2] << 16 | 
                    
(ULONG)Input[j+3] << 24;
    }
}

////////////////////////////////////////////////////////////
void DWordToByte(unsigned char* Output, DWORD* Input, UINT nLength)
{
    UINT i = 0;
    UINT j = 0;
    for (; j < nLength; i++, j += 4) 
    
{
        Output[j] =   (UCHAR)(Input[i] & 0xff);
        Output[j+1] = (UCHAR)((Input[i] >> 8) & 0xff);
        Output[j+2] = (UCHAR)((Input[i] >> 16) & 0xff);
        Output[j+3] = (UCHAR)((Input[i] >> 24) & 0xff);
    }
}

////////////////////////////////////////////////////////////
void MD5Init (void)
{
    memset(m_lpszBuffer, 0, 64 );
    m_nCount[0] = m_nCount[1] = 0;

    m_lMD5[0] = MD5_INIT_STATE_0;
    m_lMD5[1] = MD5_INIT_STATE_1;
    m_lMD5[2] = MD5_INIT_STATE_2;
    m_lMD5[3] = MD5_INIT_STATE_3;
}

////////////////////////////////////////////////////////////
void MD5Update (unsigned char *inBuf, unsigned int inLen)
{
    register int i, ii;
    int mdi;
    UINT4 in[16];

    mdi = (int)((m_nCount[0] >> 3) & 0x3F);

    if ((m_nCount[0] + ((UINT4)inLen << 3)) < m_nCount[0])
    {
        m_nCount[1]++;
    }
    m_nCount[0] += ((UINT4)inLen << 3);
    m_nCount[1] += ((UINT4)inLen >> 29);

    while (inLen--)
    {
        m_lpszBuffer[mdi++] = *inBuf++;

        if (mdi == 0x40)
        {
            for (= 0, ii = 0; i < 16; i++, ii += 4)
            {
                in[i] = (((UINT4)m_lpszBuffer[ii+3]) << 24) |
               (((UINT4)m_lpszBuffer[ii+2]) << 16) |
               (((UINT4)m_lpszBuffer[ii+1]) << 8) |
               ((UINT4)m_lpszBuffer[ii]);
            }
            Transform (m_lMD5, in);
            mdi = 0;
        }
    }
}

////////////////////////////////////////////////////////////
void MD5Final (char* cReturnStr)
{
    unsigned char bits[8];
    int nIndex;
    unsigned int nPadLen;
    const int nMD5Size = 16;
    unsigned char lpszMD5[16];
    char temp[4];
    int i;

    cReturnStr[0]='\0';

    DWordToByte( bits, m_nCount, 8 );

    nIndex = (int)((m_nCount[0] >> 3) & 0x3f);
    nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex);
    MD5Update (PADDING, nPadLen);

    MD5Update (bits, 8);

    DWordToByte( lpszMD5, m_lMD5, nMD5Size );

    for (i=0; i < nMD5Size; i++) 
    
{
        if (lpszMD5[i] == 0)
        {
            temp[0] = '0';
            temp[1]='0';
        }
        else if (lpszMD5[i] <= 15)
        {
            sprintf(temp,"0%x",lpszMD5[i]);
        }
        else
        
{
            sprintf(temp,"%x",lpszMD5[i]);
        }
        strcat(cReturnStr,temp);
    }
    lpszMD5[0]='\0';
}

////////////////////////////////////////////////////////////
void Transform(register UINT4 *buf,register UINT4 *in)
{
    register UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];

#define S11 7
#define S12 12
#define S13 17
#define S14 22
    FF ( a, b, c, d, in[ 0], S11, 0xD76AA478L); 
    FF 
( d, a, b, c, in[ 1], S12, 0xE8C7B756L); 
    FF 
( c, d, a, b, in[ 2], S13, 0x242070DBL); 
    FF 
( b, c, d, a, in[ 3], S14, 0xC1BDCEEEL); 
    FF 
( a, b, c, d, in[ 4], S11, 0xF57C0FAFL); 
    FF 
( d, a, b, c, in[ 5], S12, 0x4787C62AL); 
    FF 
( c, d, a, b, in[ 6], S13, 0xA8304613L); 
    FF 
( b, c, d, a, in[ 7], S14, 0xFD469501L); 
    FF 
( a, b, c, d, in[ 8], S11, 0x698098D8L); 
    FF 
( d, a, b, c, in[ 9], S12, 0x8B44F7AFL); 
    FF 
( c, d, a, b, in[10], S13, 0xFFFF5BB1L); 
    FF 
( b, c, d, a, in[11], S14, 0x895CD7BEL); 
    FF 
( a, b, c, d, in[12], S11, 0x6B901122L); 
    FF 
( d, a, b, c, in[13], S12, 0xFD987193L); 
    FF 
( c, d, a, b, in[14], S13, 0xA679438EL); 
    FF 
( b, c, d, a, in[15], S14, 0x49B40821L); 

#define S21 5
#define S22 9
#define S23 14
#define S24 20
    GG ( a, b, c, d, in[ 1], S21, 0xF61E2562L); 
    GG 
( d, a, b, c, in[ 6], S22, 0xC040B340L); 
    GG 
( c, d, a, b, in[11], S23, 0x265E5A51L); 
    GG 
( b, c, d, a, in[ 0], S24, 0xE9B6C7AAL); 
    GG 
( a, b, c, d, in[ 5], S21, 0xD62F105DL); 
    GG 
( d, a, b, c, in[10], S22, 0x02441453L); 
    GG 
( c, d, a, b, in[15], S23, 0xD8A1E681L); 
    GG 
( b, c, d, a, in[ 4], S24, 0xE7D3FBC8L); 
    GG 
( a, b, c, d, in[ 9], S21, 0x21E1CDE6L); 
    GG 
( d, a, b, c, in[14], S22, 0xC33707D6L); 
    GG 
( c, d, a, b, in[ 3], S23, 0xF4D50D87L); 
    GG 
( b, c, d, a, in[ 8], S24, 0x455A14EDL); 
    GG 
( a, b, c, d, in[13], S21, 0xA9E3E905L); 
    GG 
( d, a, b, c, in[ 2], S22, 0xFCEFA3F8L); 
    GG 
( c, d, a, b, in[ 7], S23, 0x676F02D9L); 
    GG 
( b, c, d, a, in[12], S24, 0x8D2A4C8AL); 

#define S31 4
#define S32 11
#define S33 16
#define S34 23
    HH ( a, b, c, d, in[ 5], S31, 0xFFFA3942L); 
    HH 
( d, a, b, c, in[ 8], S32, 0x8771F681L); 
    HH 
( c, d, a, b, in[11], S33, 0x6D9D6122L); 
    HH 
( b, c, d, a, in[14], S34, 0xFDE5380CL); 
    HH 
( a, b, c, d, in[ 1], S31, 0xA4BEEA44L);
    HH ( d, a, b, c, in[ 4], S32, 0x4BDECFA9L); 
    HH 
( c, d, a, b, in[ 7], S33, 0xF6BB4B60L); 
    HH 
( b, c, d, a, in[10], S34, 0xBEBFBC70L); 
    HH 
( a, b, c, d, in[13], S31, 0x289B7EC6L); 
    HH 
( d, a, b, c, in[ 0], S32, 0xEAA127FAL); 
    HH 
( c, d, a, b, in[ 3], S33, 0xD4EF3085L); 
    HH 
( b, c, d, a, in[ 6], S34, 0x04881D05L);
    HH ( a, b, c, d, in[ 9], S31, 0xD9D4D039L); 
    HH 
( d, a, b, c, in[12], S32, 0xE6DB99E5L); 
    HH 
( c, d, a, b, in[15], S33, 0x1FA27CF8L); 
    HH 
( b, c, d, a, in[ 2], S34, 0xC4AC5665L); 

#define S41 6
#define S42 10
#define S43 15
#define S44 21
    II ( a, b, c, d, in[ 0], S41, 0xF4292244L); 
    II 
( d, a, b, c, in[ 7], S42, 0x432AFF97L); 
    II 
( c, d, a, b, in[14], S43, 0xAB9423A7L); 
    II 
( b, c, d, a, in[ 5], S44, 0xFC93A039L); 
    II 
( a, b, c, d, in[12], S41, 0x655B59C3L); 
    II 
( d, a, b, c, in[ 3], S42, 0x8F0CCC92L); 
    II 
( c, d, a, b, in[10], S43, 0xFFEFF47DL); 
    II 
( b, c, d, a, in[ 1], S44, 0x85845DD1L); 
    II 
( a, b, c, d, in[ 8], S41, 0x6FA87E4FL); 
    II 
( d, a, b, c, in[15], S42, 0xFE2CE6E0L); 
    II 
( c, d, a, b, in[ 6], S43, 0xA3014314L); 
    II 
( b, c, d, a, in[13], S44, 0x4E0811A1L); 
    II 
( a, b, c, d, in[ 4], S41, 0xF7537E82L); 
    II 
( d, a, b, c, in[11], S42, 0xBD3AF235L); 
    II 
( c, d, a, b, in[ 2], S43, 0x2AD7D2BBL); 
    II 
( b, c, d, a, in[ 9], S44, 0xEB86D391L); 

    buf
[0] += a;
    buf[1] += b;
    buf[2] += c;
    buf[3] += d;
}

////////////////////////////////////////////////////////////
void GetMD5(char* pBuf, UINT nLength,char* cReturnStr)
{
    MD5Init();
    MD5Update((unsigned char*)pBuf, nLength);
    MD5Final(cReturnStr);
}



Использование:

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



#include <stdio.h>
#include "md5.h"

const char in[]={"Hello RadioKot!"}; // строка, которую будем хешировать
char hash[34]; //Тут сохранится вычисленный хен

GetMD5((char*)in, strlen(in), hash); // вычисляем MD5 хеш
printf("string = %s\nhash = %s\n", in, hash); // Выводим результат



Результат:

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

string = Hello RadioKot!
hash = 37941d5ed59f94752b7cff0267a30f42


Но хеш - это полбеды. Злоумышленнику хватит и хеша для взлома. Потому, если это WEB приложение, то
надо задумываться о применении HTTPS. Для этого не требуется программировать шифрование.
Достаточно сервер сконфигурировать должным образом. WEB проектов и различных примеров в сети, как грязи.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

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

Сообщение Mishany »

Столкнулся с небольшим парадоксом, лыжи не едут....
обычная динамическая индикация на 3 разряда, но если передаем переменную равную нулю в функцию inki - в портС присваивается несуществующее значение из массива равное 0х0А, толи так оптимизация криво работает, толи мега8 глючит код в AVR Studio5 упрощенный вариант
Спойлер

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

#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
void inki(int t);
//.......................0.....1.....2.....3.....4.....5.....6.....7.....8.....9....
const char digit[10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}; // масив цифр для отправки на К561ИД1(CD4028BE)
uint8_t tscr[3];
uint8_t dig = 0;

void inki(int t)
{
        tscr[0] = t/100;// сотни
      tscr[1] = (t/10)%10;//десятки
      tscr[2] = t%10;//еденицы
}

ISR (TIMER2_COMP_vect)
{
   uint8_t digr; // выходы PB1,PB2,PB3
if(dig < 3)   // три разряда 0,1,2 digr3-еденицы
   {
   PORTC = digit[tscr[dig]]; // выводим цифру на дешифратор катоды т.е.0-9
   digr=dig+1;   
   PORTB|=(1<<digr);
   }
if (++dig > 3)
   {
   dig = 0;
   }
}

int main(void)
{
   /**********************************настройка портов******************************/
   DDRB|=(1<<1)|(1<<2)|(1<<3); //аноды(разряды)
   DDRC|=(1<<0)|(1<<1)|(1<<2)|(1<<3);//катоды идут на К561ИД1
/**********************************настройка таймера2 индикация цифр*****************************/
TCCR2 |= (1 << CS20) | (1 << CS21);   //предделитель на 32
TIMSK |= (1<<OCIE2) | (1<<TOIE2);
sei();
while(1)
   {
/////////////////////////////////////////////////////отображение режимов
inki(0); // на PORTC откуда то появляется 0x0A??????
// при любом переданным значением отличным от нуля все отлично...
   }   
   return 0;
}
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

1. все переменные, используемые в обработчиках прерывания и где-то еще, должны объявляться как volatile
2. ну кто вас учил задавать макрос F_CPU внутри исходника?! азы-то надо знать - этот макрос должен задаваться в параметрах проекта, как глобальный макрос
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Вы говорите про развёртку на три цифры, но по прерыванию получается четыре прохода:
1. dig = 0, выводим в порт C число digit[tscr[0]], дальше в конце dig = 1;
2. dig = 1, выводим в порт C число digit[tscr[1]], дальше в конце dig = 2;
3. dig = 2, выводим в порт C число digit[tscr[2]], дальше в конце dig = 3; (при dig = 2 условие if (++dig > 3) всё ещё не выполняется
4. dig = 3, выводим в порт C число digit[tscr[0]], дальше в конце dig = 0; (условие выполнилось).

Мелкие замечания:
- слово "единица" пишется через "и" (режет глаз)
- чисто по смыслу лучше 0 считать единицы, 1 десятки, 2 сотни и так далее. А у Вас шиворот-навыворот.
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

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

Сообщение Mishany »

нее, код рабочий, а я лошара, питание прое*** на к561ид1, пока были сигналы на ее входах она подпитывалась и работала, а када 0 микросхемка вырубалась, а то что я вчера намерял 0х0А похоже был просто глюк ид1, сейчас со светиком прошелся по нагам и запалил свой косяк)))
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 231
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

Mishany писал(а):

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

   PORTB|=(1<<digr);

Глюков еще не было?
Уровни в PORTB устанавливаются, но нигде не сбрасываются.
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

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

Сообщение Mishany »

сбрасываются, только в другом таймере, я его вырезал из примера вместе с сбросом (не доглядел при упрощении кода), проблема уже решена, проблема была в плате, не допаял..
Аватара пользователя
slavokhire5
Прорезались зубы
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

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

Сообщение slavokhire5 »

Здравствуйте, коты:)
пытаюсь освоить кейл и попутно блютуз микросхемку bluenrg.
компилирую пример от производителя - все ок.

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

typedef __packed struct _evt_le_meta_event{
uint8_t subevent;
uint8_t data[0]; // ругается сюда error: #94-D: the size of an array must be greater than zero
} PACKED evt_le_meta_event;

два вопроса к сообществу:
1. зачем вообще нужны нулевые массивы в структуре? как-то "застолбить" место?
2. как успокоить кейл и не поломать библиотечный код?
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

slavokhire5 писал(а):компилирую пример от производителя - все ок.

когда попытался это дело перетащить в свой проект, кейл начал ругаться на нулевые размеры некоторых массивов:
[...]
2. как успокоить кейл и не поломать библиотечный код?

Если один и тот же компилятор на идентичный код ругается в зависимости от проекта - то попробуйте сравнить настройки проектов из примера и вашего. Вероятно в части включения поддержки разных фич языка есть разница.

slavokhire5 писал(а):typedef __packed struct _evt_le_meta_event{
uint8_t subevent;
uint8_t data[0]; // ругается сюда error: #94-D: the size of an array must be greater than zero
} PACKED evt_le_meta_event;

два вопроса к сообществу:
1. зачем вообще нужны нулевые массивы в структуре? как-то "застолбить" место?

Возможно это структура есть заголовок данных нефиксированного (неизвестного) размера. Программа обращается к элементам массива data в зависимости от типа события subevent - зная что событие номер 1 тащит с собой десять байт - оперируем индексами 0-9, а событие номер 2 содержит сто байт - значит допустимо обращаться до 99-го индекса. Ну а sizeof такой структуры вернёт чистый размер заголовка - без данных.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
Аватара пользователя
slavokhire5
Прорезались зубы
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

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

Сообщение slavokhire5 »

Здравствуйте коты:)

у меня вопрос по указателям (см. коменты в коде)

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

....
typedef __packed struct _evt_cmd_complete{
  uint8_t  ncmd;
  uint16_t opcode;
} PACKED evt_cmd_complete;
.....

int hci_send_req(struct hci_request *r, BOOL async)
{
...
uint8_t *ptr;
evt_cmd_complete *cc;
......
ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE);   // HCI_EVENT_HDR_SIZE == 2
// dataBuff типа uint8_t. в нем лежат значения 0x04, 0x0e, 0x04, 0x01, 0x0c, 0xfc.....
// в результате *ptr = 0x01
......
 cc = (void *) ptr;     // сс->ncmd = 0x01, cc->opcode == 0x00FC, хотя по логике должен быть равен 0x0CFC. что неправильно?
....
}


UPD1:и после выполнения строчки if (cc->opcode != opcode) я падаю в hard fault. если ее закоментить, то все хорошо. я так понимаю, это что-то с адресацией не так?
UPD2:поэкспериментировал с данными в dataBuff. допустим, он содержит значения 0x04, 0x0e, 0x04, 0x01, 0x0c, 0xfc, 0xaa.....
тогда в сс->opcode будет лежать 0xaafc, а в сс->ncmd будет 0x01. если сс->ncmd сделать типа uint16_t, то в сс->ncmd будет 0x0c01. т.е. байты меняет местами и почему-то отбрасывается 0x0c.

вся проблема в том, что я ковыряю примеры bluetooth от stm. перетаскиваю их с stm32l053 на stm32f030. теоретически в библиотеке должно быть все правильно, значит где-то косячу я.
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
viiv
Грызет канифоль
Сообщения: 280
Зарегистрирован: Чт ноя 06, 2014 13:09:06

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

Сообщение viiv »

slavokhire5 писал(а):после выполнения строчки if (cc->opcode != opcode) я падаю в hard fault.


Твой целовой MCU умеет обращаться по невыровненным данным? Конкретно с твоим MCU не разбирался, но не все "умеют" обращаться к невыровненным данным. С этим связаны и другие, описываемые проблемы.
Например, посмотри sizeof () твоей структуры, думаю, будешь удивлен.
Аватара пользователя
Siarzhuk
Потрогал лапой паяльник
Сообщения: 353
Зарегистрирован: Вс янв 19, 2014 22:41:55

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

Сообщение Siarzhuk »

slavokhire5 писал(а):у меня вопрос по указателям (см. коменты в коде)

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

....
typedef __packed struct _evt_cmd_complete{
  uint8_t  ncmd;
  uint16_t opcode;
} PACKED evt_cmd_complete;
.....


поэкспериментировал с данными в dataBuff. допустим, он содержит значения 0x04, 0x0e, 0x04, 0x01, 0x0c, 0xfc, 0xaa.....
тогда в сс->opcode будет лежать 0xaafc, а в сс->ncmd будет 0x01. если сс->ncmd сделать типа uint16_t, то в сс->ncmd будет 0x0c01. т.е. байты меняет местами и почему-то отбрасывается 0x0c.

Похоже компилятор проигнорировал просьбу упаковать структуру. Байты меняются местами потому что платформа Little Endian.
Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR! ;-)
yuriy m
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пт окт 17, 2014 12:42:38

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

Сообщение yuriy m »

Доброго времени суток. Есть маленькая задачка,только или я дурак или лыжи не едут. Выход -это обычный быстрый шим. На входе есть переменный резистор,установлен в среднее положение на входе шима нет. При вращении резистора от среднего положения вправо или влево у нас должен увеличиваться шим до максимально значения. Считываем 8 бит ацп и загоняем в OCR предварительно отняв 125 едениц ,то мы получаем в каждую сторону 125 шагов,что будет вялятся примерно половина заполнения шим,потом умножаем на 2. Ну и принципе на выходе мы имеем ,если резистор крутить от среднего положения в право ,на выходе будет менятся шим от 0-255. А теперь вопрос ,как сделать чтобы от середины резистора при вращении влево тоже менялся шим от 0 до 255 ? Ну принципе из куска понятно ,что это управление реверсом моторчика одним резистором со средним положением.

Спасибо

if (ReadADC(3)>130) // ход в перед
{
PORTD &=~(1<<1); // выключить одну диагональ моста
_delay_ms(1); // пауза
PORTD|=(1<<2); // включить другую диагональ моста
speed = (ReadADC(3)-125)*2;
OCR2B=speed;
}
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

я так понимаю, просто надо так: speed = abs(ReadADC(3)-125)*2;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
yuriy m
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пт окт 17, 2014 12:42:38

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

Сообщение yuriy m »

ARV писал(а):я так понимаю, просто надо так: speed = abs(ReadADC(3)-125)*2;

Судя по всему нет,это не то. Выше я код написал ,для случая если резистор крутить от середины в право , а как сделать когда крутишь от середины влево ? Я понимаю что надо что то про инвертировать ,
но что-то не догоняю как...
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

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

насколько я понял, сам реверс вы делаете переключением плеч полумоста, а ШИМ просто задает "амплитуду". так вот, в вашем коде добавка функции abs даст ситуацию, когда в среднем положении резистора будет выдаваться 0, а по мере сдвига к краям - положительные значения в пределах примерно от 0 до 250, т.е. амплитуда будет плавно нарастать.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20091
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Сообщение Gudd-Head »

ARV писал(а):в среднем положении резистора будет выдаваться 0
Причём этот ноль надо будет ловить с точностью в 1/256 :)))
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
yuriy m
Первый раз сказал Мяу!
Сообщения: 23
Зарегистрирован: Пт окт 17, 2014 12:42:38

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

Сообщение yuriy m »

Я правильно понял ,что это как то так ?

if (ReadADC(3)>133) // ход в перед
{
PORTD &=~(1<<1); // выключить одну диагональ моста
_delay_ms(1); // пауза
PORTD|=(1<<2); // включить другую диагональ моста
speed = ((ReadADC(3)-122)*2)+11;
OCR2B=speed;
}
if ((ReadADC(3)>120)&&(ReadADC(3)<133))
{
OCR2B=0;
}
if (ReadADC(3)<120) // ход назад
{
PORTD &=~(1<<2); // выключить одну диагональ моста
_delay_ms(1); // пауза
PORTD|=(1<<1); // включить другую диагональ моста
speed = abs((ReadADC(3)-122)*2)+11;
OCR2B=speed;
}
То что шим будет не с нуля ,принципе не имеет значения...
Или есть более красивое решение ? ПС Сильно не пинайте ,только учу СИ.
Ответить

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