как я нахожу тонкую ошибку - PullRequest
0 голосов
/ 25 сентября 2019

Я не понимаю, почему переменная имеет значение 0, оно должно быть 23?

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int array[] = {23, 34, 12, 17, 204, 99, 16};
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int main(){
    int d = -1, x = 0;
    if (d <= TOTAL_ELEMENTS - 2)
        x = array[d + 1];
    printf("x= %d \n", x);
    return 0;
}

1 Ответ

2 голосов
/ 25 сентября 2019

Это происходит из-за обычных арифметических преобразований .

Когда операнды оператора включают в себя как целое число со знаком, так и целое число без знака, а тип без знака по меньшей мере такой же большой, кактип со знаком, значение со знаком преобразуется в значение без знака.Когда значение со знаком является отрицательным, оно преобразуется в большое положительное значение.

Правила целочисленных преобразований изложены в разделе 6.3.1.8p1 стандарта C :

Если оба операнда имеют одинаковый тип, дальнейшее преобразование не требуется.

В противном случае, если оба операнда имеют целочисленные типы со знаком или у обоих целочисленные типы без знака, операнд с типом меньшегоранг целочисленного преобразования преобразуется в тип операнда с большим рангом.

В противном случае, если операнд с целым типом без знака имеет ранг, больший или равный рангу типа другого операнда, тогда операндс целым типом со знаком преобразуется в тип операнда с целым типом без знака.

В противном случае, если тип операнда с целочисленным типом со знаком может представлять все значения типа операнда с целым числом без знакатип, то операнд с целым типом без знака преобразуется в тип operand со целым типом со знаком.

В противном случае оба операнда преобразуются в целочисленный тип без знака
, соответствующий типу операнда со целым типом со знаком

В этом выражении:

(d <= TOTAL_ELEMENTS - 2)

Что расширяется до:

(d <= (sizeof(array) / sizeof(array[0])) - 2)

Оператор sizeof оценивает значение типа size_t, которое не подписано.Таким образом, типы операндов выглядят так:

(int <= ((size_t / size_t) - int)

Оба операнда оператора / имеют тип size_t, поэтому результат этой операции имеет тип size_t.Затем правый операнд - преобразуется в тип size_t.Поскольку значение 2 соответствует этому типу, значение не изменяется.

Теперь у нас есть оператор <= с int для одного размера и size_t для другого.Левый операнд преобразуется из int в size_t, однако значение -1 не подходит для этого типа, поэтому оно преобразуется.Преобразованное значение на самом деле является наибольшим возможным значением для size_t, которое, следовательно, больше, чем значение на правой стороне, что делает результат <= ложным.

Чтобы это исправить, вам нужноприведите значение без знака справа к знаку, чтобы предотвратить преобразование левой стороны:

if (d <= (int)(TOTAL_ELEMENTS - 2))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...