Pergunta

Considere o programa C composto por dois arquivos,

f1.c:

int x;

f2.c:

int x=2;

A minha leitura do parágrafo 6.9.2 do o C99 padrão é que este programa deve ser rejeitada. Na minha interpretação de 6.9.2, x variável é tentativamente definido em f1.c, mas esta definição tentativa torna-se uma definição real no final da unidade de tradução, e (na minha opinião), deve, por conseguinte, se comportam como se f1.c continha o int x=0; definição.

Com todos os compiladores (e, mais importante, os ligantes) eu era capaz de tentar, não é isso que acontece. Todas as plataformas de compilação Eu tentei fazer ligar o acima de dois arquivos, e o valor de x é 2 em ambos os arquivos.

Eu duvido que isso acontece por acidente, ou apenas como um recurso de "fácil" para fornecer para além do que a norma exige. Se você pensar sobre isso, isso significa que existe um apoio especial na vinculador para essas variáveis ??globais que não têm um inicializador, ao contrário daqueles explicitamente inicializado para zero. Alguém me disse que o recurso vinculador pode ser necessário compilar Fortran de qualquer maneira. Isso seria uma explicação razoável.

Todos os pensamentos sobre isso? Outras interpretações da norma? Nomes de plataformas no qual os ficheiros f1.c e f2.c lixo a ser ligados entre si? ??

Nota: isto é importante porque a questão ocorre no contexto de análise estática. Se os dois arquivos podem recusar-se a ser ligado em alguma plataforma, o analisador deve queixar-se, mas se todas as plataformas compilação aceita isso, então não há nenhuma razão para avisar sobre isso.

Foi útil?

Solução

Veja também Quais são variáveis ??extern em C . Isso é mencionado no padrão C no informativo anexo J como uma extensão comum:

J.5.11 múltiplas definições externas

Pode haver mais de uma definição externa para o identificador de um objeto, com ou sem o uso explícito da palavra-chave externo; Se as definições de discordar, ou mais de um é inicializado, o comportamento é indefinido (6.9.2).

Aviso

Como @ litb pontos aqui fora, e como referi na minha resposta à pergunta de referência cruzada, usando múltiplas definições por leads variável global para um comportamento indefinido, que é a forma do padrão de dizer "tudo pode acontecer". Uma das coisas que pode acontecer é que se comporta de programa como você espera; e J.5.11 diz, aproximadamente, "você pode ter sorte com mais frequência do que você merece". Mas um programa que depende de várias definições de uma variável externa - com ou sem a explícita 'externa' palavra-chave - não é um programa estritamente em conformidade e não garantido para o trabalho em todos os lugares. Equivalentemente:. Ele contém um bug que pode ou não pode mostrar-se

Outras dicas

Existe algo chamado uma "extensão comum" para o padrão, onde as variáveis ??que definem várias vezes é permitida, desde que a variável é inicializada apenas uma vez. Consulte http://c-faq.com/decl/decldef.html

A página do link diz que este é pertinente para plataformas Unix - Eu acho que é o mesmo para c99 como c89 - embora talvez ele tenha sido adotado por mais compiladores para formar uma espécie de padrão de fato. Interessante.

Esta é esclarecer a minha resposta a um comentário por olovb:

saída de nm para um arquivo de objeto compilados a partir de "int x;". Nesta plataforma, os símbolos são precedidos com um '_', ou seja, a variável x aparece como _x.

00000000 T _main
         U _unknown
00000004 C _x
         U dyld_stub_binding_helper

de saída nm para um ficheiro de objecto compilado a partir de "int x = 1;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

de saída nm para um ficheiro de objecto compilado a partir de "int x = 0;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

saída de nm para um arquivo de objeto compilados a partir de "extern int x;"

00000000 T _main
         U _unknown
         U dyld_stub_binding_helper

EDIT: saída de nm para um arquivo de objeto compilados a partir de "externo int x;" onde x é realmente usado em uma das funções

00000000 T _main
         U _unknown
         U _x
         U dyld_stub_binding_helper
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top