Перейти к содержанию
    

Передача указателя в качестве аргумента.

Есть такая функция.

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. Подскажите где ошибка.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Передавать надо указатель на указатель.

 

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;
   }

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подскажите где ошибка.
Ошибка в вашем стойком нежелании учить язык путем чтения документации. Потратьте наконец один день на чтение Кернигана и Ритчи.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть такая функция.

// 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

return 0;

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

return 0;

 

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

описка.

 

При "проверке" внутри функции значение pchr меняется так, как написано, но нигде не сказано компилятору, что значение надо оттуда вытащить наружу в вызывающую функцию.

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

 

Ошибка в вашем стойком нежелании учить язык путем чтения документации. Потратьте наконец один день на чтение Кернигана и Ритчи.

 

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

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

:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 );

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

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

вы считаете что монструозная sprint это попроще? :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

кстати сделал проверку

   #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 раза меньше.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

посмотрел листинг - размер кода с strcat почти в 2 раза меньше.
Зато memcpy скорее всего быстрее

 

    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];

Хорошо, что в C++ пока нет такой мерзости как локальные массивы переменного размера

 

Изменено пользователем conan

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зато memcpy скорее всего быстрее

 

    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];

Хорошо, что в C++ пока нет такой мерзости как локальные массивы переменного размера

я думал над этим. тут конечно есть опасность stack overflow. но я думаю есть механизмы контроля. вроде регистр SP доступен. можно посмотреть где мы находимся в стаке и вычислить сколько осталось места?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не, массивы переменной длины иногда могут быть полезны. Но этот код является наглядной иллюстрацией к "если бы строители строили дома так же, как программисты пишут программы, то первый же залетный дятел порушил бы цивилизацию":

    uint32_t el_size = strlen(el_name);
    char buf[el_size+4];

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

 

но я думаю есть механизмы контроля. вроде регистр SP доступен. можно посмотреть где мы находимся в стеке и вычислить сколько осталось места?
И где тут такие проверки?

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не, массивы переменной длины иногда могут быть полезны. Но этот код является наглядной иллюстрацией к "если бы строители строили дома так же, как программисты пишут программы, то первый же залетный дятел порушил бы цивилизацию":

    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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

 

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

поэтому я думаю правильней сделать END_OF_STACK – SP.

Чушь

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...