[C#] Из жизни багов: байты в циклах

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Algol, 17 Dec 2009.

  1. Irdis

    Irdis Elder - Старейшина

    Joined:
    6 Feb 2006
    Messages:
    248
    Likes Received:
    52
    Reputations:
    3
    Code:
    	for (unsigned char b = 0; (std::cout<<(int)b++<<"\n")&&(b!=0); );
    тоже самое на плюсах
     
  2. Meecript_

    Meecript_ Banned

    Joined:
    29 Oct 2008
    Messages:
    194
    Likes Received:
    62
    Reputations:
    32
    Code:
    for (byte b = 0; (std::cout << b++ << std::endl) && b; );
    P.S.: не помню, как в VS, но в билдере по умолчанию typedef unsigned char byte; есть
     
    #22 Meecript_, 19 Dec 2009
    Last edited: 19 Dec 2009
  3. Markus_13

    Markus_13 Member

    Joined:
    19 Feb 2009
    Messages:
    74
    Likes Received:
    19
    Reputations:
    0
    не, конечно не спорю что JS разделяет переменные по типам, но насколько я помню в самом коде переменные не объявляются - т.к. JS работает с переменными взависимости от обращения, если я напишу:
    то сначала перем-ая s будет обрабатываться как число, затем как строка, а затем и вовсе как объект... :rolleyes:
     
  4. Meecript_

    Meecript_ Banned

    Joined:
    29 Oct 2008
    Messages:
    194
    Likes Received:
    62
    Reputations:
    32
    Algol, миниквест пора заканчивать. Говори правильный ответ. Мне кажется постпроверка с префиксным инкрементом в этом случае оптимальный вариант. По крайней мере по количеству используемой памяти )
     
  5. Markus_13

    Markus_13 Member

    Joined:
    19 Feb 2009
    Messages:
    74
    Likes Received:
    19
    Reputations:
    0
    SitraIT, ыыы, типа вот этого чтоли:
    Code:
    function MyClass(){
    this.name="Some";
    }
    var s=new MyClass();
    хотя я с JS работаю весьма недолго - я знаю это, но я и не писал что там нельзя этого делать ;)
    З.Ы. вообще имхо это не классы и объекты, а костыли)))
     
  6. scrat

    scrat кодер

    Joined:
    8 Apr 2007
    Messages:
    625
    Likes Received:
    541
    Reputations:
    3
    по-моему ответ где-то тут
    Code:
    .method private hidebysig static void  Main() cil managed
    {
      .entrypoint
      // Code size       47 (0x2f)
      .maxstack  2
      .locals init (uint8 V_0,
               bool V_1)
      IL_0000:  nop
      IL_0001:  ldc.i4.0
      IL_0002:  stloc.0
      IL_0003:  br.s       IL_001b
      IL_0005:  ldstr      "{0}"
      IL_000a:  ldloc.0
      IL_000b:  box        [mscorlib]System.Byte
      IL_0010:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                    object)
      IL_0015:  nop
      IL_0016:  ldloc.0
      IL_0017:  ldc.i4.1
      IL_0018:  add
      IL_0019:  conv.u1
      IL_001a:  stloc.0
      IL_001b:  ldloca.s   V_0
      IL_001d:  ldc.i4     0xff
      IL_0022:  call       instance int32 [mscorlib]System.Byte::CompareTo(uint8)
      IL_0027:  ldc.i4.0
      IL_0028:  clt
      IL_002a:  stloc.1
      IL_002b:  ldloc.1
      IL_002c:  brtrue.s   IL_0005
      IL_002e:  ret
    } // end of method c::Main
    
     
  7. Algol

    Algol New Member

    Joined:
    29 May 2002
    Messages:
    1,759
    Likes Received:
    4
    Reputations:
    0
    Эээ... А разве здесь может быть правильный ответ :rolleyes:
    Правильный - любой который работает :)
    Лично я бы писал так как предлагал slesh:
    Code:
    for(byte b=0;b<=255;b++)
    {
      Console.WriteLine(b);
      if(b==255) break;
    }
    Некрасиво конечно, но по другому не получится.

    Еще мне понравился вариант desTiny, что на C# выглядело бы типа такого
    Code:
    byte b = 0;
    do
          Console.WriteLine(b);
          b++;
    while(b!=0);
    
    Он конечно содержит минимум операторов, но у него есть недостаток - он в общем случае не работает, если границы перебора заранее не известны.

    Да и кстати, вообще-то я спрашивал почему же исходный код не работает, а все почему то начали приводить примеры работающих кодов :D

    Раз никто не ответил, отвечу сам:
    На самом деле, в си-подобных языках нет оператора for в чистом виде. Фактически for это цикл while, для которого указано условие продолжения (b<=255) и некторый оператор, изменяющий b (b++).
    Причем условние продолжения цикла проверяется на каждой итерации.
    Когда значение b достигает 255, цикл отрабатывает, и далее выполняется операция b++, результатом которой является снова 0! Далее проверяется условие b<=255 - оно очевидно выполняется, и цикл идет дальше, таким образом зацикливаясь в бесконечность.
    Для си в принципе это поведение нормальное, однако для C# лично мне это кажется не очень логичным поведением. Логичнее было бы на 255++ генерировать исключение (что то типа OverflowException) - ведь фктически происходит переполение. Но нет, он тихо сбрасывается в ноль и идет себе дальше :(
    Точно такая же ситуация возникает и для всех остальных целочисленных типов. Например цикл
    for(int i=0;i<=int.MaxInt;i++) - тоже зацикливается.
    Получается что стандартный код типа
    for(int i=1;i<=arr.Count;i++)
    является небезопасным, так как если arr.Count==int.MaxInt, то цикл будет бесконечным :[
     
    #27 Algol, 20 Dec 2009
    Last edited: 20 Dec 2009
  8. Irdis

    Irdis Elder - Старейшина

    Joined:
    6 Feb 2006
    Messages:
    248
    Likes Received:
    52
    Reputations:
    3
    спасибо кэп...
     
  9. Root-access

    Root-access Elder - Старейшина

    Joined:
    18 Jun 2008
    Messages:
    193
    Likes Received:
    195
    Reputations:
    91
    Мне это напомнило такой код на с:
    Code:
    int a[10], i;
    for(i=0;i<=10;i++) a[i]=0;
    
    На старых компиляторах он уходил в бесконечный цикл.
    Вот и задачка. А ну-ка скажите, почему это происходит? ;)
    Кстати, если чуть подправить код, программа и в новых компиляторах будет получаться вечная.
     
    2 people like this.
  10. scrat

    scrat кодер

    Joined:
    8 Apr 2007
    Messages:
    625
    Likes Received:
    541
    Reputations:
    3
    предлагаю обратиться с этим на формуы msdn или к разработчикам платформы .net
     
  11. jawbreaker

    jawbreaker Elder - Старейшина

    Joined:
    7 Jul 2008
    Messages:
    156
    Likes Received:
    76
    Reputations:
    3
    Дружно учим C#:
    PHP:
    checked
    {
        for (
    byte b 0<= 255b++)
        
    Console.WriteLine(b);
    }
     
    #31 jawbreaker, 30 Dec 2009
    Last edited: 30 Dec 2009
  12. Retimiled

    Retimiled Banned

    Joined:
    23 Dec 2009
    Messages:
    110
    Likes Received:
    17
    Reputations:
    0
    каким образом Algol вывел логическую цепочку от целеноправленного введения for в бесконечны цикл.... до отсутствия реализации for как цельной структуры а не цикла while не понятно (для программиста компилятора это узкоспециализированная задача и реализовывать он ее может в соответствии с быстродействием или оптимизацией памяти, никто же не заставляет его использовать реализацию while)
    [​IMG]
    ... по вашей логике все в этом мире сведется к циклу loop (ассемблера) а все остальное от лукавого?????? :D

    цикл for в примере algol-а не на миг не ушел от описния Керниган Ричи....(не делали же списиально списифического описания for для шарпа) дак что же задавать вопрос о том "..а почему он не разворачивает конфеты?"

    Вопросы переполнения переменных это азы Си 8)))
    Школьники многих школ .... где преподают Си вместо Паскаля ВАМ ПОДТВЕРДЯТ ЭТО :D :p

    для С# не придумывали новый синтаксис ни для 'for' ни для if ни для while или until, используется стандартные функции подходящие под описание языка Си и мне программировать совершенно без разницы на TurboC MSVC Net или шарпе без разницы что касается основных структур языка а если я хочу переполнять .... ПОЧЕМУ РАЗРАБОТЧИК КОМПИЛЯТОРА должен запретить мне в соответствии с синтаксисом переполнять переменную чтоб превратить ее в ноль?

    такой прием я видел дважды один раз в реализаци победителя конференции AES - блочном шифровании 2fish...

    каждый можете сделать аналог for
    и понять разницу
    между
    while(... ) {.....}
    и do {....} while(....);
    только тот кто использует for 8))) и сам знает как им пользоваться В СООТВЕТСВИИ С ОПИСАНИЕМ 8))!
     
    #32 Retimiled, 30 Dec 2009
    Last edited: 30 Dec 2009
  13. Algol

    Algol New Member

    Joined:
    29 May 2002
    Messages:
    1,759
    Likes Received:
    4
    Reputations:
    0
    Память под a[] не выделяется?
     
  14. Algol

    Algol New Member

    Joined:
    29 May 2002
    Messages:
    1,759
    Likes Received:
    4
    Reputations:
    0
    Это конечно здорово, но в подавляющем числе случаев - checked не используется, а описанное поведение является неожиданным для программиста.
     
  15. Root-access

    Root-access Elder - Старейшина

    Joined:
    18 Jun 2008
    Messages:
    193
    Likes Received:
    195
    Reputations:
    91

    Почему же? Выделяется вполне...
     
  16. Algol

    Algol New Member

    Joined:
    29 May 2002
    Messages:
    1,759
    Likes Received:
    4
    Reputations:
    0
    Из всего этого набора слов (отмечаешь наверное уже :D ) я так понял ты критикуешь мою фразу о том что "в си-подобных языках нет оператора for в чистом виде" ?
    Могу объяснить более подробно, что и имел ввиду:
    1) Цикл for в Си действительно органозован через while. И даже не столько в синтаксическом плане, сколько в логическом. На каждой итерации - проверяется некое условие, и выполняется некое действие. По сути - это while, просто синтаксически оформленный иначе. Но, если мы посмотрим на теорию программирования (безотносително к какому-либо языку), то смысл for - совсем другой. Смысл for - повторить свое тело заданное число раз. Причем некоторые языки дают даже более жесткое определение - повторение своего тела определенное и заданное наперед число раз. Именно такое поведение реализуется в Паскале (Школьники многих школ .... где преподают Паскаль вместо Си ВАМ ПОДТВЕРДЯТ ЭТО :D ). И это правильно, ибо это ближе к изначальному определению for. В Си же (как и во многих других вещах) решили не париться и сделали for через while.
    А приведенный выше пример как раз и демонстрирует недостаток такого подхода. В Паскале же этот цикл работает без проблем. Он и не может не работать, ведь смысл конструкции for i:=0 to 255 do; в том, что i последовательно принимает значения от 0 до 255, и никаких i++ тут нет, поэтому и переполнения тут никакого быть не может в принципе. Конечно, где-то там внутри , в откомпилированном exe i++ где-то есть , но отсутсвие побочных эффектов, переполения нам гарантирует компилятор, и мы об этом не должны думать.
    Надеюсь понятно изложил? Да и к тому же фразу о том, что в Си по факту нет for - придумал не я. Слышал давно очень, уже и не вспомню откуда :)

    2) Касаемо C#. Да, сишарп по синтаксису близок к Си, но семантика и идеология языка - гораздо ближе к Паскалю, чем к Си. Именно поэтому я и написал что си-подобное поведение шарпа в данном случае не очень ожидаемо.
     
  17. Algol

    Algol New Member

    Joined:
    29 May 2002
    Messages:
    1,759
    Likes Received:
    4
    Reputations:
    0
    Я просто не пишу на Си, но мне казалось что под массив нужно явно выделить память. Нет ?
     
  18. Ra$cal

    Ra$cal Elder - Старейшина

    Joined:
    16 Aug 2006
    Messages:
    670
    Likes Received:
    185
    Reputations:
    78
    память под а выделяется. тока она на стеке. а цикл идет <= 10, компиль видимо генерит так, что переменная i лежит за массивом(a[10] указывает на i). таким образом i при значении 10 затирается нулем, с помощью выхода за границы массива. видимо как то так

    а вот это бред. тогда уж скорее while - это for, у кторого не задан первый и последний параметр типа

    Code:
    for(; b < 255;){}
     
    #38 Ra$cal, 30 Dec 2009
    Last edited: 30 Dec 2009
    2 people like this.
  19. Algol

    Algol New Member

    Joined:
    29 May 2002
    Messages:
    1,759
    Likes Received:
    4
    Reputations:
    0
    Ясно, ну здесь уже проблема с отсутствием контроля границ массива. В шарпе и паскале тут бы выпал эксепшен.
     
  20. Retimiled

    Retimiled Banned

    Joined:
    23 Dec 2009
    Messages:
    110
    Likes Received:
    17
    Reputations:
    0
    8)) ... ну еще раз повторюсь .... програмисты используют особенности работы for (в Си понимании) .... кароче ВСЕХ С НОВЫМ ГОДОМ !! :p