Понимание пространств имен C

Цитата из здесь,

В C существуют два разных пространства имен типов: пространство имен имен struct/union/enum и пространство имен typedef.

name.c

$ cat name.c
#include<stdio.h>

typedef long long long2;

int long2 () {
    return 4;
}

int main() {

    printf("hello, world!");
    return 0;
}
$ gcc name.c -o name
name.c:4: error: 'long2' redeclared as different kind of symbol
name.c:3: error: previous declaration of 'long2' was here
$

name2.c

$ cat name2.c
#include<stdio.h>

int four() {
    return 4;
}

struct dummy {
    int member;
};

int main() {

    struct dummy four;
}

$ gcc name2.c -o name2
$ 

Я пытаюсь понять конфликты пространства имен C.

  • В первом случае, почему существует конфликт? Функции также относятся к пространству имен typedef?

  • Во втором случае, почему нет конфликта вообще? Функция и переменная называются четырьмя. Почему компилятор разрешает это? Как разрешается &four?

Ответы

Ответ 1

C имеет четыре разных пространства имен для идентификаторов:

  • Имена ярлыков (тип goto).
  • Теги (названия структур, союзов и перечислений).
  • Члены структур и союзов (у них есть отдельное пространство имен для каждой структуры/объединения).
  • Все остальные идентификаторы (имена функций, имена объектов, имена типов (def), константы перечисления и т.д.).

См. также C99 6.2.3.

Итак, на ваш два вопроса можно ответить как:

  • Да, имена функций и имена typedef имеют одно и то же пространство имен.
  • Не конфликтует, потому что компилятор будет использовать правила области (для имен функций или объектов). Идентификатор в основном называется теневым глобальным именем функции, что ваш компилятор предупредит вас, если вы установите уровни предупреждений достаточно высокими.

Ответ 2

Но решающим моментом в ваших примерах является не пространство имен, а область имен.

В name.c оба long2 являются "обычными идентификаторами" (совместно используют одно и то же пространство имен), и оба они определены в одной и той же области, поэтому существует конфликт. (C99, раздел 6.7/3)

Если name2.c, локальная переменная four находится в области, более глубокой, чем функция four, поэтому переменная скрывает функцию four (C99 & sect; 6.2.1/4).

Ответ 3

В вашем втором примере не отображается "no conflict". Есть конфликт! Попробуйте следующее:

#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
    struct dummy four;
    four.member = four();
}

И теперь это

#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
    int (*fx)(void) = four; /* "save" function */
    struct dummy four;     /* hide it         */
    four.member = fx();    /* use "hidden" fx */
}

В вашем втором примере переменная four скрывает функцию four().