Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как я получил Адъ
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
ViKo
Создал строку:
char *Buff = "Hello, ViKo!\r\n";
Передаю раз в секунду через CDC в STM32F3Discovery:
CDC_Transmit_FS((uint8_t *)Buff, sizeof Buff);
Получаю в терминальной программе:
HellHellHellHell...

Передаю иначе:
CDC_Transmit_FS((uint8_t *)Buff, sizeof *Buff);
Получаю:
HHHH...

Что же, компилятор не знает длину строки, что хранит в своих таблицах?

P.S. Естественно, когда пишу
CDC_Transmit_FS((uint8_t *)Buff, 14);
то все нормально.

P.P.S. и скобками аргумент для sizeof обкладывал, не помогло.
V_G
Поищите в вашей версии Си функцию типа strlen.
Использовать функцию sizeof для строки некорректно, она для другого предназначена.

ЗЫ. Посмотрите в отладчике, ваша строка, размещенная в памяти, нулем завершается? Все функции вычисления длины строки ищут окончание в виде нулевого байта.
ViKo
Цитата(V_G @ May 12 2015, 10:50) *
Поищите в вашей версии Си функцию типа strlen.
Использовать функцию sizeof для строки некорректно, она для другого предназначена.

ЗЫ. Посмотрите в отладчике, ваша строка, размещенная в памяти, нулем завершается? Все функции вычисления длины строки ищут окончание в виде нулевого байта.

Нулем завершается, конечно.
Написал по-простому:
char Buff[] = "Hello, ViKo!\r\n";
CDC_Transmit_FS((uint8_t *)Buff, sizeof Buff);
Все передается, и нуль тоже.
Hello, ViKo!<\r><\n><\0>

Мне непонятно, sizeof указателя должен же быть равен 4 для Cortex. Почему один символ передается?
Так нормально работает, спасибо!
char *Buff = "Hello, ViKo!\r\n";
CDC_Transmit_FS((uint8_t *)Buff, strlen (Buff));
CrimsonPig
Цитата(ViKo @ May 12 2015, 08:42) *
Что же, компилятор не знает длину строки, что хранит в своих таблицах?


А в чем проблема-то ? Читайте Кернигана с Ритчи и голова болеть не будет. Там все написано.

-- объявление указателя на инициализированный участок памяти
char* Buf = "abc";

sizeof(Buf) - это размер указателя на строку, в вашем случае, похоже, 4 байта.
sizeof(*Buf) - размер типа данных, на который этот указатель указывает, то есть char, в вашем сулчае 1 байт.

-- объявление _массива_
char Arr1[] = "asdf";
sizeof(Arr1) == sizeof(char)*_5_;

int Arr2[] = {1,2,3};
sizeof(Arr2) == sizeof(int)*3;

Длинна строки не обязательно должна быть равна длинне массива.
const char Str1 = "abcd\0asdf";
Длинна строки Str1 будет 4 символа.



aaarrr
Цитата(ViKo @ May 12 2015, 11:05) *
Мне непонятно, sizeof указателя должен же быть равен 4 для Cortex. Почему один символ передается?

Все правильно, для первого примера:
sizeof(Buff) возвращает размер указателя на char
sizeof(*Buff) возвращает размер char
ViKo
О, спасибо! Действительно, все оказалось просто, когда рассказали.
А длину строки, на которую указывает указатель, только с помощью strlen вычислять?
aaarrr
Цитата(ViKo @ May 12 2015, 11:24) *
А длину строки, на которую указывает указатель, только с помощью strlen вычислять?

Только так (или руками).
ViKo
Однако, sizeof вычисляется на этапе компиляции (обычно), а strlen нет.

Можно подставить макроопределение вместо строки.
#define STR_HI_ALL "Hi, All!"
char *Buff = STR_HI_ALL;
CDC_Transmit_FS((uint8_t *)Buff, sizeof(STR_HI_ALL));
Результат не проверял. Дома не на чем.
CrimsonPig
Цитата(ViKo @ May 12 2015, 17:15) *
Можно подставить макроопределение вместо строки.
#define STR_HI_ALL "Hi, All!"
char *Buff = STR_HI_ALL;
CDC_Transmit_FS((uint8_t *)Buff, sizeof(STR_HI_ALL));
Результат не проверял. Дома не на чем.


На кой? Чтоб запутать потенциального противника ?

Было же уже решение для вашего (непонятно зачем) случая:
const char szStr[] ="abcd";

Кстати, функция
CDC_Transmit_FS() объявлена коряво. По-хорошему, ее надо сделать такой:

void CDC_Transmit_FS(const void* apData, uint8_t aNumBytes);

Тогда не надо будет кастить первый аргумено при ее вызове с любым типом данных
ViKo
Цитата(CrimsonPig @ May 12 2015, 20:12) *
На кой? Чтоб запутать потенциального противника ?

Да, это уже не имеет смысла.
Цитата
Кстати, функция
CDC_Transmit_FS() объявлена коряво. По-хорошему, ее надо сделать такой:
void CDC_Transmit_FS(const void* apData, uint8_t aNumBytes);
Тогда не надо будет кастить первый аргумено при ее вызове с любым типом данных

Это камень в бошки программистов STM32Cube. rolleyes.gif
desh
Цитата
А длину строки, на которую указывает указатель, только с помощью strlen вычислять?


Если строка не меняется между вызовами, то через sizeof(Buff) - 1

Код
const uint8_t Buff[] = "Hello, ViKo!\r\n";
CDC_Transmit_FS(Buff, sizeof(Buff) - 1);


Цитата
Это камень в бошки программистов STM32Cube


Не вдаваясь в подробности реализации CDC_Transmit_FS внутри функции указатель типа uint8_t * проще инкрементировать или обращаться к произвольному элементу по индексу.
Сергей Борщ
Цитата(desh @ May 13 2015, 16:16) *
Не вдаваясь в подробности реализации CDC_Transmit_FS внутри функции указатель типа uint8_t * проще инкрементировать или обращаться к произвольному элементу по индексу.
Действия внутри функции - личное дело ее создателя. Никто и ничто не мешает ему создать локальную копию переданного указателя любого нужного типа. Поскольку функция может передавать что угодно, она должна получать "указатель на константное что угодно", т.е. void const *. В качестве примера можно посмотреть на memcpy() и подобные функции.
desh
Сергей, я Вас безмерно уважаю, но то что, так сделано в функции memcpy - это ни разу не аргумент. Функция CDC_Transmit_FS передает данные во внешний мир и передавать в нее что угодно как минимум не всегда корректно в плане переносимости между платформами из-за порядка байт и выравнивания структур.
Сергей Борщ
Цитата(desh @ May 13 2015, 17:07) *
Функция CDC_Transmit_FS передает данные
Вот именно, что данные. Которые совсем не обязательно будут массивом байтов. Поэтому возлагать на пользователя необходимость захламлять исходник явными приведениями типа указателя на эти данные к указателю на массив байтов по меньшей мере непрофессионально. Кроме всего прочего параметр должен быть указателем именно на константные данные, потому что функция эти данные не меняет, значит а) может работать и с константными данными (из флеша) и б) константность помогает компилятору сгенерить более оптимальный код.

Все это вопросы хорошего стиля и подобные ляпы в примерах от производителя чести этому производителю не делают.

сравните:

Код
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
....
}

void test()
{
    static char const Hello_string[] = "Слава мне, победителю драконов!";

    CDC_Transmit_FS((uint8_t*)Hello_string, sizeof(Hello_string) - 1);
}

и
Код
uint8_t CDC_Transmit_FS(void const * psrc, uint16_t Len)
{
     uint8_t const * Buf = (uint8_t const *)psrc;
....
}

void test()
{
    static char const Hello_string[] = "Слава мне, победителю драконов!";

    CDC_Transmit_FS(Hello_string, sizeof(Hello_string) - 1);
}

одна строка в исходнике библиотечной функции разгружает от мусора исходник приложения и позволяет сосредоточится на решении задачи.
demiurg_spb
Цитата(ViKo @ May 12 2015, 19:15) *
Однако, sizeof вычисляется на этапе компиляции (обычно), а strlen нет.
Зависит от компилятора.
Например GCC благодаря Built-in Functions умеет считать длину константной строки на этапе компиляции даже при использовании strlen.
Эдди
Цитата(Сергей Борщ @ May 13 2015, 17:17) *
одна строка в исходнике библиотечной функции разгружает от мусора исходник приложения и позволяет сосредоточится на решении задачи.

Угу. Скажите это быдлокодерам из STM. Они сколько лет SPL пилили, пока не поняли, что говно сваяли? А теперь другой кал пилят.
Не надо этой гадостью пользоваться, умоляю!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.