реклама на сайте
подробности

 
 
> Как я получил Адъ, sizeof string
ViKo
сообщение May 12 2015, 07:42
Сообщение #1


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Создал строку:
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 обкладывал, не помогло.
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 15)
V_G
сообщение May 12 2015, 07:50
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955



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

ЗЫ. Посмотрите в отладчике, ваша строка, размещенная в памяти, нулем завершается? Все функции вычисления длины строки ищут окончание в виде нулевого байта.
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 12 2015, 08:05
Сообщение #3


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(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));
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение May 12 2015, 08:18
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502



Цитата(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 символа.



Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 12 2015, 08:21
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



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

Все правильно, для первого примера:
sizeof(Buff) возвращает размер указателя на char
sizeof(*Buff) возвращает размер char
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 12 2015, 08:24
Сообщение #6


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



О, спасибо! Действительно, все оказалось просто, когда рассказали.
А длину строки, на которую указывает указатель, только с помощью strlen вычислять?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение May 12 2015, 08:29
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(ViKo @ May 12 2015, 11:24) *
А длину строки, на которую указывает указатель, только с помощью strlen вычислять?

Только так (или руками).
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 12 2015, 16:15
Сообщение #8


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



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

Можно подставить макроопределение вместо строки.
#define STR_HI_ALL "Hi, All!"
char *Buff = STR_HI_ALL;
CDC_Transmit_FS((uint8_t *)Buff, sizeof(STR_HI_ALL));
Результат не проверял. Дома не на чем.
Go to the top of the page
 
+Quote Post
CrimsonPig
сообщение May 12 2015, 17:12
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502



Цитата(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);

Тогда не надо будет кастить первый аргумено при ее вызове с любым типом данных
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 12 2015, 18:44
Сообщение #10


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



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

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

Это камень в бошки программистов STM32Cube. rolleyes.gif
Go to the top of the page
 
+Quote Post
desh
сообщение May 13 2015, 13:16
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 113
Регистрация: 25-10-07
Из: Краснодар
Пользователь №: 31 725



Цитата
А длину строки, на которую указывает указатель, только с помощью 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 * проще инкрементировать или обращаться к произвольному элементу по индексу.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 13 2015, 13:23
Сообщение #12


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
desh
сообщение May 13 2015, 14:07
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 113
Регистрация: 25-10-07
Из: Краснодар
Пользователь №: 31 725



Сергей, я Вас безмерно уважаю, но то что, так сделано в функции memcpy - это ни разу не аргумент. Функция CDC_Transmit_FS передает данные во внешний мир и передавать в нее что угодно как минимум не всегда корректно в плане переносимости между платформами из-за порядка байт и выравнивания структур.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 13 2015, 14:17
Сообщение #14


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(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);
}

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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 13 2015, 14:47
Сообщение #15


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



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


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Эдди
сообщение May 13 2015, 15:32
Сообщение #16


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



Цитата(Сергей Борщ @ May 13 2015, 17:17) *
одна строка в исходнике библиотечной функции разгружает от мусора исходник приложения и позволяет сосредоточится на решении задачи.

Угу. Скажите это быдлокодерам из STM. Они сколько лет SPL пилили, пока не поняли, что говно сваяли? А теперь другой кал пилят.
Не надо этой гадостью пользоваться, умоляю!
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 15:29
Рейтинг@Mail.ru


Страница сгенерированна за 0.01486 секунд с 7
ELECTRONIX ©2004-2016