Странное преобразование LLVM без подписи в подпись в цикле For

Я не уверен, что это происходит только в Apple LLVM Compiler 4.0 (XCode 4.4.1), но я заметил следующее:

NSUInteger currentIndex = 0;
NSUInteger sideSize = 2;

// Method A
for (NSInteger i = currentIndex-sideSize; i < currentIndex+sideSize; i++)
{
    printf("In the loop\n"); // WON'T be executed
}

// Method B
for (NSInteger i = (NSInteger)(currentIndex-sideSize); i < currentIndex+sideSize; i++)
{
    printf("In the loop\n"); // WON'T be executed
}

// Method C
for (NSInteger i = (NSInteger)(currentIndex-sideSize); i < (NSInteger)(currentIndex+sideSize); i++)
{
    printf("In the loop\n"); // WILL be executed
}

// Method D
NSInteger initialIndex = currentIndex-sideSize;
NSInteger finalIndex = currentIndex+sideSize;
for (NSInteger i = initialIndex; i < finalIndex; i++)
{
    printf("In the loop\n"); // WILL be executed
}

Метод B и метод C практически одинаковы, за исключением того, что мы явно не приводим результат оператора сложения к значению со знаком.

Может кто-нибудь объяснить, пожалуйста, что происходит?

1 ответ

Решение

Дело в том, что если в выражении есть операнды со знаком и без знака, в соответствии со стандартом C, операнд со знаком будет преобразован в целое число без знака. Что произойдет тогда, если вы вычтете 2 из 0, что приведет к -2, но, поскольку оно обрабатывается как целое число без знака (при сравнении значений), оно переполняется и в конечном итоге становится большим числом. Вот почему цикл в методе B не выполняется, а цикл в методе C выполняется (когда вы явным образом приводите результат и / или операнды к знаку, переполнение не происходит, и цикл корректно переходит от -2 к 2),

Это странная вещь в стандарте C, а не в LLVM. LLVM отлично следует стандарту здесь.

Другие вопросы по тегам