Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Препроцессор. Или inline ф-ция как макрос.


Автор: andrew_121 8.6.2008, 14:06
День добрый.

Нужно стандартные ф-ции, типа:
Код

strcpy
strcat
strcmp
...

Реализовать в виде макроса. Сама реализация понятна, но как вернуть значение ?

Код

#define strcmp(dst, src) { \
    if ( !src || !*src || !dst ) { \
        return src; \
    } \
    char* res = dst; \
    while ( *src ) { \
        *dst++ = *src++; \
    } \
    return res; \
} \



Что вернет return ?

Автор: Daevaorn 8.6.2008, 14:12
Цитата(andrew_121 @  8.6.2008,  15:06 Найти цитируемый пост)
Что вернет return ? 

return вернет res. Только этого не будет ожидать клиентский код . Поэтому, во все макросы надо добавить ещё один параметр, куда записывать результат.

Автор: andrew_121 8.6.2008, 14:15
Daevaorn: Примерчик можно...

Есть еще мнения?

Автор: mes 8.6.2008, 14:24
Цитата(andrew_121 @  8.6.2008,  14:06 Найти цитируемый пост)
#define strcmp(dst, src) { \
    if ( !src || !*src || !dst ) { \
        return src; \
    } \
    char* res = dst; \
    while ( *src ) { \
        *dst++ = *src++; \
    } \
    return res; \
} \

при использовании макроса будет построена следуюшая комбинация
Код


вместо: strcmp(src,dst) 
будет :
{
    if ( !src || !*src || !dst ) {       return src;    }
    char* res = dst; 
    while ( *src ) {      *dst++ = *src++;     } 
    return res; 
} 


// то есть построится тело функции , а это совсем не то что вы хотели 
// хотя что именно хотели получить , не понятно
// если функцию стравнения для любого типа (то непонятно тогда почему название strcmp)- то смотреть в сторону шаблона
// если функцию для сравнения строк то #define там не нужен



Автор: baldina 8.6.2008, 14:29
макрос должен представлять выражение, имеющее значение. естественно, никаких return
как-то так: 
Код

#define strcmp(_res, _s1, _s2) { \
  char *s1=_s1, *s2=_s2; \
   while (*_s1 && (_res=*s2++-*s1++)==0); \
 }

Автор: andrew_121 8.6.2008, 14:31
mes: Что получиться я заню, от этого и вопрос - Как из тела функции в виде макроса, получить результат ???

Добавлено через 4 минуты и 40 секунд
baldina: Спасибо. Щас буду тестить.
По идее такая реализация строковых функций должна работать быстрее стандартной.
А какие подводные камни появятся...?

Автор: baldina 8.6.2008, 14:39
про выражение написал, а значения не показал  smile 
не получится тут "вернуть", нужен параметр макроса для результата

Добавлено через 4 минуты и 45 секунд
Цитата

такая реализация строковых функций должна работать быстрее стандартной

отнюдь. стандартная на ассемблере написана smile 
если надо избежать накладные расходы на вызов функции, используй inline 
кстати, современные компиляторы умеют в режиме оптимизации встраивать такие функции как strcmp, strcpy, pow, sqrt, sin и т.п. (intrinsic functions)

Автор: andrew_121 8.6.2008, 14:58
Цитата

кстати, современные компиляторы умеют в режиме оптимизации встраивать такие функции как strcmp, strcpy, pow, sqrt, sin и т.п. (intrinsic functions)


Знаю про это.
Но практика показывает, что это не всегда происходит. И не понятно от чего и почему...

Автор: Lazin 8.6.2008, 14:59
Цитата(andrew_121 @  8.6.2008,  14:15 Найти цитируемый пост)
Есть еще мнения?

макросы для этих целей использовать нельзя, это дурной тон.
Как уже было сказано, компилятор в состоянии сам определить, где требуется функцию вызвать а где ее лучше встроить. 
В случае использования макросов таким вот образом, страдает ясность кода, большинство IDE не смогут сделать подсказку для макроса, статические анализаторы кода то-же отдыхают. 
К тому-же, возможны тяжело обнаруживаемые ошибки.

Автор: mes 8.6.2008, 15:02
Цитата(andrew_121 @  8.6.2008,  14:31 Найти цитируемый пост)
Что получиться я заню, от этого и вопрос - Как из тела функции в виде макроса, получить результат ???

не использовать слово return, например
#define test(dst, src)  ( !src || !*src || !dst ) ? src : dst

но в любом случае не понятна цель - если для скорости - то такой путь заблуждение

Автор: Lazin 8.6.2008, 15:03
Цитата(andrew_121 @  8.6.2008,  14:58 Найти цитируемый пост)
Знаю про это.
Но практика показывает, что это не всегда происходит. И не понятно от чего и почему... 

это происходит, для того, что-бы уменьшить объем кода.
там где это может дать увеличение производительности, например в цикле, встраивание происходит. если функция вызывается всего один раз, то экономить пару наносекунд тратящихся на ее вызов нет смысла smile 

Автор: andrew_121 8.6.2008, 15:18
mes: Да, для скорости...
Так как большие изменения в программу вносить не хочется.
Это один из простых способов.

Добавлено @ 15:24
Вот что я сделал:
Код

#define mystrcmp2(_res, _s1, _s2) { \
    char *s1=_s1, *s2=_s2; \
    while (*s1 && (_res=*s2++-*s1++)==0); \
}
 
int main() {

    char str1[128] = "abcdef";
    char str2[128] = "abcdef";
    int res = 0;
    
    mystrcmp2( res, str1, str2 );
    
    printf( (res == 0) ? "res = %d string is equal!\n" : "res = %d string is not equal!\n", res );
    
    return res;
}



Гну препроцессор сотворяет вот что:
Код

int main() {

 char str1[128] = "abcdef";
 char str2[128] = "abcdef";
 int res = 0;

 { char *s1=str1, *s2=str2; while (*s1 && (res=*s2++-*s1++)==0); };

 printf( (res == 0) ? "res = %d string is equal!\n" : "res = %d string is not equal!\n", res );

 return res;
}


Но почему-то res = 84, а не 0.
Первый недостаток макросов - хрен отладишь!!!

А...вот опечатка:  while (*s1 && (res=*s2++-*s1++)==0);

Автор: MAKCim 8.6.2008, 15:31
в GCC решение такое
Код

#define strcmp(dst, src) {( \
    if ( !src || !*src || !dst ) src; \
    char* res = dst; \
    while (*src++ = *dst++); \
    res; })

Цитата

A compound statement enclosed in parentheses may appear as an expression in GNU C.
This allows you to use loops, switches, and local variables within an expression.

в коде ядра Linux данное расширение широко используется

Автор: andrew_121 8.6.2008, 15:38
MAKCim Т.е. запись вида:
Код

char* result = strcmp( "abcdef", "abcdef" );

Будет трактоваться как:
Код

char* result = src || res

В зависимости от результата...?

Автор: MAKCim 8.6.2008, 15:39
Цитата(andrew_121 @  8.6.2008,  15:38 Найти цитируемый пост)
В зависимости от результата...? 

да, только, наверное, макрос должен называться strcpy, а не strcmp  smile 

Автор: andrew_121 8.6.2008, 15:42
Всем Благодарен.
В особености baldina и MAKCim.

Добавлено через 2 минуты и 28 секунд
Цитата(MAKCim @ 8.6.2008,  15:39)
Цитата(andrew_121 @  8.6.2008,  15:38 Найти цитируемый пост)
В зависимости от результата...? 

да, только, наверное, макрос должен называться strcpy, а не strcmp  smile

Пардон...я заметил позже...
Но не стал изменять название функции.

P.S.
Ты единственный кто заметил  smile 

Автор: andrew_121 8.6.2008, 15:59
Хотя...это гибрид какой-то...
Суть не в этом.

Автор: UnrealMan 8.6.2008, 16:48
Цитата(MAKCim @  8.6.2008,  15:31 Найти цитируемый пост)
A compound statement enclosed in parentheses may appear as an expression in GNU C.

Жесть smile 

Автор: MAKCim 8.6.2008, 16:57
Цитата(UnrealMan @  8.6.2008,  16:48 Найти цитируемый пост)
Жесть

а то  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)