ViKo 1 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба Создал строку: 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 11 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба Поищите в вашей версии Си функцию типа strlen. Использовать функцию sizeof для строки некорректно, она для другого предназначена. ЗЫ. Посмотрите в отладчике, ваша строка, размещенная в памяти, нулем завершается? Все функции вычисления длины строки ищут окончание в виде нулевого байта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба Поищите в вашей версии Си функцию типа 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 0 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба Что же, компилятор не знает длину строки, что хранит в своих таблицах? А в чем проблема-то ? Читайте Кернигана с Ритчи и голова болеть не будет. Там все написано. -- объявление указателя на инициализированный участок памяти 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 69 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба Мне непонятно, sizeof указателя должен же быть равен 4 для Cortex. Почему один символ передается? Все правильно, для первого примера: sizeof(Buff) возвращает размер указателя на char sizeof(*Buff) возвращает размер char Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба О, спасибо! Действительно, все оказалось просто, когда рассказали. А длину строки, на которую указывает указатель, только с помощью strlen вычислять? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба А длину строки, на которую указывает указатель, только с помощью strlen вычислять? Только так (или руками). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба Однако, sizeof вычисляется на этапе компиляции (обычно), а strlen нет. Можно подставить макроопределение вместо строки. #define STR_HI_ALL "Hi, All!" char *Buff = STR_HI_ALL; CDC_Transmit_FS((uint8_t *)Buff, sizeof(STR_HI_ALL)); Результат не проверял. Дома не на чем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrimsonPig 0 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба Можно подставить макроопределение вместо строки. #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 1 12 мая, 2015 Опубликовано 12 мая, 2015 · Жалоба На кой? Чтоб запутать потенциального противника ? Да, это уже не имеет смысла. Кстати, функция CDC_Transmit_FS() объявлена коряво. По-хорошему, ее надо сделать такой: void CDC_Transmit_FS(const void* apData, uint8_t aNumBytes); Тогда не надо будет кастить первый аргумено при ее вызове с любым типом данных Это камень в бошки программистов STM32Cube. :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 13 мая, 2015 Опубликовано 13 мая, 2015 · Жалоба А длину строки, на которую указывает указатель, только с помощью 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 * проще инкрементировать или обращаться к произвольному элементу по индексу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 13 мая, 2015 Опубликовано 13 мая, 2015 · Жалоба Не вдаваясь в подробности реализации CDC_Transmit_FS внутри функции указатель типа uint8_t * проще инкрементировать или обращаться к произвольному элементу по индексу.Действия внутри функции - личное дело ее создателя. Никто и ничто не мешает ему создать локальную копию переданного указателя любого нужного типа. Поскольку функция может передавать что угодно, она должна получать "указатель на константное что угодно", т.е. void const *. В качестве примера можно посмотреть на memcpy() и подобные функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
desh 0 13 мая, 2015 Опубликовано 13 мая, 2015 · Жалоба Сергей, я Вас безмерно уважаю, но то что, так сделано в функции memcpy - это ни разу не аргумент. Функция CDC_Transmit_FS передает данные во внешний мир и передавать в нее что угодно как минимум не всегда корректно в плане переносимости между платформами из-за порядка байт и выравнивания структур. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 13 мая, 2015 Опубликовано 13 мая, 2015 · Жалоба Функция 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 0 13 мая, 2015 Опубликовано 13 мая, 2015 · Жалоба Однако, sizeof вычисляется на этапе компиляции (обычно), а strlen нет.Зависит от компилятора. Например GCC благодаря Built-in Functions умеет считать длину константной строки на этапе компиляции даже при использовании strlen. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться