каково поведение, когда char сравнивается с unsigned short на языке c? - PullRequest
0 голосов
/ 11 июля 2020

Когда я запускаю следующую программу:

void func(unsigned short maxNum, unsigned short di)
{
    if (di == 0) {
        return;
    }

    char i;

    for (i = di; i <= maxNum; i += di) {
        printf("%u ", i);
    }

    printf("\n");
}

int main(int argc, char **argv)
{
    func(256, 100);
    return 0;
}

Это бесконечно l oop, но мне интересно, когда char сравнивается с unsigned short, переводится ли char в unsigned short? В этой ситуации char является переполненным и больше, чем maxNum. Я действительно не знаю, как объяснить результаты этой программы.

Ответы [ 3 ]

2 голосов
/ 11 июля 2020

Поведение, определяемое реализацией , Неопределенное поведение и CHAR_MAX < 256

Давайте разберемся:

... unsigned short maxNum
... unsigned short di
char i;
for (i = di; i <= maxNum; i += di) {
    printf("%u ", i);
}

char может быть со знаком char или без знака char. Предположим, что это подписанный .

unsigned short может иметь тот же диапазон, что и unsigned, когда оба 16-битные. Однако чаще встречается unsigned short как 16-битный и int, unsigned * как 32-битный.

Существуют и другие возможности, но давайте go перейдем к двум вышеупомянутым предположениям.

i = di может быть интересно, если назначенное значение выходит за пределы диапазона char, но 100 всегда находится в диапазоне char, поэтому i равно 100.

Каждый аргумент в i <= maxNum проходит через обычные целочисленные акции , поэтому подписанный char i сначала становится int 100, а 16-битный maxNum становится int 256. Поскольку 100 < 256 истинно, вводится тело l oop. Обратите внимание, что i никогда не ожидал бы иметь значение, равное 256, поскольку CHAR_MAX меньше 256 - даже в следующих циклах - это объясняет видимое навсегда l oop. Но подождите, есть еще

С printf("%u ", i);, printf() ожидает совпадающий аргумент unsigned. Но i как тип с меньшим диапазоном, чем int, повышается до int с тем же значением как часть аргумента .... Обычно печатаются несовпадающие спецификаторы и тип неопределенное поведение за исключением: когда значение может быть представлено как знаковый, так и беззнаковый тип. Поскольку 100 - это первый раз, все в порядке.

В конце l oop i += di похоже на i = i + di;. Аргументы сложения с go по обычные целочисленные акции и становятся int 100 добавляются к int 100. Эта сумма составляет 200. Пока ничего странного. Тем не менее, присвоение 200 подписанному char закрывает 200, поскольку оно выходит за пределы допустимого диапазона. Это поведение, определяемое реализацией . Присвоенное значение могло быть 0, 1 или 2 .... Обычно значение оборачивается ("модифицируется") путем добавления / вычитания 256 до тех пор, пока не попадет в диапазон. 100 + 100-256 -> -56.

Но вторая printf("%u ", i); пытается напечатать -56 и , что - это неопределенное поведение .

Совет: включите все предупреждения, хорошие компиляторы укажут на многие из этих проблем и сэкономят ваше время.

0 голосов
/ 11 июля 2020

Я получил ответ от http://www.idryman.org/blog/2012/11/21/integer-promotion/, и char, и unsigned short переведены в int, что может объяснить процесс и результат этих программ.

0 голосов
/ 11 июля 2020

Вы устанавливаете maxNum на 256. Наибольшее число, которое вы можете сохранить на 8 битах, - 255 (11111111 в двоичном формате). unsigned char имеет 8 бит. «Нормальный» char использует один из битов как знаковый бит, поэтому вы можете эффективно использовать только 7 его битов для хранения числа (1111111_2 = 127).

Следовательно, i переменная никогда не может быть больше 127, поэтому i <= maxNum всегда будет истинным, потому что даже 127 меньше 256.

Пока выполняется условие, l oop будет выполняться.

...