На недавнем экзамене у меня был вопрос в духе
Если x является указателем на число с плавающей точкой, какой тип x [5] или операция недопустима?
Правильный ответ на этот вопрос был «плавать». Я проверил следующий код
float test = 3.3;
float* test2 = &test;
std::cout<< test2[2];
и увидел, что ответ действительно был поплавком. Я не понимаю, почему это происходит, и был бы признателен за объяснение, поскольку я не смог найти его в примечаниях к лекции.
Если x является указателем на число с плавающей точкой, какой тип x [5] или операция недопустима?
Правильный ответ:
Операция недопустима, результирующий тип будет float
в любом случае.
Этот экзаменационный вопрос был очень плохим.
Фактический тип выражения x[5]
не имеет никакого представления о том, является ли фактическая операция «незаконной», что бы это ни значило.
Правильный термин — является ли операция неопределенным поведением или нет.
Однако независимо от того, является ли операция неопределенным поведением, выражение x[5]
имеет четко определенный тип, который float
,
Чтобы быть немного придирчивым: ответ «тип выражения x[5]
is float «. Является ли операция» незаконной «, грубо говоря, невозможно определить, так как свободное описание x
Быть просто «указателем на число с плавающей точкой» можно интерпретировать несколькими различными способами.
Если x является указателем на число с плавающей точкой, какой тип x [5] или операция недопустима?
Если ничего не предусмотрено, операция x[5]
незаконно, тип x[5]
все еще четко определен float
Если x на самом деле является указателем на элемент массива с плавающей точкой, учитывая, что после этого элемента в этом массиве более 5 элементов, x[5]
законно например:
float a[10] = { 0.0 };
float *x = a;
x[5] = 1.0; // legal
x = a + 4; // x point to the 5th element of a
x[5] = 0; // legal
x = a + 5;
x[5] = 0; // illegal
float t = 0;
x = &t; x[5] = 0; // illegal
Во всем приведенном выше примере тип x[5]
четко определено как поплавок. Потому что [expr.sub]
(подчеркнуто мое):
Выражение постфикса, за которым следует выражение в квадратных скобках, является выражением постфикса. Одно из выражений должно быть glvalue типа «массив T» или prvalue типа «указатель на T», а другое должно быть prvalue перечисления с незаданной областью или целочисленного типа. Результат типа «Т». Тип «Т» должен быть полностью определенным типом объекта.66 Выражение E1 [E2] идентично (по определению) * ((E1) + (E2)) [Примечание: см. [Expr.unary] и [expr.add] для деталей * и + и [dcl.array] для деталей массивов. — примечание конца], за исключением того, что в случае операнда массива результатом является lvalue, если этот операнд является lvalue и xvalue в противном случае. Выражение E1 секвенируется перед выражением E2.