Теперь рассмотрим следующий код:
blockquote>void print_double(const double d){ printf("d = %lf\n", d); } int main(int args, const char *argv[]){ double d = 10.2; print_double(d); }
Ваш код не имеет псевдонимов.
d
в main иd
вprint_double
являются различными объектами, поскольку аргументы всегда передаются по значению. Но если бы мы «исправили» пример:void print_double(const double *pd){ printf("d = %lf\n", *pd); } int main(int args, const char *argv[]){ double d = 10.2; print_double(&d); }
Это все еще хорошо определено.
*pd
является lvalue типаconst double
.const double
является квалифицированной версиейdouble
. Все типы совместимы между собой (тривиально). Таким образом, вторая пуля имеет место, и этот псевдоним действителен.
Если два указателя (lvalue доступы) могут , псевдоним - это другое дело, чем если бы они указывали на совместимых типов . Часть, которую вы цитируете, посвящена псевдониму указателя (так называемое «правило строгого псевдонима»), который по какой-то причине записывается как:
blockquote>
- тип, совместимый с эффективным типом объекта, [1116 ]
- квалифицированная версия типа, совместимого с эффективным типом объекта
Что означает, что объект с квалификацией const может псевдоним не Квалифицированный объект, даже если они не являются совместимыми типами. Пример:
void f (const int* a, int* b);
a
могут указывать на те же данные, что иb
. Компилятор не вправе предполагать, что они указывают на отдельные объекты.Но это даже не относится к вашему случаю, так как вы передаете параметр по значению и создаете локальную копию. Псевдоним будет применяться, если ваш пример был таким:
double a = 10.2; int main(int args, const char *argv[]){ print_double(&a); } void print_double(const double* b){ printf("d = %lf\n", b); }
Где параметр
b
- это квалифицированная версия типа, совместимого с эффективным типом объекта (double
). Поэтому компилятор может не предполагать, чтоb
не указывает на глобальную переменнуюa
.
Относительно совместимости:
Всякий раз, когда вы копируете объект либо с помощью присваивания
=
, либо путем передачи его в качестве параметра функции, правила простого присвоения включаются. 6.5.16.1 позволяет это:blockquote>
- левый операнд имеет атомарный, квалифицированный или неквалифицированный тип указателя, и (учитывая тип, который левый операнд будет иметь после преобразования в lvalue) оба операнда являются указателями на квалифицированные или неквалифицированные версии совместимых типов, а тип, на который указывает левый, имеет все квалификаторы типа, на который указывает правый;
Значение
int* a; const int* b = a;
в порядке, ноconst int* a; int* b = a;
является нарушением ограничения , Те же самые правила применяются во время передачи параметров, см. 6.9.1 / 10:При входе в функцию оцениваются выражения размера каждого изменяемого параметра, а значение каждого выражения аргумента преобразуется. к типу соответствующего параметра как по присваиванию.
blockquote>В вашем случае происходит то, что значение
d
в вызывающей стороне копируется в новую переменную типаconst double
. Это разрешено согласно правилу простого присваивания, и вы создаете новую переменную - все хорошо.