Ir ao conteúdo

C Especificadores extern e static


Ir à solução Resolvido por arfneto,

Posts recomendados

Postado

Boa noite, colegas.

Estava dando uma olhada no livro C: Como Programar 6ª edição, e me deparei com o seguinte:

Citação

Variáveis globais e nomes de funções são da classe de armazenamento extern, como padrão.

E mais adiante, o autor diz:

Citação

variáveis declaradas fora das definições de função são da classe de memória static, por default, e são conhecidas como variáveis globais.

E bem, vejo que ele disse o mesmo sobre os dois especificadores de classe de armazenamento... 🤔

O único uso que conheço do extern é para referenciar variáveis globais e funções em outro arquivo, daí declaramos a variável ou função precedida por extern, mas não acho que variáveis globais e funções sejam precedidas por extern por padrão... Não seriam precedidas por static? Qual seria o certo?

  • Obrigado 1
Postado
13 horas atrás, Lucca Rodrigues disse:

não acho que variáveis globais e funções sejam precedidas por extern por padrão... Não seriam precedidas por static? Qual seria o certo?

 

O livro.

 

Se coloque no lugar do linker...

 

pense nesses arquivos:

 

umx.c
 

// umx.c
    int x = 42;

outrox.c

 

// outrox.c
    int x = 4242;

 

E compile os dois:
 

    gcc -c umx.c outrox.c

 

Sem problemas. Nos dois casos x é extern porque afinal não está dentro de nada para ser interno. E deve ser static porque tem que ser criado e não está dentro de nenhum contexto.

 

Agora pense (no lugar do linker) nesse programa, maisum.c 
 

// maisum.c
#include <stdio.h>

int (existe)(int);

void quanto(int x)
{
    // chama alguma f() que veio
    printf( "quanto(%d): x = %d\n", x,  existe(x) );
}

 

Esse programa  cria a função quanto() que mostra o valor de x, só que x é um parâmetro, nem static nem extern.

Só que declara existe() que obviamente é extern porque aqui não está.

 

Agora em main.c a conta precisa fechar:
 

#include <stdio.h>

extern int x;
void quanto(int);

int existe(int x){ printf("existe(%d)\n", x); return x; };

int main(void)
{
    printf("main() x= %d\n", x );
    quanto(x);
    return 0;   
}

 

a função existe() que faltava é criada aqui. E tem seu próprio x. Mas main() vai usar o  x global e chamar quanto() com o valor desse x.

 

Claro, x não precisa ser extern mas se quiser x por exemplo como uma semente para rand() que vem de algum lugar central, vai deixar como extern e contar que isso se resolva na hora do build. 

 

Claro, quanto() poderia ser declarada extern mas é implícito porque afinal aqui ela não está.

 

E claro que não pode incluir umx.c ou outrox.c no build (link) porque vai duplicar ou triplicar x.

 

E se rodar
 

gcc -c -Wall umx.c
gcc -c -Wall outrox.c
gcc -c -Wall maisum.c

echo "// um usa umx.c "
./um
gcc -o um main.c maisum.o umx.o -l c

echo "// dois usa outrox.c "
./dois
gcc -o outro main.c maisum.o outrox.o -l c

 

vai ver 
 

// um usa umx.c 
main() x= 42
existe(42)
quanto(42): x = 42
// dois usa outrox.c 
main() x= 4242
existe(4242)
quanto(4242): x = 4242

 

 

E faz sentido.

 

Tente

    gcc -o juntos main.c maisum.o umx.o outrox.o -l c

 

E vai ver

 

/usr/bin/ld: outrox.o:(.data+0x0): 
    multiple definition of `x'; umx.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status

 

 

 

  • Obrigado 1
Postado

@arfneto

2 horas atrás, arfneto disse:

Esse programa  cria a função quanto() que mostra o valor de x, só que x é um parâmetro, nem static nem extern.

De certo modo, `x` seria auto :D

É uma variável local de quanto().

 

2 horas atrás, arfneto disse:

Nos dois casos x é extern porque afinal não está dentro de nada para ser interno. E deve ser static porque tem que ser criado e não está dentro de nenhum contexto.

Não entendi muito bem essa segunda afirmação... extern e static não são mutualmente exclusivos?

Havia dito que:

16 horas atrás, Lucca Rodrigues disse:

não acho que variáveis globais e funções sejam precedidas por extern por padrão... Não seriam precedidas por static?

porque usar extern seria dizer que a variável estaria definida em outro lugar, e que essa declaração nada mais é que uma referenciação à definição, mas acho que isso seria só quando usamos extern explicitamente, a menos que estejamos tratando de protótipos de função, como você disse:

2 horas atrás, arfneto disse:

Claro, quanto() poderia ser declarada extern mas é implícito porque afinal aqui ela não está.

extern não faria diferença nesse caso.

Mas novamente, extern e static não são mutualmente exclusivos? Uma variável com static só pode ser acessada pelas funções do mesmo arquivo em que foi definida, e o mesmo vale para as funções definidas com static, certo?

Me surgiram outras dúvidas (duvidosas)...

E se definirmos uma função com extern? Não que faça sentido 🤪, até porque acho que a definição não deixaria de ser uma definição só porque está precedida por extern.

E se declararmos um protótipo de função precedido por static num arquivo diferente de onde está a definição? Faria alguma diferença?

  • Solução
Postado
1 hora atrás, Lucca Rodrigues disse:

De certo modo, `x` seria auto :D

É uma variável local de quanto().

 

 

auto significa praticamente nada em C. Ou nada mesmo. Sugiro esquecer. 

 

Em C++ é outra coisa, especialmente com templates e coisas tipo &&
 

3 horas atrás, arfneto disse:

Nos dois casos x é extern porque afinal não está dentro de nada para ser interno. E deve ser static porque tem que ser criado e não está dentro de nenhum contexto

 

1 hora atrás, Lucca Rodrigues disse:

Não entendi muito bem essa segunda afirmação... extern e static não são mutualmente exclusivos?

 

 

Não. E não poderiam ser. Veja o exemplo.

 

Pense como o linker. Ele precisa fazer algo com o programa. Contexto aqui é scope. Em

 

// programa 

int x;
int y = x;
// fim

 

que vai fazer com x e y? claro que tem que ser alocados. E o scope tem que ser global. Se não fosse estaria onde? A menos que isso fosse incluído em um programa... ;) E assim são static, porque vão ter escopo global.

 

1 hora atrás, Lucca Rodrigues disse:

extern não faria diferença nesse caso

 

todo protótipo declara a função como extern. Se ela aparecer depois no mesmo arquivo aí passa a ser local... Mas ao ler o protótipo o compilador não sabe. É pra isso que existe o protótipo afinal.

 

1 hora atrás, Lucca Rodrigues disse:

Uma variável com static só pode ser acessada pelas funções do mesmo arquivo em que foi definida, e o mesmo vale para as funções definidas com static, certo?

 

Isso não é o mais importante: o importante é que variáveis estáticas são alocadas uma única vez (linker) e não a cada chamada da função. É o mesmo caso com main() que é uma função, só que em geral main() não é chamada de novo...

Isso implica em que o endereço de uma variável estática dentro da função é constante, ao contrário das outras variáveis, que são recriadas a cada chamada.

 

funções static acabam assim existindo no contexto do arquivo  porque o linker coloca o código da função em um segmento separado para esse particular bloco de código, então endereço será desconhecido fora dele.

 

1 hora atrás, Lucca Rodrigues disse:

E se definirmos uma função com extern? Não que faça sentido

 

4 horas atrás, arfneto disse:

Claro, quanto() poderia ser declarada extern mas é implícito porque afinal aqui ela não está.

 

pois é. auto para as variáveis não quer dizer nada, extern para as funções não quer dizer nada. A menos que tenha um código enorme com múltiplos #include por exemplo e queira ter certeza de que ninguém dentro dele define uma certa função cujo protótipo está no header

 

1 hora atrás, Lucca Rodrigues disse:

E se declararmos um protótipo de função precedido por static num arquivo diferente de onde está a definição? Faria alguma diferença?

 

 

Deve gerar um warning ao menos. Mas desde que o linker encontre uma no caminho vai gerar o código.

 

 

 

 

  • Obrigado 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!