2015-12-23 2 views
9

Пусть у меня есть a.c и b.c, которые оба определяют типы, называемые struct foo, с различными определениями:Разные единицы перевода позволяют определять структуры с тем же именем?

#include <stdio.h> 

struct foo { 
    int a; 
}; 

int a_func(void) { 
    struct foo f; 
    f.a = 4; 
    printf("%d\n", f.a); 
    return f.a * 3; 
} 

 

#include <stdio.h> 

struct foo { // same name, different members 
    char *p1; 
    char *p2; 
}; 

void b_func(void) { 
    struct foo f; 
    f.p1 = "hello"; 
    f.p2 = "world"; 
    printf("%s %s\n", f.p1, f.p2); 
} 

В C, могут ли эти файлы и быть связаны друг с другом как части стандартов -конформирующая программа?

(В C++, я считаю, что это запрещено One Definition Rule.)

+2

Конечно ... пока в каком-либо контексте видится только одно определение. Но будьте осторожны с extern, что вы не ссылаетесь на объект, созданный с другим определением, чем тот, с которым вы обращаетесь к нему с помощью ... – Dmitri

+0

Как сказал dimitri, techincally да, но я бы сказал, что это не идеальный стиль кодирования. – Taelsin

+1

Нет ничего плохого в стиле кодирования, и extern не имеет к этому никакого отношения. –

ответ

8

Struct метки представляют собой идентификаторы с никакой связи (C11 6.2.2/6)

правила о нескольких определений идентификаторов, не имеющих связи находятся в 6.7/3:

Если идентификатор не имеет связи, не должно быть не более чем одна декларация идентификатора (в описатель или спецификатор типа) с той же области и в том же пространстве имен, за исключением того, что:

  • имя typedef может быть переопределено для обозначения того же типа, что и в настоящее время, при условии, что тип не является измененным типом;
  • теги могут быть переоформлены, как указано в 6.7.2.3.

В вашей программе, два заявления foo в различных областях, так что условие «с той же области» не выполняется, и, следовательно, это правило не нарушается.

0

В языке программирования Си, это не имеет значения, что вы называете свои типы. Символы печатаются в соответствии со структурой типа, а не по типу имен. Полностью законно использовать одно и то же имя структуры для разных типов структуры в разных файлах. Однако вы не можете использовать разные типы для объявления одной и той же функции.

+1

Это довольно смутно. C имеет номинальные, а не структурные типы. Проблема здесь не имеет ничего общего с этим, а скорее касается сферы. Поскольку символы определены в разных областях, они независимы. –

1

Способ думать об этом в терминах compilation units. Файл .c, а также вложенная иерархия включенных файлов .h, содержат один compilation unit. Препроцессор расширяет все файлы .h и представляет весь компилятор compilation unit.

compilation unit замкнутое пространство имен для макросов, имена типов, статических идентификаторов, перечислений и т.д. Эти имена не могут иметь дубликаты в пределах этого пространства имен, и ни одно из этих имен не видны за пределами этого пространства имен. Импликация заключается в том, что другой compilation unit является отдельным закрытым пространством имен и может использовать для повторного использования тех же идентификаторов, если в пределах нет дубликатов, которые используют пространство имен.

Следовательно, вы можете использовать одно и то же имя для определенных идентификаторов, если они находятся в отдельных пространствах имен compilation unit.

Обратите внимание, что внешние видимые идентификаторы, такие как нестатические глобальные переменные, функции и т. Д.должны быть уникальными во всем внешнем пространстве имен, которое охватывает все compilation units, соединенные вместе в один исполняемый файл.

+0

Где вы говорите «пространство имен», стандартным термином C является «область действия». В стандарте C термин «пространство имен» не вещь, а «пространство имен» означает что-то другое. Ваше «внешнее пространство имен» будет описывать коллекцию «идентификаторов с внешней связью» –

+2

«пространство имен», как используется здесь, является общим термином. Существуют системы (языки), где этот термин явно принят, чтобы подразумевать аналогичную семантику. Но «пространство имен» является общим термином в вычислениях. – Ziffusion

Смежные вопросы