Могут ли два объекта в глобальной области иметь одинаковое имя? - PullRequest
0 голосов
/ 17 июня 2011

Рассмотрим следующий фрагмент:

struct foo_struct {
   int a;
   int b;
};

struct foo_struct *foo;
struct foo_struct foo_global;

int foo(int x)
{
  ....
  return 0;
}

int main(void)
{
   foo = &foo_global;
  ...
}

Итак, у меня есть два идентификатора, но для разных объектов (правильно ли называть функцию объектом?).Это строго незаконно, или стандарт определяет такой случай как «неопределенное поведение».Какая часть стандарта описывает это?

Ответы [ 3 ]

3 голосов
/ 17 июня 2011

Я получаю:

a.c:9: error: ‘foo’ redeclared as different kind of symbol
a.c:6: note: previous declaration of ‘foo’ was here

Я очень сомневаюсь, что это законно.Вы можете устранить неоднозначность foo = &foo_global, потому что вы не можете «перезаписать» функцию, но void *var = foo будет неоднозначным (это foo указатель функции или указатель struct foo_struct?).

Теперь стандарт:

6.2.1 §2 Для каждого отдельного объекта, который обозначает идентификатор, идентификатор является видимым (т.е. может использоваться) только в пределах области текста программы, называемой ее областью действия.Различные объекты, обозначенные одним и тем же идентификатором, имеют разные области действия или находятся в разных пространствах имен.[...]

Таким образом, идентификаторы должны иметь разные области действия или разные пространства имен.

6.2.1 §4 Если описатель или спецификатор типа, который объявляет идентификаторпоявляется вне любого блока или списка параметров, у идентификатора есть область файла, которая заканчивается в конце единицы перевода.[...]

6.2.1. §6 Два идентификатора имеют одинаковую область действия тогда и только тогда, когда их области действия заканчиваются в одной и той же точке.

Они указывают, что оба идентификатора имеют одинаковыеобласть действия (область действия файла), которая заканчивается в конце блока перевода.

6.2.3 §1 [...] [T] здесь являются отдельными пространствами имен для различных категорий идентификаторов, так какследует:

  • label names [...]

  • tags структур, объединений и перечислений [...]

  • members структур или объединений [...]

  • всех других идентификаторов, называемых обычными идентификаторами (объявленными в обычных деклараторах иликак константы перечисления).

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

Следовательно, они имеют одинаковую область видимости и одно и то же имяпространство, которое не удовлетворяет 6.2.1 § 2.

1 голос
/ 17 июня 2011

Вы пытались его скомпилировать? С gcc это не разрешено и выдает конечно ошибку

error: ‘foo’ redeclared as different kind of symbol
error: previous declaration of ‘foo’ was here
0 голосов
/ 17 июня 2011

У вас может быть переменная, тип которой является указателем на функцию, поэтому, когда вы ее вызываете, вызываете ли вы функцию или функцию, указанную переменной с тем же именем?Это неоднозначно.Я думаю, что это незаконно.Нет проблем, например, в Java, потому что там не может быть переменной, указывающей на функцию, поэтому использование скобок устраняет неоднозначность, если вы ссылаетесь на функцию или переменную.

typedef void (*functiontype)();
functiontype func;

void f1 () {
    ...
}
void func () {
    ...
}
void main() {
    func = &f1;
    func();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...