1 Востаннє редагувалося taburyak (16.01.2018 12:41:37)

Тема: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Є дві функції (ось прототипи):

bool getData(unsigned int *data0, unsigned int *data1);
bool readUInt(uint8_t address, unsigned int *value);

А ось сама функція getData:

bool getData(unsigned int *data0, unsigned int *data1)
{
    if (readUInt(TSL2561_REG_DATA_0, data0) && readUInt(TSL2561_REG_DATA_1, data1))
    {
        return(true);
    }
    return(false);
}

Функція getData отримує вказівники на змінні шляхом взяття адресної змінної (наприклад getData(&data0, &data1) і далі ці вказівники має передати ще в одну функцію яка приймає вказівники. І я вже ті data0 i data1 вже напряму кидаю до readUInt? Так правильно? Бо я ще плутаюсь в цих вказівниках.

Ось для мене зрозуміла конструкція:

bool getData(unsigned int *data0, unsigned int *data1)
{
    unsigned int tmpdata0 = *data0;
    unsigned int tmpdata1 = *data1;

    if (readUInt(TSL2561_REG_DATA_0, &tmpdata0) && readUInt(TSL2561_REG_DATA_1, &tmpdata1))
    {
        *data0 = tmpdata0;
        *data1 = tmpdata1;
        return(true);
    }
    return(false);
}

Це еквівалентно?

2 Востаннє редагувалося koala (16.01.2018 14:23:01)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Другий варіант трохи повільніший. Якщо мова йде не про багатопотокове програмування, то ці коди дійсно функціонально еквівалентні.
А ще раджу без потреби не брати те, що ви повертаєте, в дужки, а якщо повертаєте булеве значення - то не робити return true/return false:

    bool getData(unsigned int *data0, unsigned int *data1)
    {
        return readUInt(TSL2561_REG_DATA_0, data0) && readUInt(TSL2561_REG_DATA_1, data1);
    }
Подякували: sensei, taburyak, leofun013

3

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

По великому рахунку в кінцевому результаті різниці для користувача не буде, але насправді ж ви виконуєте лишнє копіювання об'єктів на які вказують вказівники data0 та data1.

В даному випадку це ускладнює тільки розуміння коду, але уявіть якби ці об'єкти були тяжкими, або їх було багато, тоді б це копіювання зайняло б чимало часу.

bool getData(int *data0, int *data1)
{
    int tmpdata0 = *data0;
    //*data0 - розіменовуєте вказівник, тобто ця операція поверне значення на яке він вказує
    // і воно скопіюється у змінну int tmpdata0

    readUInt(TSL2561_REG_DATA_0, &tmpdata0);
    //передаєте адресу копії у функцію readUInt, де вона присвоїться іншому вказівнику
    
   *data0 = tmpdata0;
   //повертаєтесь до початкового вказівника та замінюєте його попереднє значення
   //на значення цієї копії яка якось опрацювалась у функції readUInt

    return true;
}

Весь цей код скорочується до варіанту описаного у вашій першій функції: коли ви в readUInt передаєте безпосередньо вказівник, і тоді скопіюється лише вказівник, а не сам об'єкт.

bool getData(int *data0, int *data1)
{
    readUInt(TSL2561_REG_DATA_0, data0)
}
Подякували: taburyak1

4

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Я сподіваюся у вас там насправді за вказівником не один єдиний int? Бо інакше навіщо морочити собі цими вказівниками голову, якщо вказівник як мінімум не менший за int?
Також про всяк випадок нагадаю, що цей вказівник не можна ніде зберігати, бо він може вказувати на змінну десь всередині стеку.

Подякували: sensei, leofun012

5

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Дякую хлопці. Зрозумів. А то я засумнівався ;)

6

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Torbins, там це вихідне значення. Функція повертає статус (прочитано-не прочитано).
taburyak, ваша функція є фактично обгорткою для двох викликів readUInt. Так це і уявляйте:

bool getData(дані_для_першої_readUInt, дані_для_другої_readUInt)
{
    return    readUInt(TSL2561_REG_DATA_0, дані_для_першої_readUInt) 
           && readUInt(TSL2561_REG_DATA_1, дані_для_другої_readUInt);
}

І все, вас не обходить, якого типу ці дані.

Подякували: sensei, taburyak, leofun013

7 Востаннє редагувалося taburyak (09.02.2018 10:11:54)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Деякі речі в C/C++, в силу недостатнього досвіду, ламають мені мозок. Допоможіть розібратись як це і для чого.
Сподобалась ідея цього міжMCUушного протоколу.
Залізна частина мене не цікавила, а саме формування пакету для відправки, та розбирання пакету після прийому мене цікавить. Ну то лірика, все одно ніхто не буде заглиблюватись. По суті. Я не розумію ось оце:

В "h" файлі оголошені прототипи таким чином:

// Установка функций, которые вызываются при получении пакетов
// Эта - получает пакеты, которые адресованы нам
void clunet_set_on_data_received(void (*f)(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size));

// А эта - абсолютно все, которые ходят по сети, включая наши
void clunet_set_on_data_received_sniff(void (*f)(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size));

Наскільки я зрозумів, то це оголошена функція яка викликає ще одну функцію за вказівником з перерахованими параметрами.

Далі в "c" файлі на початку оголошені??? такі прототипи??? функцій чи це вже виклик функцій??? Я тут вже заплутався:

void (*on_data_received)(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size) = 0;
void (*on_data_received_sniff)(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size) = 0;

В моєму розумінні тут вже вказані вказівники конкретних функцій, але функція не викликається бо вказані не конкретні параметри, а так як в прототипах функцій. І чому їм присвоюється нуль??? Що це за така конструкція?

Далі в програмі зустрічається вже виклик таких функцій таким чином:

if (on_data_received_sniff)
        (*on_data_received_sniff)(src_address, dst_address, command, data, size);

Або:

if (on_data_received)
        (*on_data_received)(src_address, dst_address, command, data, size);

Що в умові перевіряється? Як це працює? Для чого такі навороти?

Ну і в кінці "с" файлу самі функції, які були оголошені на початку???

void
clunet_set_on_data_received(void (*f)(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size))
{
    on_data_received = f;
}

void
clunet_set_on_data_received_sniff(void (*f)(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size))
{
    on_data_received_sniff = f;
}

Ця конструкція взагалі по за межами мого розуміння. І між цими двома функціями я взагалі не бачу різниці. Нащо робити окремі назви однаковісіньким функціям???

Допоможіть зрозуміти. Будь ласочка.

8 Востаннє редагувалося ReAl (09.02.2018 11:51:45)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Це асинхронна функція зворотного виклику, її встановлення і використання.

taburyak написав:
void clunet_set_on_data_received_sniff(void (*f)(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size));

Наскільки я зрозумів, то це оголошена функція яка викликає ще одну функцію за вказівником з перерахованими параметрами.

Вона не викликає цю функцію, а лише приймає вказівник на неї як параметр і заносить його у змінну.

taburyak написав:

Далі в "c" файлі на початку оголошені??? такі прототипи??? функцій чи це вже виклик функцій??? Я тут вже заплутався:

void (*on_data_received)(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size) = 0;
void (*on_data_received_sniff)(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size) = 0;

В моєму розумінні тут вже вказані вказівники конкретних функцій, але функція не викликається бо вказані не конкретні параметри, а так як в прототипах функцій. І чому їм присвоюється нуль??? Що це за така конструкція?

Це визначення змінних — вказівників на функції із заданим прототипом

taburyak написав:

Далі в програмі зустрічається вже виклик таких функцій таким чином:

if (on_data_received_sniff)
        (*on_data_received_sniff)(src_address, dst_address, command, data, size);

Або:

if (on_data_received)
        (*on_data_received)(src_address, dst_address, command, data, size);

Що в умові перевіряється? Як це працює? Для чого такі навороти?

Перевіряється, чи вказівник не нульовий (тобто чи користувач встановив власний обробник). Якщо не нульовий, то викликається його функція. По стандарту достатньо було написати

if (on_data_received)
        on_data_received(src_address, dst_address, command, data, size);

як на мене, зайві зірочки-дужки тут знижують ясність тексту.

Далі у себе пишете функцію з таким прототипом:

void my_on_data_received(uint8_t src_address, uint8_t dst_address, uint8_t command, char* data, uint8_t size)
{
    // робите що треба з даними, при потребі встановлюєте свої прапорці
}

// десь в коді
    // ...
    // Встановити свій обробник прийнятих даних
    clunet_set_on_data_received(my_on_data_received);
    // ...

Тепер коли буде отримано пакет, clunet сам викличе цю Вашу my_on_data_received(), до того не чіпатиме.
Тільки викликатиметься my_on_data_received() швидше за все з переривання, коли по черговому байту буде з'ясовано, що пакет закінчився. Відповідно, ця функція не повинна надто довго працювати (у крайньому разі — дозволити переривання після своєї критичної частини) і з головною програмою при потребі спілкуватися через volatile-змінні.

Подякували: taburyak, leofun01, sensei3

9

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

ReAl написав:

Це асинхронна функція зворотного виклику

Ого! Крутяк! Може ж навчусь цьому нарешті. Величезне дякую за пояснення. Деякі речі зрозумів, все інше треба переварити і почитати.

10 Востаннє редагувалося ReAl (09.02.2018 13:37:35)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Доповнення (про це є у вікі-статті, тільки там приклад синхронного варіанту)
Можна було б спочатку визначити typedef для цих callback-функцій, тоді запис виглядав би так:

typedef void (*clunet_callback_t)(uint8_t src_address, uint8_t dst_address,
                                  uint8_t command, char* data, uint8_t size);

void clunet_set_on_data_received(clunet_callback_t f);
void clunet_set_on_data_received_sniff(clunet_callback_t f);

clunet_callback_t on_data_received = 0;
clunet_callback_t on_data_received_sniff = 0;

// ...

void
clunet_set_on_data_received(clunet_callback_t f)
{
    on_data_received = f;
}

// ...

Але свою функцію однак треба було б описувати із повним прототипом.
Хтось любить заводити typedef-и, хтось вважає, що краще робити повний опис — скрізь однаковий.

Подякували: taburyak, sensei2

11

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

taburyak написав:

Це еквівалентно?

Ні.

// Не знаю, що це за сталі
const int TSL2561_REG_DATA_0 = 0;
const int TSL2561_REG_DATA_1 = 1;

bool readUInt(int, unsigned int *data) {
    *data = 0;
    return false;
}

bool getData1(unsigned int *data0, unsigned int *data1)
{
    unsigned int tmpdata0 = *data0;
    unsigned int tmpdata1 = *data1;

    if (readUInt(TSL2561_REG_DATA_0, &tmpdata0) && readUInt(TSL2561_REG_DATA_1, &tmpdata1))
    {
        *data0 = tmpdata0;
        *data1 = tmpdata1;
        return(true);
    }
    return(false);
}

bool getData2(unsigned int *data0, unsigned int *data1)
{
    if (readUInt(TSL2561_REG_DATA_0, data0) && readUInt(TSL2561_REG_DATA_1, data1))
    {
        return(true);
    }
    return(false);
}

int main() {
    unsigned int i = 1;
    getData1(&i, &i);
    cout << i << endl;
    getData2(&i, &i);
    cout << i << endl;
}

Видає:

Console написав:

0
1

getData1 гарантує, що у випадку невдачі читання, оригінальні дані залишаться незміненими.

12

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

ReAl написав:

Це асинхронна функція зворотного виклику, її встановлення і використання.

Хочу ще раз подякувати за зрозумілі пояснення. В мене наче виходить так як задумав. Створити бібліотеку протоколу взаємодії між MCU без прив'язки до конкретного заліза. Те що стосується заліза: ініціалізація, та транспорт прийому доставки пакетів, то буде вже в зворотніх викликах. Тепер треба створити бібліотеку яка буде формувати запити, та реагувати на запити. Той ще клопіт  *SCRATCH*

Подякували: NaharD, 0xDADA11C7, ReAl4

13

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

taburyak написав:

Створити бібліотеку протоколу взаємодії між MCU без прив'язки до конкретного заліза.

Що в таких бібліотеках добре, то якщо все уважно зробити, так воно потім не лише на мікроконтролерах різних, а й у лінуксі з віндовсом бігатиме.

Подякували: 0xDADA11C7, taburyak, leofun013

14

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

ReAl написав:

Що в таких бібліотеках добре, то якщо все уважно зробити, так воно потім не лише на мікроконтролерах різних, а й у лінуксі з віндовсом бігатиме.

Бляхамухацекапєць!!! Дякую за ідею!!! Я в цьому напряму й не думав навіть. А це ж тепер, як все продумати і довести до кінця, можна десктопну версію клієнта blynk забабахати  :o

15 Востаннє редагувалося taburyak (14.02.2018 13:38:05)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Продовжуємо день "кохання", та кохатись з кодом Сі, Сі++, вказівниками і з blynk'ом. Гуртовуха ще та.

В бібліотеці blynk є функція яка приймає номер піна і, вважай, будь яку інформацію, чи то ціле число, чи то з комою, чи то текстовий рядок. Ось воно:

/**
     * Sends value to a Virtual Pin
     *
     * @param pin  Virtual Pin number
     * @param data Value to be sent
     */
    template <typename... Args>
    void virtualWrite(int pin, Args... values) {
        char mem[BLYNK_MAX_SENDBYTES];
        BlynkParam cmd(mem, 0, sizeof(mem));
        cmd.add("vw");
        cmd.add(pin);
        cmd.add_multi(values...);
        static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, cmd.getBuffer(), cmd.getLength()-1);
    }

    /**
     * Sends buffer to a Virtual Pin
     *
     * @param pin  Virtual Pin number
     * @param buff Data buffer
     * @param len  Length of data
     */
    void virtualWriteBinary(int pin, const void* buff, size_t len) {
        char mem[8];
        BlynkParam cmd(mem, 0, sizeof(mem));
        cmd.add("vw");
        cmd.add(pin);
        static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, cmd.getBuffer(), cmd.getLength(), buff, len);
    }

    /**
     * Sends BlynkParam to a Virtual Pin
     *
     * @param pin  Virtual Pin number
     * @param param
     */
    void virtualWrite(int pin, const BlynkParam& param) {
        virtualWriteBinary(pin, param.getBuffer(), param.getLength());
    }

    void virtualWrite(int pin, const BlynkParamAllocated& param) {
        virtualWriteBinary(pin, param.getBuffer(), param.getLength());
    }

Приклади застосування:

// Send string
Blynk.virtualWrite(pin, "abc");

// Send integer
Blynk.virtualWrite(pin, 123);

// Send float
Blynk.virtualWrite(pin, 12.34);

// Send multiple values as an array
Blynk.virtualWrite(pin, "hello", 123, 12.34);

// Send RAW data
Blynk.virtualWriteBinary(pin, buffer, length);

Так от коли я з STM32 кидаю ціле число і на ESP8266 очікую отримати ціле число і його передаю далі на блінк - все чудово працює ось таким чином:

//STM32 відправка стану кнопки
uint8_t state = 0;
Blynk_virtualWrite(V20, &state, sizeof(state));

Сама функція Blynk_virtualWrite:

void Blynk_virtualWrite(int pin, uint8_t *pData, uint8_t size)
{
    char dataToBlynk[MYHIOT_SEND_BUFFER_SIZE - MYHIOT_OFFSET_DATA];

    dataToBlynk[BLYNK_OFFSET_PIN] = pin;

    uint8_t i;
    for (i = 0; i < size; i++)
    {
        dataToBlynk[BLYNK_OFFSET_DATA_PIN + i] = pData[i];
    }

    myhiot_send(BLYNK_DEVICE_ID, 1, MYHIOT_COMMAND_BLYNK, dataToBlynk, size + BLYNK_OFFSET_DATA_PIN);

//    uint8_t *mem;
//    mem = (uint8_t *) malloc((size + BLYNK_OFFSET_DATA_PIN) * sizeof(uint8_t));
//    *(mem + BLYNK_OFFSET_PIN) = (uint8_t) pin;
//    memcpy(mem + BLYNK_OFFSET_DATA_PIN, pData, size);
//    myhiot_send(BLYNK_DEVICE_ID, 1, MYHIOT_COMMAND_BLYNK, (char *) mem, sizeof(mem));
//    free(mem);
}

Працює і розкоментована частина і закоментована.

Функцію myhiot_send не приводжу, там до пакету додаються адреси, пріоритети, контрольні суми, то не важливо.

На прийомній стороні (ESP8266) той пакет розбирається на складові і якщо я очікую конкретний тип даних char:

void data_received(unsigned char src_address, unsigned char dst_address, unsigned char command, char* data, unsigned char size)
{    
if (command == MYHIOT_COMMAND_BLYNK)
    {
        Blynk.virtualWrite(data[0], data[1]);        
    }
}

То працює належним чином.

Якщо я пуляю з STM32, наприклад float:

float value = 12.987456;
Blynk_virtualWrite(V0, (uint8_t *) value, sizeof(value));

І приймаю на ESP8266, та передаю до Blynk ось так:

void data_received(unsigned char src_address, unsigned char dst_address, unsigned char command, char* data, unsigned char size)
{    
    if (command == MYHIOT_COMMAND_BLYNK)
    {                
        Blynk.virtualWriteBinary(data[0], &data[1], sizeof(data) - 1);        
    }
}

То в додатку просто бачу послідовність кодів CHAR.

В мене не вистачає досвіду зрозуміти, як зробити так, щоб я не морочився з типами даних, які відправляю, зі сторони STM32 і на прийомній стороні це коректно сприймалось і передавало на blynk сервер, теж коректні дані.
Ну щоб було прозоро, що я відправляю дані з ESP8266 на блінк сервер, так само міг відправляти і з STM32.

Подякували: 0xDADA11C71

16

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Тааак, трішки розібрався. Поки зробив під кожен тип змінних окрему функцію. Не знаю як це втілити в одну.

Зі сторони STM32:

void Blynk_virtualWriteInt(int pin, int value)
{
    char dataToBlynk[MYHIOT_SEND_BUFFER_SIZE - MYHIOT_OFFSET_DATA];

    dataToBlynk[BLYNK_OFFSET_PIN] = pin;
    dataToBlynk[BLYNK_OFFSET_TYPE_DATA] = BLYNK_TYPE_INT;

    char *pValue;
    pValue = (char *) &value;

    uint8_t i;
    for (i = 0; i < sizeof(int); i++)
    {
        dataToBlynk[BLYNK_OFFSET_DATA_PIN + i] = *(pValue++);
    }

    myhiot_send(BLYNK_DEVICE_ID, 1, MYHIOT_COMMAND_BLYNK, dataToBlynk, sizeof(int) + BLYNK_OFFSET_DATA_PIN);
}

void Blynk_virtualWriteFloat(int pin, float value)
{
    char dataToBlynk[MYHIOT_SEND_BUFFER_SIZE - MYHIOT_OFFSET_DATA];

    dataToBlynk[BLYNK_OFFSET_PIN] = pin;
    dataToBlynk[BLYNK_OFFSET_TYPE_DATA] = BLYNK_TYPE_FLOAT;

    char *pValue;
    pValue = (char *) &value;

    uint8_t i;
    for (i = 0; i < sizeof(float); i++)
    {
        dataToBlynk[BLYNK_OFFSET_DATA_PIN + i] = *(pValue++);
    }

    myhiot_send(BLYNK_DEVICE_ID, 1, MYHIOT_COMMAND_BLYNK, dataToBlynk, sizeof(float) + BLYNK_OFFSET_DATA_PIN);
}

void Blynk_virtualWriteString(int pin, char* value, uint8_t size)
{
    char dataToBlynk[MYHIOT_SEND_BUFFER_SIZE - MYHIOT_OFFSET_DATA];

    dataToBlynk[BLYNK_OFFSET_PIN] = pin;
    dataToBlynk[BLYNK_OFFSET_TYPE_DATA] = BLYNK_TYPE_CHAR;

    uint8_t i;
    for (i = 0; i < size; i++)
    {
        dataToBlynk[BLYNK_OFFSET_DATA_PIN + i] = *(value++);
    }

    myhiot_send(BLYNK_DEVICE_ID, 1, MYHIOT_COMMAND_BLYNK, dataToBlynk, size + BLYNK_OFFSET_DATA_PIN);
}

Зі сторони ESP8266:

if (command == MYHIOT_COMMAND_BLYNK)
{        
    if (data[BLYNK_OFFSET_TYPE_DATA] == BLYNK_TYPE_INT)
    {                        
        int myInt;
        memcpy(&myInt, data + BLYNK_OFFSET_DATA_PIN, sizeof(myInt));
        Blynk.virtualWrite(data[BLYNK_OFFSET_PIN], myInt);
    }
    else if (data[BLYNK_OFFSET_TYPE_DATA] == BLYNK_TYPE_FLOAT)
    {
        float myFloat;        
        memcpy(&myFloat, data + BLYNK_OFFSET_DATA_PIN, sizeof(myFloat));                        
        Blynk.virtualWrite(data[BLYNK_OFFSET_PIN], myFloat);
    }
    else if (data[BLYNK_OFFSET_TYPE_DATA] == BLYNK_TYPE_CHAR)
    {
        Blynk.virtualWriteBinary(data[BLYNK_OFFSET_PIN], data + BLYNK_OFFSET_DATA_PIN, size -BLYNK_OFFSET_DATA_PIN);
    }

Ну і на STM32 роблю відправку так:

if(!HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) && !triggerPressedButton)
      {
          triggerPressedButton = true;
          HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);

          if(HAL_GPIO_ReadPin(LD3_GPIO_Port, LD3_Pin))
          {
              //TODO: відправка команди увімкнути щось
              Blynk_virtualWriteInt(V20, 1);
              Blynk_virtualWriteInt(V0, -754);
              Blynk_virtualWriteFloat(V1, -75.45689);
              char* value = "LED is ON\n";
              Blynk_virtualWriteString(V40, value, strlen(value));
          }
          else
          {
              //TODO: відправка команди вимкнути щось
              Blynk_virtualWriteInt(V20, 0);
              Blynk_virtualWriteInt(V0, 40569);
              Blynk_virtualWriteFloat(V1, 40.23);
              char* value = "LED is OFF\n";
              Blynk_virtualWriteString(V40, value, strlen(value));
          }
      }
      else if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) && triggerPressedButton)
      {
          triggerPressedButton = false;
      }

Все коректно відтворюється.

Прихований текст

https://lh3.googleusercontent.com/HHfNsMfQcvnuxV3q1mtcB1RDPymxY9Kgw1zJyY95Iraf4Y8MPKxWg_AuC_stIbvsH-DN7Kcl8G_Y3bi45EtQ34DnG5vD8rIMPEiexmRhgnlC7FdkT1_3AVrkQcemNBTo1yy4IAhxo7V144dt1tpqK_xlK9maKkGD1z9AYC8RFl6SgmT3RS--otnc0AJDsDPrLaFh0pC47uir7xK5y7eXIZkM4X-K95_SxHfu_l9Rwxt-ZWeAyyBb-L3HRW2G_mP7mevwshjRbpUvKKV23hkjUKpNDrwloZtMnQx8w_U31cPZ5OcyQ7q0q17XI6IZCO8yAlNT539Mjd3pBGKc-xXbvmWD2yp_Yk-BsIIpPYLK66AiRZRUZbGOu-fhgdLnVFwRxLcUzXyy34l2XG9M2wTEY8CQ4S8u8Z-T1epoaHndBhmA0AiepMwOSFDJVQtiV9ChSkDnJVHnfQ-WYoN15uofAxq60kXHUm3-wJq-kNqZv3oUHVbCybSP4JSMbe8f91yxHa9RKBMqmiLzRsx6JKY2sJLo06EEHz1bCwErpKnw9BRGDiGBo2sfpAXmM4N3c9T64heIAsEPEEVJVbIbb1EP2ncX2x1675ABLF9VMf4H=w202-h359-no

https://lh3.googleusercontent.com/rQk0ljourknGx_U4fI_0t8Luq2-BOUcTsHxrvWLqd_vGut_2RTbAxY2P2GtvA4bwQiCIxWkALtOaXtEtM9MHQnC56VHBHI4lI-GZaPbXSB1EZDDGmUL31_37qRVL9eZGVN3CyvhrDMbWXgIhgDy6dhylwRza7ZtLNn66oDieU3WwjUGn_k5IswuKuDXxZOEfzAzEk80BmAk-4bX0HjnzbXN2ntMM727X6w8zvDwkGgZNx8qeGpykO8Q6TDvrDBaC7F-YdWbfpN38n5pwQsWrFYig9l2B3gNQglb7-vxW9x60i-sp5zKLdPCTi0955tGfTeW2KUiOPbcHDl6jHTwJ4ceL95FdHT9pkmYxwTufI-wCdKHCzrIaEF2m3OpGaDq5jXvQ-fv4liaPd2DK68Iy2ZUjuknxtPLaZvWe-4AwCDfEd7zuRcZ_0J8ikugmBjB1Urx_2sWjvKBwZ4pu5joAq1E5_Tfw8ICWvazZ0ZDoQNBHx7W6IqfARP3G68szTKXvXDuPH9h7qVI0JBe2P8W_0QCKbCtJATnl1wnOIXMyRiLq9F76AjRzDuG9xsm1QkgCWFM34Xq-5OuIG33p0_Kmzi796tIdTC2pn9t7JWPI=w602-h1069-no

Питання 1: якось можна викрутитись однією функцією замість трьох окремих? Там майже все повторюється.
Питання 2: у функції Blynk_virtualWriteString треба ще вказувати розмір масиву char. А можна якось цей розмір вже всередені функції визначити, щоб розмір на вхід не вказувати?

17

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

В плюсах для цього є template. В PureC - макроси, але не факт, що з ними буде зручніше, ніж із трьома функціями.

Подякували: taburyak1

18 Востаннє редагувалося Yola (16.02.2018 06:00:02)

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

тут треба перевіряти чи size не більше ніж достиме значення. Також не треба виности i за межі циклу, навіщо засмічувати зовнішню область видності ще однією змінною.

    uint8_t i;
    for (i = 0; i < size; i++)
    {
        dataToBlynk[BLYNK_OFFSET_DATA_PIN + i] = *(value++);
    }

зрештою ви всі типи можете трактувати як масиви символів, наприклад:

    float value = 1.f;
    char *chvalue = (char*)(&value);
    Blynk_virtualWrite(pin, chvalue, sizeof(float));

тоді буде потрібен лише третій варіант функції.

Якщо після вище сказаного питання #2 ще стоїть, то якщо ваш рядок може містити усі символи, то ніяк! Якщо у вас є заборонені символи, то можете вставляти в кінець такий символ і перевіряти на нього.

Подякували: taburyak1

19

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

koala написав:

В плюсах для цього є template

Так отож. А маємо поки Cі.

Yola написав:

тут треба перевіряти чи size не більше ніж достиме значення

Точно, я й забув про це.

Yola написав:

ваш рядок може містити усі символи, то ніяк

Зрозумів. Тоді ніяк, а точніше хай буде як є.

20

Re: У функцію вказівник на змінну, а далі той вказівник в ще одну функцію

Зведіть три функції в одну, яка отримує вказівник і розмір. Мати три функції з майже ідентичним кодом - небезпечно.

Якщо хочете, то можете залишити обгортки, як-от:

void Blynk_virtualWriteFloat(int pin, float value) {
    char *chvalue = (char*)(&value);
    Blynk_virtualWriteString(pin, chvalue, sizeof(float));
}
Подякували: taburyak, ReAl2