Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
1 / 1 / 0
Регистрация: 08.06.2015
Сообщений: 13
1

При попытке вычислить длину строки стандартной функцией strlen возникает ошибка

17.06.2015, 19:39. Показов 1808. Ответов 13
Метки нет (Все метки)

Есть код, в котором объявлена volatile-переменная c_buf, представляющая собой массив символов:
C
1
2
3
4
unsigned int l;
volatile char c_buf[11] = "\0";
//......................................
l = strlen(c_buf);
При попытке вычислить длину строки стандартной функцией strlen возникает закономерная ошибка несоответствия типов:
Type error in argument 1 to 'strlen'; expected 'const char *' but found 'volatile char *'
Как быть в такой ситуации? Написать свою реализацию strlen или возможен какой-нибудь другой подход?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.06.2015, 19:39
Ответы с готовыми решениями:

Ошибка при работе с функцией strlen
#include <iostream> #include <cstring> using namespace std; int main(){ string a; int...

Возникает ошибка при попытке регистрации
Здравствуйте, недавно начал изучать андроид, и его взаимодействие с php скриптом, а также БД...

При попытке сделать фильтрацию возникает ошибка
Добрый день. Ситуация такая: подключился к БД созданной в MSAccess. Вывел данные из неё в DBGrid....

При попытке вывести на экран данные из БД возникает ошибка
Контролер using System; using System.Collections.Generic; using System.Linq; using...

__________________
13
Эксперт С++
3057 / 1399 / 421
Регистрация: 19.01.2009
Сообщений: 3,770
17.06.2015, 19:43 2
colvern, в таком случае так же можно каст использовать:
C
1
l = strlen((char*)c_buf);
но нужно глядеть где и как изменяется c_buf, может проще в том источнике где изменяется
c_buf и обновлять какую-нибудь volatile int c_len - размер строки c_buf
1
1 / 1 / 0
Регистрация: 08.06.2015
Сообщений: 13
17.06.2015, 19:56  [ТС] 3
Благодарю, так работает.
А можно подробнее, (char*) это приведение типа? Звездочка для там для чего?
Просто я пытался сделать тоже самое без звездочки, но безрезультатно.
Си недавно начал осваивать.

Добавлено через 7 минут
Вроде понял, мы привели c_buf к указателю на тип char, верно? Потому что strlen с указателем работает.
0
Клюг
7669 / 3184 / 382
Регистрация: 03.05.2011
Сообщений: 8,381
17.06.2015, 21:57 4
Достотаточно перед вызовом добавить строчку #undef strlen, тогда прототип запомнится по первому вызову. Но будет матюг Warning! W131: No prototype found for function 'strlen', но его можно выключить.
Watcom C 1.8.
0
Псевдослучайный
1939 / 1139 / 97
Регистрация: 13.09.2011
Сообщений: 3,209
18.06.2015, 03:31 5
Квалификатор volatile для строк сам по себе — это весьма сомнительное решение. Почти наверняка это следствие ошибки в архитектуре кода.

Не по теме:

Цитата Сообщение от Charles Kludge Посмотреть сообщение
Достотаточно перед вызовом добавить строчку #undef strlen, тогда прототип запомнится по первому вызову. Но будет матюг Warning! W131: No prototype found for function 'strlen', но его можно выключить.
А это ещё более сомнительно решение. Всё-таки иногда лучше понять, что происходит, прежде, чем начинать что-то делать.

0
1 / 1 / 0
Регистрация: 08.06.2015
Сообщений: 13
18.06.2015, 19:06  [ТС] 6
NoMasters,
volatile в данном случае представляет собой массив символов. Содержимое этого массива меняется по аппаратному прерыванию. Он представляет из себя циклический буфер приемника. Как я понимаю volatile и нужно в таком случае для того, чтобы компилятор правильно обработал такую переменную. Если не прав, поправьте пожалуйста.
0
Evg
Эксперт CАвтор FAQ
21159 / 8175 / 628
Регистрация: 30.03.2009
Сообщений: 22,473
Записей в блоге: 30
18.06.2015, 20:43 7
Цитата Сообщение от colvern Посмотреть сообщение
volatile в данном случае представляет собой массив символов. Содержимое этого массива меняется по аппаратному прерыванию. Он представляет из себя циклический буфер приемника.
Именно поэтому всегда есть вероятность того, что внутри strlen'а что-то некорректно отработает. Функции работы со строками никак не рассчитаны на то, что в процессе работы эти строки кто-то будет модифицировать. Если ты гарантируешь, что на время вызова strlen'а никакая аппаратура строке не изменит, то построив преобразование к const char* (что несколько честнее, чем к char*) ты как бы и сообщаешь компилятору сей факт

Цитата Сообщение от colvern Посмотреть сообщение
Как я понимаю volatile и нужно в таком случае для того, чтобы компилятор правильно обработал такую переменную. Если не прав, поправьте пожалуйста
Правальная работа с такой переменной в данном случае - это ругань, причина описана выше
0
2051 / 1526 / 167
Регистрация: 14.12.2014
Сообщений: 13,326
18.06.2015, 20:59 8
Цитата Сообщение от colvern Посмотреть сообщение
Он представляет из себя циклический буфер приемника.
Если буфер циклический то каким образом strlen его длину посчитает? Длина циклического буфера считается как разница между головой и хвостом, с учетом заворота через край, а не как количество символов от нулевого элемента до нуля.
0
Клюг
7669 / 3184 / 382
Регистрация: 03.05.2011
Сообщений: 8,381
18.06.2015, 21:10 9
Цитата Сообщение от colvern Посмотреть сообщение
Содержимое этого массива меняется по аппаратному прерыванию.
Дык, тогда и вся работа с приёмом символов в буфер должна быть в обработчике прерываний и писана на асме или Си-- без использования strlen. А при извлечении символов на время корректировки указателей и счётчиков прерывания должны быть запрещены.
0
2051 / 1526 / 167
Регистрация: 14.12.2014
Сообщений: 13,326
18.06.2015, 21:35 10
Лови пример с приемом на прерывании в циклический буфер. Код надежный. Крутился в АСУТП годами без перезагрузок.
0
Вложения
Тип файла: rar TERMINAL.rar (2.7 Кб, 4 просмотров)
1 / 1 / 0
Регистрация: 08.06.2015
Сообщений: 13
18.06.2015, 22:34  [ТС] 11
Благодарю всех.
Запись в буфер происходит в обработчике прерывания.
strlen считает длину буфера,как длину строки до \0, т.к. массив строковый, хранятся в нем ASCii-символы.
Атомарность модификации буфера при считывании из него символа в основной программе обеспечена выключением/включением прерывания, поэтому никаких неожиданных модификаций этой переменной не предполагается. Тогда вопрос в другом, нужно ли вообще в таком случае объявлять переменную как volatile?

Ну и чтобы было понятно, код примерно такой(рабочий):
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
volatile char uartRxBuf = 0;                // однобайтный буфер UART
volatile char c_buf[BUFFER_SIZE + 1] = "\0";    // циклический буфер UART
 
// запись символа в кольцевой буфер
void pushChar(char c){
    unsigned int l, i; 
    l = strlen((char*)c_buf);               // считываем кол-во символов в буфере
    if(l == BUFFER_SIZE){           // если буфер переполнен, то...
        for(i=0; i < BUFFER_SIZE - 1; i++){     // сдвигаем буфер влево на один символ
            c_buf[i] = c_buf[i+1];
        }
        c_buf[i] = c;               // в последнюю позицию записываем поступивший символ
    } else {                        // если буфер не переполнен, то...
        c_buf[l] = c;                       // добавляем в него поступивший символ
    }
}
 
// получение символа из кольцевого буфера
char shiftChar(void){
    unsigned int l, i;
    char c = '\0';                  // если буфер пуст, вернем нуль
    ATOMIC_BLOCK(ATOMIC_FORCEON){   // выделяем блок кода, прерывания в котором запрещены
        l = strlen((char*)c_buf);           // считываем кол-во символов в буфере
        if(l){                      // если буфер не пуст, то...
            c = c_buf[0];                   // забираем символ из первой позиции
            if(l == 1){                 // если в буфере только один символ, то...
                c_buf[0] = '\0';                // очищаем буфер
            } else {                    // если в буфере несколько символов, то...
                for(i=0; i < l - 1; i++){   // сдвигаем буфер влево на один символ
                    c_buf[i] = c_buf[i+1];
                }
                c_buf[l - 1] = '\0';            // последнюю позицию зануляем
            }
        }
    }
    return c;
}
 
ISR(USART_RX_vect)      // вектор прерывания UART - завершение приема
{
    uartRxBuf = UDR0;
    pushChar(uartRxBuf);
    uartRxBuf = 0;
}
0
2051 / 1526 / 167
Регистрация: 14.12.2014
Сообщений: 13,326
18.06.2015, 23:07 12
Дык это сдвиговый буфер а не кольцевой.
0
1 / 1 / 0
Регистрация: 08.06.2015
Сообщений: 13
18.06.2015, 23:16  [ТС] 13
Fulcrum_013,
Да, всё верно, ошибся с терминологией, в кольцевом всё несколько иначе.
https://ru.wikipedia.org/wiki/Кольцевой_буфер
0
Evg
Эксперт CАвтор FAQ
21159 / 8175 / 628
Регистрация: 30.03.2009
Сообщений: 22,473
Записей в блоге: 30
19.06.2015, 11:50 14
Цитата Сообщение от colvern Посмотреть сообщение
Тогда вопрос в другом, нужно ли вообще в таком случае объявлять переменную как volatile?
Если я правильно понял твой фрагмент кода, то аппаратура НЕ пишет в буфер, в буфер запись идёт программно из обработчика прерываний. Если вся работа с буфером сосредоточена в функциях pushChar и shiftChar, а в процессе работы этих функций прерывание не срабатывает, то volatile не нужен. volatile нужен тогда, когда в "обычном" коде, который работает с буфером, возможны прерывания с модификацией буфера. Т.е. компилятор, глядя на код программы сим никак не сможет догадаться, что в последовательности типа:

C
char c1 = buf[0];
char c2 = buf[0];
два обращения к buf[0] могут выдать различные значения.
2
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.06.2015, 11:50

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

[Error SIGSEGV] Возникает ошибка при попытке присваивания
Есть 3 юнита: Первый - основной интерфейс программы Второй - интерфейс загрузки (тут ProgressBar)...

При попытке чтения ini файла возникает ошибка
При выполнении программы возникает ошибка, как ее исправить? #include &lt;windows.h&gt; void...

Возникает ошибка при попытке авторизации в ВК через VkApi
Ребята есть некая задача. Нужно написать простенькую программу для работы с ВК. В Интернете нашел...

Возникает неизвестная ошибка при попытке скомпилировать программу
#include &lt;iostream&gt; #include &lt;iomanip&gt; #include &lt;math.h&gt; #include &lt;conio.h&gt; #define LIM 5.5 ...

При попытке записать в app.config возникает ошибка NullReferenceException
Возникает NullReferenceException. Почему? App.config присутствует в проекте. Configuration...

При попытке запуска WCF службы на другой машине возникает ошибка TCP 10013
Добрый день. Написал WCF-службу. Хостом является Windows-служба. На одной из машин работает...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.