|
Передача указателя в качестве аргумента. |
|
|
|
Dec 20 2016, 10:33
|
Профессионал
    
Группа: Участник
Сообщений: 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. Подскажите где ошибка.
|
|
|
|
|
Dec 20 2016, 10:43
|
Профессионал
    
Группа: Свой
Сообщений: 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; }
|
|
|
|
|
Dec 20 2016, 10:46
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Dec 20 2016, 10:46
|
Знающий
   
Группа: Участник
Сообщений: 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
|
|
|
|
|
Dec 20 2016, 10:57
|
Участник

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

|
if (!XML_PARSER_FindElementEnd(xml_str, parent, pchr_test)); return 0;
Точка с запятой в первой строчке - так задумано?
|
|
|
|
|
Dec 20 2016, 11:10
|
Профессионал
    
Группа: Участник
Сообщений: 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)  Ошибка в вашем стойком нежелании учить язык путем чтения документации. Потратьте наконец один день на чтение Кернигана и Ритчи.
Аргументы в функцию передаются по значению. Цитата его пример другим наука.
|
|
|
|
|
Dec 20 2016, 11:48
|

Профессионал
    
Группа: Свой
Сообщений: 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 штук).
|
|
|
|
|
Dec 20 2016, 12:05
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(megajohn @ Dec 20 2016, 17:48)  какая то магия понаписана может попроще для людей сделать ? Код char buf[ el_size + sizeof( "</>" ) ]; sprintf( buff, "<%s/>", el_name ); вы считаете что монструозная sprint это попроще?
|
|
|
|
|
Dec 20 2016, 13:14
|
Профессионал
    
Группа: Участник
Сообщений: 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 раза меньше.
|
|
|
|
|
Dec 21 2016, 02:38
|
Участник

Группа: Участник
Сообщений: 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
|
|
|
|
|
Dec 21 2016, 06:37
|
Профессионал
    
Группа: Участник
Сообщений: 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 доступен. можно посмотреть где мы находимся в стаке и вычислить сколько осталось места?
|
|
|
|
|
Dec 21 2016, 06:51
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Dec 21 2016, 07:03
|
Профессионал
    
Группа: Участник
Сообщений: 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
|
|
|
|
|
Dec 21 2016, 09:12
|
Участник

Группа: Участник
Сообщений: 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. Чушь
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|