История изменений
Исправление r--r--r--, (текущая версия) :
Для for(int i = x; i != y; i++) { … a[i] … } есть гарантия, что массив a читается последовательно (можно предсказуемо подгружать кэш и использовать всякие SIMD).
Для unsigned всё становится заметно сложнее: либо делать проверку и удваивать объём кода, либо не иметь гарантии последовательного чтения.
В смысле? Вот цикл for(unsigned char i = x; i!= y; i++) { …a[i]… }. Он завершается.
Потому что может доказать, что переполнения нет. Доступ к array[i] гарантирует, что i не больше 1024.
Ладно про стандарт, но с компиляторами-то ты свои фантазии как-то пытался соотнести?
-
В реальности для знаковых компилятор тупо выбрасывает проверку недостижимого (с его, компилятора, точки зрения) условия , превращая цикл в вечный не зависимо от
sizeof(array)и "Доступ к array[i] гарантирует, что i не больше 1024."©™. -
Если компилятор НЕ может доказать, что нет переполнения, так как
sizeof(array)не известен, то они генерируют идентичный код для знаковых и беззнаковых счётчиков.
Для for(int i = x; i != y; i++) { … a[i] … } есть гарантия, что массив a читается последовательно (можно предсказуемо подгружать кэш и использовать всякие SIMD).
Но вместо этого, компилятор просто выкинет нахер условие, если может.
Для unsigned всё становится заметно сложнее: либо делать проверку и удваивать объём кода, либо не иметь гарантии последовательного чтения.
Ты хоть один реально существующий компилятор, который вместо неимения гарантий будет городить какие-то проверки сверх описанных в коде, сможешь привести?
Исправление r--r--r--, :
Для for(int i = x; i != y; i++) { … a[i] … } есть гарантия, что массив a читается последовательно (можно предсказуемо подгружать кэш и использовать всякие SIMD).
Для unsigned всё становится заметно сложнее: либо делать проверку и удваивать объём кода, либо не иметь гарантии последовательного чтения.
В смысле? Вот цикл for(unsigned char i = x; i!= y; i++) { …a[i]… }. Он завершается.
Потому что может доказать, что переполнения нет. Доступ к array[i] гарантирует, что i не больше 1024.
Ладно про стандарт, но с компиляторами-то ты свои фантазии как-то пытался соотнести?
-
В реальности для знаковых компилятор тупо выбрасывает проверку недостижимого условия, превращая цикл в вечный не зависимо от
sizeof(array)и "Доступ к array[i] гарантирует, что i не больше 1024."©™. -
Если компилятор НЕ может доказать, что нет переполнения, так как
sizeof(array)не известен, то они генерируют идентичный код для знаковых и беззнаковых счётчиков.
Для for(int i = x; i != y; i++) { … a[i] … } есть гарантия, что массив a читается последовательно (можно предсказуемо подгружать кэш и использовать всякие SIMD).
Но вместо этого, компилятор просто выкинет нахер условие, если может.
Для unsigned всё становится заметно сложнее: либо делать проверку и удваивать объём кода, либо не иметь гарантии последовательного чтения.
Ты хоть один реально существующий компилятор, который вместо неимения гарантий будет городить какие-то проверки сверх описанных в коде, сможешь привести?
Исходная версия r--r--r--, :
Для for(int i = x; i != y; i++) { … a[i] … } есть гарантия, что массив a читается последовательно (можно предсказуемо подгружать кэш и использовать всякие SIMD).
Для unsigned всё становится заметно сложнее: либо делать проверку и удваивать объём кода, либо не иметь гарантии последовательного чтения.
В смысле? Вот цикл for(unsigned char i = x; i!= y; i++) { …a[i]… }. Он завершается.
Потому что может доказать, что переполнения нет. Доступ к array[i] гарантирует, что i не больше 1024.
Ладно про стандарт, но с компиляторами-то ты свои фантазии как-то пытался соотнести?
-
В реальности для знаковых компилятор тупо выбрасывает проверку недостижимого условия, превращая цикл в вечный не зависимо от
sizeof(array)и "Доступ к array[i] гарантирует, что i не больше 1024."©™. -
Если компилятор НЕ может доказать, что нет переполнения, так как
sizeof(array)не известен, то они генерируют идентичный код для знаковых и беззнаковых счётчиков.