C: что такое пространство имен определения типа? - PullRequest
2 голосов
/ 13 мая 2019

В каком пространстве имен находится имя typedef? Рассмотрим этот код:

#include <stdio.h>

typedef struct x {   // 'x' in tag name space
   int x;            // 'x' in member name space
   int y;
} x;                 // ??

int main() {
   x foo = { 1, 2 };
   int x = 3;        // 'x' in ordinary identifier name space

   printf("%d %d %d\n", foo.x, foo.y, x);
}

Это печатает '1 2 3' с помощью gcc 4.4.7 (и g ++ 4.4.7), поэтому имена типов отделены от имен тегов, членов и обычных идентификаторов.

Этот код также компилируется и запускается на gcc / g ++ 4.4.7, производя '1, 2':

#include <stdio.h>

typedef struct x {   // 'x' in tag namespace
   int x;            // 'x' in member namespace
   int y;
} x;

int main() {
   x x = { 1, 2 };

   printf("%d %d\n", x.x, x.y);
}

Как в этом случае устраняются неоднозначности идентификаторов x?

EDIT Уточнение, я надеюсь. Рассмотрим эти две строки сверху:

   x foo = { 1, 2 };
   int x = 3;        // 'x' in ordinary identifier name space

Когда выполняется вторая строка, идентификатор x находится в области видимости и должен логически находиться в пространстве имен «обычный идентификатор». Похоже, на данный момент нет новой области видимости, потому что между строками 1 и 2 нет открывающей скобки, поэтому вторая x не может скрыть первую x, а второй x ошибочный. В чем недостаток этого аргумента, и как это относится к делу x x? Мое предположение заключалось в том, что недостатком было то, что имена типов каким-то образом имели другое неочевидное пространство имен, отсюда и название этого вопроса.

1 Ответ

4 голосов
/ 13 мая 2019

Работает не из-за пространств имен (имя нового типа и идентификатор переменной находятся в одном и том же обычном пространстве имен), а из-за области видимости.

6.2.1 Области применения идентификаторов

2 Для каждого отдельного объекта, который обозначает идентификатор, идентификатор является видимым (то есть может использоваться) только в пределах области Текст программы называется ее областью применения. Различные лица, обозначенные один и тот же идентификатор имеет разные области действия или имеет другое имя пространства. Существует четыре вида областей действия: функция, файл, блок и прототип функции. (Прототип функции - это объявление функция, которая объявляет типы своих параметров.)

4 Каждый другой идентификатор имеет область действия, определяемую размещением его объявление (в деклараторе или спецификаторе типа). Если декларатор или спецификатор типа, который объявляет идентификатор, появляется вне любого блок или список параметров, идентификатор имеет область видимости файла, которая заканчивается в конце блока перевода. Если декларатор или спецификатор типа, который объявляет идентификатор, появляется внутри блока или в списке объявлений параметров в определении функции, идентификатор имеет область видимости блока, которая заканчивается в конце связанный блок. Если декларатор или спецификатор типа, который объявляет идентификатор появляется в списке объявлений параметров в прототип функции (не является частью определения функции), идентификатор имеет область действия прототипа функции, которая заканчивается в конце объявление функции. Если идентификатор обозначает два разных сущности в одном и том же пространстве имен, области могут перекрываться. Если так, то область действия одной сущности (внутренняя область) заканчивается строго до область действия другого объекта (внешняя область). Во внутренней сфере, идентификатор обозначает сущность, объявленную во внутренней области видимости; объект, объявленный во внешней области видимости, скрыт (и не виден) внутри внутренняя сфера.

Переменная с именем x является внутренней областью действия. Таким образом, он скрывает сущность с именем x во внешней области видимости. Внутри области действия main после объявления x x это имя переменной.

Интересным является то, что в x x = { 1, 2 }; значение x изменяется в середине объявления. В начале он обозначает имя типа, но как только декларатор вводит идентификатор, x начинает обозначать переменную.


Относительно вашего редактирования «В чем недостаток этого аргумента?» Обратите внимание, что области видимости могут перекрываться (как упоминалось в предыдущем абзаце). Определение псевдонима типа находится на уровне файла. Область видимости main является новой внутренней областью, которая перекрывает внешнюю область. Вот почему его можно использовать, чтобы скрыть прежнее значение x. Если бы вы попытались сделать это в области действия файла:

typedef struct x { /* ... */ } x;
int x = 1; // immediately at file scope

Это было бы плохо сформировано. Потому что теперь действительно объявления появляются в точно такой же области.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...