Кресты / Говнокод #4124 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
namespace markup 
{
    // case sensitive string equality test
    // s_lowcase shall be lowercase string
    inline bool equal(const char* s, const char* s1, size_t length)
    {
      switch(length)
      {
        case 8: if(s1[7] != s[7]) return false;
        case 7: if(s1[6] != s[6]) return false;
        case 6: if(s1[5] != s[5]) return false;
        case 5: if(s1[4] != s[4]) return false;
        case 4: if(s1[3] != s[3]) return false;
        case 3: if(s1[2] != s[2]) return false;
        case 2: if(s1[1] != s[1]) return false;
        case 1: if(s1[0] != s[0]) return false;
        case 0: return true;
        default: return strncmp(s,s1,length) == 0;
      }
    }
...

Запостил: rat4 rat4, (Updated )

Комментарии (40) RSS

    • ничего нового или гениального.

      почти все компиляторы уже умеют это делать автоматом - и лучше.
      Ответить
          • По указанной ссылке ничего не сказано об особенностях оптимизированной версии strncmp().
            Ответить
            • Цитата из третьего абзаца: "Many of these functions are only optimized in certain cases; if they are not optimized in a particular case, a call to the library function will be emitted."

              то что ты видишь в говнокоде сверху, это то что будет сделано самим компилятором на стадии компиляции(!!) - но не всегда, а только если данная оптимизация вызова strncmp() имеет смысл. и она имеет смысл только если входной параметр длина есть константа и эта константа достаточно мелкая. Если параметр длины есть переменная, inline ГК сверху насрет кучи лишнего кода в объектные файлы снижая эффективность кэша кода.
              Ответить
              • Повторяю ещё раз. По ссылке об этом ничего не сказано. Где в этой фразе:
                "Many of these functions are only optimized in certain cases; if they are not optimized in a particular case, a call to the library function will be emitted." сказано про константы и ее размер?
                Не спорю, что это может быть действительно так, но в указанной статье об этом не сказано.
                Ответить
            • самый простой пример оптимизаций этого типа это "memcpy( &c1, &c2, 1 )" - почти все компиляторы уберут memcpy() и сгенерят просто mov байта.
              Ответить
      • Компиляторы много чего делают в целях оптимизации.
        Это же не значит, что нужно так писать.

        Не хотел бы я разбирать программы, написанные компилятором
        Ответить
  • Типа сначала хватало и 8 символов, а потом добавили default.
    Ответить
    • Интересная мысль, просмотрел весь код и заметил, что length больше 8 нигде не передаётся.
      Ответить
      • проверь что ваш компилер эту оптимизацию автоматом уже не делает. MSVC и новые GCC это умеют.
        Ответить
  • хм, такое даже школоло не напишет на лабу...
    Ответить
  • Оптимизация?
    if (length < 9) {
      while (length--)
        if (s1[length] != s[length]) return false;
      return true;
    }
    return strncmp(s, s1, length) == 0;
    Не лучше?
    Ответить
        • Хорошо хоть за два дня.
          при нуле будет тру вне зависимости от строк
          при отрицательных значениях - смотри исходник strncmp, и то, только
          если у вас получится засунуть в sizte_t (unsigned integral) отрицательное значение. энивей it's fun.
          Ответить
        • Кажется, я не понял.
          А что не так при length == 0 ?
          Для length < 0 не проверялось, ибо unsigned. Кстати, например, -2 вполне сойдёт за 4294967294, при этом strncmp() не зайдёт дальше конца самой короткой строки.
          Ответить
          • >А что не так при length == 0 ?
            s1[-1] != s[-1] или
            s1[4294967295] != s[4294967295] для unsigned
            Ответить
            • while (length--) { }
              это, грубо говоря,
              next:
              if (length == 0) goto quit;
              else {
                length = length - 1;
                // тут сравнение
                goto next;
              }
              quit:
              length = length - 1;
              Где ошибаюсь?
              Ответить
                    • вы вообще про что?

                      int main(void) {
                      const char* alpha = "bla-bla";
                      const char* beta = "bla-bla";
                      //fun starts here
                      cout << alpha[111] << endl;
                      cout << beta[111] << endl;
                      return 0;
                      }

                      $ g++ cCh.cpp
                      $ ./a.out
                      }
                      ?
                      Ответить
                      • а оказывается - что нет.

                        /* $OpenBSD: strncmp.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
                        int
                        strncmp(const char *s1, const char *s2, size_t n)
                        {
                        if (n == 0)
                        return (0);
                        do {
                        if (*s1 != *s2++)
                        return (*(unsigned char *)s1 - *(unsigned char *)--s2);
                        if (*s1++ == 0)
                        break;
                        } while (--n != 0);
                        return (0);
                        }

                        строки перебираются сначала, не с конца или середины. поэтому желанного s1[4294967295] не будет. а жаль.
                        Ответить
    • почему бы не сделать по-ебанутому!?

      const size_t MAX_LEN = 9;
      while (length < MAX_LEN) {
        --length;
        if (s1[length] != s[length]) 
          return false;
      }
      
      return (!length)?true:strncmp(s + MAX_LEN, s1 + MAX_LEN, length) == 0;
      Ответить
      • Что-то у вас не то. Условие выхода из цикла length >= MAX_LEN при этом length уменьшается.
        Так и до переполнения в минус недалеко.
        Хотя скорее будет Access violation.
        Ну и последний ретурн вообще какой-то убогий.
        Ответить
      • inline bool equal(const char* s, const char* s1, size_t length)
        {
        	const size_t easyLen = 8;
        	
        	if( length <= 0 ) return true;
        	
        	if( length <= easyLen )
        	{
        		int index = length;
        		
        		while( index-- )
        		{
        			if( s[index] != s1[index] ) return false;
        		}
        		return true;
        	}
        	
        	return strncmp(s,s1,length) == 0;
        }
        Ответить
        • заменить if( length <= 0 ) return true;
          на if( length == 0 ) return true; если size_t есть unsigned.
          Ну, или внести условие в следующий if.
          Если найдете ошибку - напишите.
          Ответить
            • Да-да. Об этом как раз в другой теме с вашим тёзкой обсуждаем :)))
              Ответить
            • нако
              bool equal(const char *ls, const char *rs, size_t length)
              {
              	static const size_t DEFAULT_MAX_LENGTH = 10;
              	const size_t MAX_LENGTH = (length <= DEFAULT_MAX_LENGTH)?0:length - DEFAULT_MAX_LENGTH;
              	
              	for(; length >= MAX_LENGTH; --length)
              		if(ls[length] != rs[length])
              			return false;
              
              	return !strncmp(ls, rs, length);
              }
              Ответить
  • Если это было сделано на основе анализа производительности кода и дало в результате ожидаемый эффект - то это ни разу не говнокод, а весьма элегантное применение конструкции типа классического Duff's Device.
    Ответить

Добавить комментарий

Семь раз отмерь — один отрежь, guest!

    А не использовать ли нам bbcode?


    8