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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Передача указателя в качестве аргумента.
Jenya7
сообщение Dec 20 2016, 10:33
Сообщение #1


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

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Есть такая функция.
Код
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char* pchr)
{
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
  
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], "/>\0", 3);
    
    pchr = strstr(xml_str, buf);
    if(pchr == NULL) return 0;
    else return 1;
}

Внутри функции pchr принимает правильное значение, все прекрасно.

Проверяем
Код
uint32_t  XML_PARSER_NewElement(char *xml_str, char *parent, char* el_name)
{
    char *pchr_test=NULL;

    if (!XML_PARSER_FindElementEnd(xml_str, parent, pchr_test));
        return 0;
}

pchr_test остается 0. Подскажите где ошибка.
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Dec 20 2016, 10:43
Сообщение #2


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

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(Jenya7 @ Dec 20 2016, 13:33) *
Подскажите где ошибка.

В функцию передаётся копия указателя, поэтому вы изменяете копию.
Передавать надо указатель на указатель.

Код
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char** pchr)
   {
       uint32_t el_size = strlen(el_name);
       char buf[el_size+4];
    
       memcpy(&buf[0], "<", 1);
       memcpy(&buf[1], el_name, el_size);
       memcpy(&buf[el_size+1], "/>\0", 3);
      
       *pchr = strstr(xml_str, buf);
       if(*pchr == NULL) return 0;
       else return 1;
   }

uint32_t  XML_PARSER_NewElement(char *xml_str, char *parent, char* el_name)
   {
       char *pchr_test=NULL;
  
       if (!XML_PARSER_FindElementEnd(xml_str, parent, &pchr_test));
           return 0;
   }
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 20 2016, 10:46
Сообщение #3


Гуру
******

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



QUOTE (Jenya7 @ Dec 20 2016, 12:33) *
Подскажите где ошибка.
Ошибка в вашем стойком нежелании учить язык путем чтения документации. Потратьте наконец один день на чтение Кернигана и Ритчи.

Аргументы в функцию передаются по значению.


--------------------
На любой вопрос даю любой ответ
"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
novikovfb
сообщение Dec 20 2016, 10:46
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 518
Регистрация: 29-09-11
Пользователь №: 67 450



Цитата(Jenya7 @ Dec 20 2016, 14:33) *
Есть такая функция.
Код
// pchr - входное значение типа "указатель на char"
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char* pchr)
{
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
  
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], "/>\0", 3);
    
    pchr = strstr(xml_str, buf);// игнориуем исходное значение, заменяем его на результат strstr
    if(pchr == NULL) return 0;
    else return 1;
}

Внутри функции pchr принимает правильное значение, все прекрасно.

Проверяем
Код
uint32_t  XML_PARSER_NewElement(char *xml_str, char *parent, char* el_name)
{
    char *pchr_test=NULL;

    if (!XML_PARSER_FindElementEnd(xml_str, parent, pchr_test));
        return 0;
}

pchr_test остается 0. Подскажите где ошибка.

При "проверке" внутри функции значение pchr меняется так, как написано, но нигде не сказано компилятору, что значение надо оттуда вытащить наружу в вызывающую функцию.
Для языка C можно переписать так:
Код
// ppchr - входное значение типа "указатель на указатель на char"
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char** ppchr)
{
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
  
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], "/>\0", 3);
    
    *ppchr = strstr(xml_str, buf);// по адресу ppchr записываем результат strstr
    if(ppchr == NULL) return 0;
    else return 1;
}
uint32_t  XML_PARSER_NewElement(char *xml_str, char *parent, char* el_name)
{
    char *pchr_test=NULL;

    if (!XML_PARSER_FindElementEnd(xml_str, parent, &pchr_test));// передаем адрес pchr_test - указатель на указатель на char
        return 0;
}

для языка C++ есть более интересная возможность - передача по ссылке

Сообщение отредактировал novikovfb - Dec 20 2016, 10:48
Go to the top of the page
 
+Quote Post
ucMike
сообщение Dec 20 2016, 10:57
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 60
Регистрация: 21-11-08
Пользователь №: 41 832



if (!XML_PARSER_FindElementEnd(xml_str, parent, pchr_test));
return 0;

Точка с запятой в первой строчке - так задумано?
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 20 2016, 11:10
Сообщение #6


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

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(ucMike @ Dec 20 2016, 16:57) *
if (!XML_PARSER_FindElementEnd(xml_str, parent, pchr_test));
return 0;

Точка с запятой в первой строчке - так задумано?

описка.

Цитата(novikovfb @ Dec 20 2016, 16:46) *
При "проверке" внутри функции значение pchr меняется так, как написано, но нигде не сказано компилятору, что значение надо оттуда вытащить наружу в вызывающую функцию.

упс... точно. надо указатель на указатель использовать. char** pchr. спасибо.

Цитата(Сергей Борщ @ Dec 20 2016, 16:46) *
Ошибка в вашем стойком нежелании учить язык путем чтения документации. Потратьте наконец один день на чтение Кернигана и Ритчи.

Аргументы в функцию передаются по значению.

Цитата
его пример другим наука.

sm.gif
Go to the top of the page
 
+Quote Post
megajohn
сообщение Dec 20 2016, 11:48
Сообщение #7


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(Jenya7 @ Dec 20 2016, 13:33) *
Код
uint32_t XML_PARSER_FindElementEnd(char *xml_str, char* el_name, char* pchr)
{
    char buf[el_size+4];
  
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], "/>\0", 3);
}


какая то магия понаписана

может попроще для людей сделать ?

Код
char buf[ el_size + sizeof( "</>" ) ];
sprintf( buff, "<%s/>",  el_name );


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 20 2016, 12:05
Сообщение #8


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

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(megajohn @ Dec 20 2016, 17:48) *
какая то магия понаписана

может попроще для людей сделать ?

Код
char buf[ el_size + sizeof( "</>" ) ];
sprintf( buff, "<%s/>",  el_name );

вы считаете что монструозная sprint это попроще? sm.gif
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 20 2016, 13:14
Сообщение #9


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

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



кстати сделал проверку
Код
   #if USE_MEMCPY
    memcpy(&buf[0], "<", 1);
    memcpy(&buf[1], el_name, el_size);
    memcpy(&buf[el_size+1], ">\0", 2);
    #else
    memset(buf, '\0', el_size+4);
    strcat(buf,"<");
    strcat(buf, el_name);
    strcat(buf, ">");
    #endif

посмотрел листинг - размер кода с strcat почти в 2 раза меньше.
Go to the top of the page
 
+Quote Post
conan
сообщение Dec 21 2016, 02:38
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 3-11-11
Пользователь №: 68 126



Цитата(Jenya7 @ Dec 20 2016, 16:14) *
посмотрел листинг - размер кода с strcat почти в 2 раза меньше.
Зато memcpy скорее всего быстрее

Код
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
Хорошо, что в C++ пока нет такой мерзости как локальные массивы переменного размера


Сообщение отредактировал conan - Dec 21 2016, 02:44
Go to the top of the page
 
+Quote Post
arhiv6
сообщение Dec 21 2016, 06:15
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 633
Регистрация: 21-05-10
Из: Томск
Пользователь №: 57 423



conan, а чем они Вам не нравятся?


--------------------
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Dec 21 2016, 06:37
Сообщение #12


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

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(conan @ Dec 21 2016, 08:38) *
Зато memcpy скорее всего быстрее

Код
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
Хорошо, что в C++ пока нет такой мерзости как локальные массивы переменного размера

я думал над этим. тут конечно есть опасность stack overflow. но я думаю есть механизмы контроля. вроде регистр SP доступен. можно посмотреть где мы находимся в стаке и вычислить сколько осталось места?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 21 2016, 06:51
Сообщение #13


Гуру
******

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



Не, массивы переменной длины иногда могут быть полезны. Но этот код является наглядной иллюстрацией к "если бы строители строили дома так же, как программисты пишут программы, то первый же залетный дятел порушил бы цивилизацию":
CODE
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
Если входной файл вдруг будет испорчен - можно легко нарваться на переполнение стека.

QUOTE (Jenya7 @ Dec 21 2016, 08:37) *
но я думаю есть механизмы контроля. вроде регистр SP доступен. можно посмотреть где мы находимся в стеке и вычислить сколько осталось места?
И где тут такие проверки?
Просто возвращайте 0 если el_size больше какого-то предела, на который у вас достаточно стека и в который заведомо укладываются все необходимые вам элементы.


--------------------
На любой вопрос даю любой ответ
"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
Jenya7
сообщение Dec 21 2016, 07:03
Сообщение #14


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

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(Сергей Борщ @ Dec 21 2016, 12:51) *
Не, массивы переменной длины иногда могут быть полезны. Но этот код является наглядной иллюстрацией к "если бы строители строили дома так же, как программисты пишут программы, то первый же залетный дятел порушил бы цивилизацию":
Код
    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];
Если входной файл вдруг будет испорчен - можно легко нарваться на переполнение стека.

И где тут такие проверки?
Просто возвращайте 0 если el_size больше какого-то предела, на который у вас достаточно стека и в который заведомо укладываются все необходимые вам элементы.

допустим размер стака 1К. А el_size 0.5К - вроде как места хватает. но я не знаю насколько заполнен стак до выделения места под el_size. есть код до него. вложенные ф-ции и.т.д и.т.п.
поэтому я думаю правильней сделать END_OF_STACK – SP.

Сообщение отредактировал Jenya7 - Dec 21 2016, 07:03
Go to the top of the page
 
+Quote Post
conan
сообщение Dec 21 2016, 09:12
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 3-11-11
Пользователь №: 68 126



Цитата(arhiv6 @ Dec 21 2016, 09:15) *
conan, а чем они Вам не нравятся?

Не эстетично же. Как минимум sizeof выносится в runtime


Цитата(Jenya7 @ Dec 21 2016, 10:03) *
допустим размер стака 1К. А el_size 0.5К - вроде как места хватает. но я не знаю насколько заполнен стак до выделения места под el_size. есть код до него. вложенные ф-ции и.т.д и.т.п.
поэтому я думаю правильней сделать END_OF_STACK – SP.

Чушь
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 19th June 2025 - 23:16
Рейтинг@Mail.ru


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