Eu já vi a palavra staticusada em diferentes lugares no código C; é como uma função / classe estática em C # (onde a implementação é compartilhada entre objetos)?
Qual é o motivo para remover "em um programa C" do final do título, @Lundin? É um pouco redundante na presença da tag c , mas me permite ver a categorização mais rapidamente, sem inspecionar as tags. Essa redundância é muito confortável quando chego à pergunta de uma direção que também pode conter perguntas sobre outros idiomas, por exemplo, pesquisa estática ou no Google.
Palec
5
@Palec Existe uma política de SO em que os itens presentes na lista de tags são redundantes no título. O site anexará automaticamente C ao site real. Um Google para "C estático" fornece essa resposta como principal hit. A razão pela qual isso foi alterado é porque essa pergunta agora faz parte das perguntas frequentes do idioma SO C e todas as postagens adicionadas são um pouco polidas.
Lundin 23/05
1
@Lundin Eu prefiro manter "C" no título, porque o SO anexa apenas uma tag ao título (a mais comum?). E se algum dia a "sintaxe" chegar a mais perguntas do que C (já que é uma coisa entre idiomas)? Eu prefiro usar o comportamento explícito :-) Edit: ah, mas há uma questão meta dizendo o contrário: meta.stackexchange.com/questions/19190/...
Uma variável estática dentro de uma função mantém seu valor entre invocações.
Uma variável global estática ou uma função é "vista" apenas no arquivo declarado em
(1) é o tópico mais externo se você é um novato, então aqui está um exemplo:
#include<stdio.h>void foo(){int a =10;staticint sa =10;
a +=5;
sa +=5;
printf("a = %d, sa = %d\n", a, sa);}int main(){int i;for(i =0; i <10;++i)
foo();}
Isso imprime:
a =15, sa =15
a =15, sa =20
a =15, sa =25
a =15, sa =30
a =15, sa =35
a =15, sa =40
a =15, sa =45
a =15, sa =50
a =15, sa =55
a =15, sa =60
Isso é útil nos casos em que uma função precisa manter algum estado entre as invocações e você não deseja usar variáveis globais. Cuidado, no entanto, esse recurso deve ser usado com moderação - torna seu código não seguro para threads e mais difícil de entender.
(2) É amplamente utilizado como um recurso de "controle de acesso". Se você tem um arquivo .c implementando alguma funcionalidade, normalmente expõe apenas algumas funções "públicas" para os usuários. O restante de suas funções deve ser feito static, para que o usuário não possa acessá-las. Isso é encapsulamento, uma boa prática.
Na linguagem de programação C, estática é usada com variáveis e funções globais para definir seu escopo para o arquivo que contém. Nas variáveis locais, estático é usado para armazenar a variável na memória alocada estaticamente, em vez da memória alocada automaticamente. Enquanto o idioma não determina a implementação de qualquer tipo de memória, a memória alocada estaticamente é normalmente reservada no segmento de dados do programa em tempo de compilação, enquanto a memória alocada automaticamente é normalmente implementada como uma pilha de chamadas transitórias.
E para responder sua segunda pergunta, não é como em C #.
No C ++, no entanto, statictambém é usado para definir atributos de classe (compartilhados entre todos os objetos da mesma classe) e métodos. Em C não há classes, portanto esse recurso é irrelevante.
Pax, o OP não sabe sobre estática, então você sugere mergulhá-lo na diferença entre unidades e arquivos de compilação? :-)
Eli Bendersky
138
Uma unidade de compilação é um único arquivo que o compilador vê. Seu arquivo .c pode incluir outros arquivos .c, mas após o pré-processador classificar as inclusões, o compilador eventualmente vê apenas uma única "unidade de compilação".
Eli Bendersky
81
@robUK: o compilador nem sabe sobre os arquivos .h - eles são combinados nos arquivos .c no pré-processador. Portanto, sim, você pode dizer que o arquivo .c, com todos os cabeçalhos incluídos, é uma única unidade de compilação.
Eli Bendersky
6
@ TonyD talvez seja confuso, mas é assim que a compilação funciona. Normalmente, pode haver um .cmonte de arquivos de cabeçalho, mas o diabo está sempre no que não é típico.
peterph
7
@TonyD O compilador faz a compilação. O pré-processador faz o pré-processamento. Chamar o conjunto de ferramentas de 'compilador' não muda o que é ou o que faz.
Route de milhas
231
Há mais um uso não abordado aqui, e isso é parte de uma declaração de tipo de matriz como argumento para uma função:
int someFunction(char arg[static10]){...}
Nesse contexto, isso especifica que os argumentos passados para essa função devem ser uma matriz do tipo charcom pelo menos 10 elementos. Para mais informações, veja minha pergunta aqui .
Eu não acho que C tinha argumentos de matriz? Linus Torvalds reclama com raiva sobre as pessoas fazendo isso.
Suprjami 29/09/2015
13
@jamieb: C não têm argumentos da matriz, mas esse meio de sintaxe específicas que a função espera arg[0]até arg[9]a ter valores (o que também implica que a função não aceitar um ponteiro nulo). Os compiladores podem utilizar essas informações de alguma forma para otimização, e os analisadores estáticos podem utilizar essas informações para garantir que a função nunca receba um ponteiro nulo (ou, se puder dizer, uma matriz com menos elementos do que o especificado).
dreamlax
19
@Qix - Este era um novo significado sobrecarregado dado staticem C99. Tem mais de uma década e meia de idade, mas nem todos os escritores de compiladores adotaram todos os recursos do C99 - portanto, o C99 como um todo permanece amplamente desconhecido.
Happy Green Kid Naps
@suprjami Eu não tenho 100% de certeza do que você quer dizer com "argumentos da matriz" , mas se você quer dizer int arr[n];, essa é uma VLA (matriz de comprimento variável) , que foi adicionada na C99. É isso que você quis dizer?
RastaJedi
170
Resposta curta ... depende.
Variáveis locais definidas estáticas não perdem seu valor entre as chamadas de função. Em outras palavras, são variáveis globais, mas com escopo definido para a função local em que estão definidos.
Variáveis globais estáticas não são visíveis fora do arquivo C em que estão definidas.
Funções estáticas não são visíveis fora do arquivo C em que estão definidas.
Então, "função estática" e "função privada" significam a mesma coisa? Da mesma forma, "variáveis globais estáticas" e "variáveis globais privadas" são a mesma coisa?
user1599964
40
Trata-se de C. Não há privado / público em C.
chris
19
@ user1599964 embora não exista privateem C, sua analogia é boa: estática torna as coisas "privadas" para um determinado arquivo. E os arquivos em C frequentemente são mapeados para classes em C ++.
Ciro Santilli adicionou uma nova foto
67
Exemplo de escopo variável de vários arquivos
Aqui ilustro como a estática afeta o escopo das definições de função em vários arquivos.
ac
#include<stdio.h>/*
Undefined behavior: already defined in main.
Binutils 2.24 gives an error and refuses to link.
/programming/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
*//*int i = 0;*//* Works in GCC as an extension: https://stackoverflow.com/a/3692486/895245 *//*int i;*//* OK: extern. Will use the one in main. */externint i;/* OK: only visible to this file. */staticint si =0;void a(){
i++;
si++;
puts("a()");
printf("i = %d\n", i);
printf("si = %d\n", si);
puts("");}
m()
i =1
si =1
m()
i =2
si =2
a()
i =3
si =1
a()
i =4
si =2
Interpretação
existem duas variáveis separadas para si, uma para cada arquivo
existe uma única variável compartilhada para i
Como de costume, quanto menor o escopo, melhor, sempre declare variáveis static se puder.
Na programação C, os arquivos são frequentemente usados para representar "classes" e as staticvariáveis representam membros estáticos privados da classe.
O que os padrões dizem sobre isso
C99 N1256 draft 6.7.1 "Especificadores da classe de armazenamento" diz que staticé um "especificador da classe de armazenamento".
6.2.2 / 3 "Ligações de identificadores" diz staticimplica internal linkage:
Se a declaração de um identificador de escopo de arquivo para um objeto ou uma função contiver o estático do especificador de classe de armazenamento, o identificador terá ligação interna.
e 6.2.2 / 2 diz que internal linkagese comporta como no nosso exemplo:
No conjunto de unidades de tradução e bibliotecas que constituem um programa inteiro, cada declaração de um identificador específico com ligação externa indica o mesmo objeto ou função. Dentro de uma unidade de conversão, cada declaração de um identificador com ligação interna indica o mesmo objeto ou função.
onde "a unidade de tradução é um arquivo de origem após o pré-processamento.
Como o GCC o implementa para o ELF (Linux)?
Com o STB_LOCAL ligação.
Se compilarmos:
int i =0;staticint si =0;
e desmonte a tabela de símbolos com:
readelf -s main.o
a saída contém:
Num:ValueSizeTypeBindVisNdxName5:00000000000000044 OBJECT LOCAL DEFAULT 4 si
10:00000000000000004 OBJECT GLOBAL DEFAULT 4 i
portanto, a ligação é a única diferença significativa entre eles. Valueé apenas o deslocamento para a .bssseção, portanto esperamos que seja diferente.
STB_LOCAL Os símbolos locais não são visíveis fora do arquivo de objeto que contém sua definição. Símbolos locais com o mesmo nome podem existir em vários arquivos sem interferir entre si
o que a torna uma escolha perfeita para representar static.
Variáveis sem estática são STB_GLOBALe a especificação diz:
Quando o editor de links combina vários arquivos de objetos realocáveis, ele não permite várias definições de símbolos STB_GLOBAL com o mesmo nome.
que é coerente com os erros de link em várias definições não estáticas.
Se acionarmos a otimização -O3, o sisímbolo será removido inteiramente da tabela de símbolos: ele não pode ser usado de fora de qualquer maneira. TODO por que manter variáveis estáticas na tabela de símbolos quando não há otimização? Eles podem ser usados para qualquer coisa? Talvez para depuração.
A função retornaria 1, 2, 3 etc. - a variável não está na pilha.
ac:
staticint foo(){}
Isso significa que esta função tem escopo apenas neste arquivo. Portanto, ac e bc podem ter foo()s diferentes , e foo não é exposto a objetos compartilhados. Portanto, se você definiu foo em ac, não poderia acessá-lo de b.cou de outros lugares.
Na maioria das bibliotecas C, todas as funções "privadas" são estáticas e a maioria "pública" não é.
+1 por mencionar x que não está na pilha ou pilha. Está no espaço estático da memória.
Gob00st
1
@ Gob00st espaço de memória estática? você quis dizer "segmento de dados" ...?
Yousha Aleayoub
24
As pessoas continuam dizendo que 'estático' em C tem dois significados. Ofereço uma maneira alternativa de visualizá-lo, que lhe dá um único significado:
A aplicação de 'estático' a um item força esse item a ter duas propriedades: (a) não é visível fora do escopo atual; (b) É persistente.
A razão pela qual parece ter dois significados é que, em C, todo item ao qual 'estático' pode ser aplicado já possui uma dessas duas propriedades , portanto parece que esse uso específico envolve apenas o outro.
Por exemplo, considere variáveis. As variáveis declaradas fora das funções já têm persistência (no segmento de dados), portanto, aplicar 'estático' só pode torná-las visíveis fora do escopo atual (unidade de compilação). Por outro lado, variáveis declaradas dentro de funções já não têm visibilidade fora do escopo atual (função), portanto, aplicar 'estático' só pode torná-las persistentes.
Aplicar 'estático' a funções é como aplicá-lo a variáveis globais - o código é necessariamente persistente (pelo menos no idioma), portanto, apenas a visibilidade pode ser alterada.
NOTA: Esses comentários se aplicam apenas a C. No C ++, aplicar 'estático' aos métodos de classe está realmente dando à palavra-chave um significado diferente. Da mesma forma para a extensão de argumento de matriz C99.
Seu (a) é redundante na melhor das hipóteses. Nenhuma variável é visível fora do seu escopo. Essa é simplesmente a definição de escopo. O que você quer dizer é chamado de ligação no padrão C. staticfornece ligação interna a um identificador.
Jens
16
Da Wikipedia:
Na linguagem de programação C, estática é usada com variáveis e funções globais para definir seu escopo para o arquivo que contém. Nas variáveis locais, estático é usado para armazenar a variável na memória alocada estaticamente, em vez da memória alocada automaticamente. Enquanto o idioma não determina a implementação de qualquer tipo de memória, a memória alocada estaticamente é normalmente reservada no segmento de dados do programa em tempo de compilação, enquanto a memória alocada automaticamente é normalmente implementada como uma pilha de chamadas transitórias.
static significa coisas diferentes em diferentes contextos.
Você pode declarar uma variável estática em uma função C. Essa variável é visível apenas na função, no entanto, ela se comporta como um global, pois é inicializada apenas uma vez e mantém seu valor. Neste exemplo, toda vez que você ligar foo(), imprimirá um número crescente. A variável estática é inicializada apenas uma vez.
void foo (){staticint i =0;
printf("%d", i); i++}
Outro uso de estático é quando você implementa uma função ou variável global em um arquivo .c, mas não deseja que seu símbolo seja visível fora do .objgerado pelo arquivo. por exemplo
Se você declarar uma variável em uma função estática, seu valor não será armazenado na pilha de chamadas de funções e continuará disponível quando você chamar a função novamente.
Se você declarar uma variável global estática, seu escopo será restrito ao arquivo em que você a declarou. Isso é um pouco mais seguro que um global comum, que pode ser lido e modificado durante todo o programa.
Detesto responder a uma pergunta antiga, mas acho que ninguém mencionou como a K&R a explica na seção A4.1 de "A linguagem de programação C".
Em resumo, a palavra estática é usada com dois significados:
Static é uma das duas classes de armazenamento (a outra é automática). Um objeto estático mantém seu valor entre invocações. Os objetos declarados fora de todos os blocos são sempre estáticos e não podem ser automatizados.
Porém, quando a staticpalavra - chave (grande ênfase em ser usada no código como palavra-chave) é usada com uma declaração, ela fornece a ligação interna ao objeto para que ela possa ser usada apenas dentro dessa unidade de tradução. Mas se a palavra-chave for usada em uma função, ela altera a classe de armazenamento do objeto (o objeto só seria visível dentro dessa função). O oposto de static é a externpalavra - chave, que fornece a ligação externa a um objeto.
Peter Van Der Linden dá esses dois significados em "Programação C Especialista":
Dentro de uma função, mantém seu valor entre as chamadas.
Há uma terceira classe de armazenamento, registre-se . Algumas pessoas também defendem uma quarta classe de armazenamento, alocada , para o armazenamento retornado por malloc e amigos.
Jens
@Jens 'register' é apenas uma dica para o compilador; o armazenamento do registro não pode ser imposto de dentro da fonte C. Portanto, eu não consideraria uma classe de armazenamento.
GermanNerd
1
@GermanNerd Acho que o padrão ISO C discorda de sua visão, pois claramente faz registerum especificador de classe de armazenamento (C99 6.7.1 Especificadores de classe de armazenamento). E é mais do que apenas uma dica, por exemplo, você não pode aplicar o endereço do operador &em um objeto com classe de armazenamento, registerindependentemente de o compilador alocar um registro ou não.
Jens
@ Jens Obrigado por me lembrar sobre &. Eu poderia ter feito muito C ++ ..... De qualquer forma, enquanto 'register' é um especificador de classe de armazenamento, na realidade o compilador provavelmente criará o mesmo código de máquina para o especificador 'auto' (inútil) e para o 'register 'especificador. Portanto, a única coisa que resta é a restrição no nível do código-fonte de não ser possível obter um endereço. Aliás, essa pequena discussão me levou a encontrar um bug no Netbeans; desde a minha última atualização, o padrão é a cadeia de ferramentas g ++ em novos projetos C!
GermanNerd
6
Em C, estática tem dois significados, dependendo do escopo de seu uso. No escopo global, quando um objeto é declarado no nível do arquivo, significa que esse objeto é visível apenas dentro desse arquivo.
Em qualquer outro escopo, ele declara um objeto que manterá seu valor entre os diferentes momentos em que o escopo específico é inserido. Por exemplo, se um int for delcared dentro de um procedimento:
void procedure(void){staticint i =0;
i++;}
o valor de 'i' é inicializado como zero na primeira chamada para o procedimento e o valor é retido cada vez que o procedimento é chamado. se 'i' fosse impresso, produziria uma sequência de 0, 1, 2, 3, ...
É importante observar que variáveis estáticas nas funções são inicializadas na primeira entrada dessa função e persistem mesmo após o término da chamada; no caso de funções recursivas, a variável estática é inicializada apenas uma vez e persiste também em todas as chamadas recursivas e mesmo após o término da chamada da função.
Se a variável foi criada fora de uma função, significa que o programador só pode usar a variável no arquivo de origem em que a variável foi declarada.
Então essa variável pode ser vista apenas neste arquivo. A variável não pode ser exportada para nenhum outro lugar.
Se você declarar dentro de uma função, o valor da variável manterá seu valor sempre que a função for chamada.
Uma função estática não pode ser exportada de fora do arquivo. Portanto, em um *.carquivo, você está ocultando as funções e as variáveis se as declarar estáticas.
Variáveis estáticas em C têm a vida útil do programa.
Se definidos em uma função, eles têm escopo local, ou seja, podem ser acessados apenas dentro dessas funções. O valor das variáveis estáticas é preservado entre as chamadas de função.
No programa acima, var é armazenado no segmento de dados. Sua vida útil é todo o programa C.
Após a chamada de função 1, vartorna-se 2. Após a chamada de função 2, vartorna-se 3.
O valor de varnão é destruído entre as chamadas de funções.
Se vartivesse entre variáveis não estáticas e locais, seria armazenado no segmento de pilha no programa C. Como o quadro da pilha da função é destruído após o retorno da função, o valor de vartambém é destruído.
Variáveis estáticas inicializadas são armazenadas no segmento de dados do programa C, enquanto variáveis não inicializadas são armazenadas no segmento BSS.
Outra informação sobre estática: se uma variável é global e estática, ela possui o tempo de vida do programa C, mas o escopo do arquivo. É visível apenas nesse arquivo.
Para tentar isso:
file1.c
staticint x;int main(){
printf("Accessing in same file%d", x):}
file2.c
externint x;
func(){
printf("accessing in different file %d",x);// Not allowed, x has the file scope of file1.c}
run gcc -c file1.c
gcc -c file2.c
Agora tente vinculá-los usando:
gcc -o output file1.o file2.o
Isso causaria um erro de vinculador, pois x tem o escopo do arquivo file1.c e o vinculador não conseguiria resolver a referência à variável x usada no arquivo2.c.
Eu entendo que os dados são persistentes, o que significa que não será perdido após cada chamada de função, mas por que não static int var = 1;mudar o valor de volta para uma de cada vez
Eames
3
Uma variável estática é uma variável especial que você pode usar em uma função e salva os dados entre as chamadas e não os exclui entre as chamadas. Por exemplo:
void func(){staticint count;// If you don't declare its value, the value automatically initializes to zero
printf("%d, ", count);++count;}void main(){while(true){
func();}}
Você pode substituir printf("%d, ", count); count++;por `printf ("% d, ", count ++) (não que isso importe: P).
RastaJedi
2
Um valor de variável estática persiste entre diferentes chamadas de função e seu escopo é limitado ao bloco local, uma var estática sempre inicializa com o valor 0
(1) Variáveis locais declaradas static: alocadas no segmento de dados em vez da pilha. Seu valor é retido quando você chama a função novamente.
(2) Variáveis ou funções globais declaradas static: Unidade de compilação externa invisível (ou seja, são símbolos locais na tabela de símbolos durante o vínculo).
As variáveis estáticas têm a propriedade de preservar seu valor mesmo depois de estarem fora do escopo! Portanto, as variáveis estáticas preservam o valor anterior no escopo anterior e não são inicializadas novamente no novo escopo.
Veja isso por exemplo - Uma variável int estática permanece na memória enquanto o programa está sendo executado. Uma variável normal ou automática é destruída quando uma chamada de função em que a variável foi declarada termina.
Como 1 permanece na memória como foi declarado estático
Variáveis estáticas (como variáveis globais) são inicializadas como 0 se não forem inicializadas explicitamente. Por exemplo, no programa abaixo, o valor de x é impresso como 0, enquanto o valor de y é algo como lixo. Veja isso para mais detalhes.
Na programação C, staticé uma palavra-chave reservada que controla a vida útil e a visibilidade. Se declararmos uma variável como estática dentro de uma função, ela será visível apenas em toda a função. Nesse uso, a vida útil dessa variável estática será iniciada quando uma chamada de função e será destruída após a execução dessa função. você pode ver o seguinte exemplo:
> O programa acima nos dará esta saída: Primeira saída do contador = 1 Segunda saída do contador = 1 <Não é verdade. Variáveis estáticas são inicializadas apenas uma vez. Portanto, a saída será 1, depois 2 e assim por diante.
Respostas:
(1) é o tópico mais externo se você é um novato, então aqui está um exemplo:
Isso imprime:
Isso é útil nos casos em que uma função precisa manter algum estado entre as invocações e você não deseja usar variáveis globais. Cuidado, no entanto, esse recurso deve ser usado com moderação - torna seu código não seguro para threads e mais difícil de entender.
(2) É amplamente utilizado como um recurso de "controle de acesso". Se você tem um arquivo .c implementando alguma funcionalidade, normalmente expõe apenas algumas funções "públicas" para os usuários. O restante de suas funções deve ser feito
static
, para que o usuário não possa acessá-las. Isso é encapsulamento, uma boa prática.Citando a Wikipedia :
E para responder sua segunda pergunta, não é como em C #.
No C ++, no entanto,
static
também é usado para definir atributos de classe (compartilhados entre todos os objetos da mesma classe) e métodos. Em C não há classes, portanto esse recurso é irrelevante.fonte
.c
monte de arquivos de cabeçalho, mas o diabo está sempre no que não é típico.Há mais um uso não abordado aqui, e isso é parte de uma declaração de tipo de matriz como argumento para uma função:
Nesse contexto, isso especifica que os argumentos passados para essa função devem ser uma matriz do tipo
char
com pelo menos 10 elementos. Para mais informações, veja minha pergunta aqui .fonte
arg[0]
atéarg[9]
a ter valores (o que também implica que a função não aceitar um ponteiro nulo). Os compiladores podem utilizar essas informações de alguma forma para otimização, e os analisadores estáticos podem utilizar essas informações para garantir que a função nunca receba um ponteiro nulo (ou, se puder dizer, uma matriz com menos elementos do que o especificado).static
em C99. Tem mais de uma década e meia de idade, mas nem todos os escritores de compiladores adotaram todos os recursos do C99 - portanto, o C99 como um todo permanece amplamente desconhecido.int arr[n];
, essa é uma VLA (matriz de comprimento variável) , que foi adicionada na C99. É isso que você quis dizer?Resposta curta ... depende.
Variáveis locais definidas estáticas não perdem seu valor entre as chamadas de função. Em outras palavras, são variáveis globais, mas com escopo definido para a função local em que estão definidos.
Variáveis globais estáticas não são visíveis fora do arquivo C em que estão definidas.
Funções estáticas não são visíveis fora do arquivo C em que estão definidas.
fonte
private
em C, sua analogia é boa: estática torna as coisas "privadas" para um determinado arquivo. E os arquivos em C frequentemente são mapeados para classes em C ++.Exemplo de escopo variável de vários arquivos
Aqui ilustro como a estática afeta o escopo das definições de função em vários arquivos.
ac
main.c
GitHub upstream .
Compile e execute:
Resultado:
Interpretação
si
, uma para cada arquivoi
Como de costume, quanto menor o escopo, melhor, sempre declare variáveis
static
se puder.Na programação C, os arquivos são frequentemente usados para representar "classes" e as
static
variáveis representam membros estáticos privados da classe.O que os padrões dizem sobre isso
C99 N1256 draft 6.7.1 "Especificadores da classe de armazenamento" diz que
static
é um "especificador da classe de armazenamento".6.2.2 / 3 "Ligações de identificadores" diz
static
implicainternal linkage
:e 6.2.2 / 2 diz que
internal linkage
se comporta como no nosso exemplo:onde "a unidade de tradução é um arquivo de origem após o pré-processamento.
Como o GCC o implementa para o ELF (Linux)?
Com o
STB_LOCAL
ligação.Se compilarmos:
e desmonte a tabela de símbolos com:
a saída contém:
portanto, a ligação é a única diferença significativa entre eles.
Value
é apenas o deslocamento para a.bss
seção, portanto esperamos que seja diferente.STB_LOCAL
está documentado na especificação ELF em http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :o que a torna uma escolha perfeita para representar
static
.Variáveis sem estática são
STB_GLOBAL
e a especificação diz:que é coerente com os erros de link em várias definições não estáticas.
Se acionarmos a otimização
-O3
, osi
símbolo será removido inteiramente da tabela de símbolos: ele não pode ser usado de fora de qualquer maneira. TODO por que manter variáveis estáticas na tabela de símbolos quando não há otimização? Eles podem ser usados para qualquer coisa? Talvez para depuração.Veja também
static
funções: https://stackoverflow.com/a/30319812/895245static
comextern
, o que "faz o contrário": como uso extern para compartilhar variáveis entre arquivos de origem?Namespace anônimos em C ++
No C ++, convém usar espaços de nome anônimos em vez de estático, o que gera um efeito semelhante, mas oculta ainda mais as definições de tipo: espaços de nome anônimos / anônimos / funções estáticas
fonte
Depende:
A função retornaria 1, 2, 3 etc. - a variável não está na pilha.
ac:
Isso significa que esta função tem escopo apenas neste arquivo. Portanto, ac e bc podem ter
foo()
s diferentes , e foo não é exposto a objetos compartilhados. Portanto, se você definiu foo em ac, não poderia acessá-lo deb.c
ou de outros lugares.Na maioria das bibliotecas C, todas as funções "privadas" são estáticas e a maioria "pública" não é.
fonte
As pessoas continuam dizendo que 'estático' em C tem dois significados. Ofereço uma maneira alternativa de visualizá-lo, que lhe dá um único significado:
A razão pela qual parece ter dois significados é que, em C, todo item ao qual 'estático' pode ser aplicado já possui uma dessas duas propriedades , portanto parece que esse uso específico envolve apenas o outro.
Por exemplo, considere variáveis. As variáveis declaradas fora das funções já têm persistência (no segmento de dados), portanto, aplicar 'estático' só pode torná-las visíveis fora do escopo atual (unidade de compilação). Por outro lado, variáveis declaradas dentro de funções já não têm visibilidade fora do escopo atual (função), portanto, aplicar 'estático' só pode torná-las persistentes.
Aplicar 'estático' a funções é como aplicá-lo a variáveis globais - o código é necessariamente persistente (pelo menos no idioma), portanto, apenas a visibilidade pode ser alterada.
NOTA: Esses comentários se aplicam apenas a C. No C ++, aplicar 'estático' aos métodos de classe está realmente dando à palavra-chave um significado diferente. Da mesma forma para a extensão de argumento de matriz C99.
fonte
static
fornece ligação interna a um identificador.Da Wikipedia:
fonte
static
significa coisas diferentes em diferentes contextos.Você pode declarar uma variável estática em uma função C. Essa variável é visível apenas na função, no entanto, ela se comporta como um global, pois é inicializada apenas uma vez e mantém seu valor. Neste exemplo, toda vez que você ligar
foo()
, imprimirá um número crescente. A variável estática é inicializada apenas uma vez.Outro uso de estático é quando você implementa uma função ou variável global em um arquivo .c, mas não deseja que seu símbolo seja visível fora do
.obj
gerado pelo arquivo. por exemplofonte
Se você declarar uma variável em uma função estática, seu valor não será armazenado na pilha de chamadas de funções e continuará disponível quando você chamar a função novamente.
Se você declarar uma variável global estática, seu escopo será restrito ao arquivo em que você a declarou. Isso é um pouco mais seguro que um global comum, que pode ser lido e modificado durante todo o programa.
fonte
Detesto responder a uma pergunta antiga, mas acho que ninguém mencionou como a K&R a explica na seção A4.1 de "A linguagem de programação C".
Em resumo, a palavra estática é usada com dois significados:
static
palavra - chave (grande ênfase em ser usada no código como palavra-chave) é usada com uma declaração, ela fornece a ligação interna ao objeto para que ela possa ser usada apenas dentro dessa unidade de tradução. Mas se a palavra-chave for usada em uma função, ela altera a classe de armazenamento do objeto (o objeto só seria visível dentro dessa função). O oposto de static é aextern
palavra - chave, que fornece a ligação externa a um objeto.Peter Van Der Linden dá esses dois significados em "Programação C Especialista":
fonte
register
um especificador de classe de armazenamento (C99 6.7.1 Especificadores de classe de armazenamento). E é mais do que apenas uma dica, por exemplo, você não pode aplicar o endereço do operador&
em um objeto com classe de armazenamento,register
independentemente de o compilador alocar um registro ou não.Em C, estática tem dois significados, dependendo do escopo de seu uso. No escopo global, quando um objeto é declarado no nível do arquivo, significa que esse objeto é visível apenas dentro desse arquivo.
Em qualquer outro escopo, ele declara um objeto que manterá seu valor entre os diferentes momentos em que o escopo específico é inserido. Por exemplo, se um int for delcared dentro de um procedimento:
o valor de 'i' é inicializado como zero na primeira chamada para o procedimento e o valor é retido cada vez que o procedimento é chamado. se 'i' fosse impresso, produziria uma sequência de 0, 1, 2, 3, ...
fonte
É importante observar que variáveis estáticas nas funções são inicializadas na primeira entrada dessa função e persistem mesmo após o término da chamada; no caso de funções recursivas, a variável estática é inicializada apenas uma vez e persiste também em todas as chamadas recursivas e mesmo após o término da chamada da função.
Se a variável foi criada fora de uma função, significa que o programador só pode usar a variável no arquivo de origem em que a variável foi declarada.
fonte
Se você declarar isso em um
mytest.c
arquivo:Então essa variável pode ser vista apenas neste arquivo. A variável não pode ser exportada para nenhum outro lugar.
Se você declarar dentro de uma função, o valor da variável manterá seu valor sempre que a função for chamada.
Uma função estática não pode ser exportada de fora do arquivo. Portanto, em um
*.c
arquivo, você está ocultando as funções e as variáveis se as declarar estáticas.fonte
Variáveis estáticas em C têm a vida útil do programa.
Se definidos em uma função, eles têm escopo local, ou seja, podem ser acessados apenas dentro dessas funções. O valor das variáveis estáticas é preservado entre as chamadas de função.
Por exemplo:
No programa acima,
var
é armazenado no segmento de dados. Sua vida útil é todo o programa C.Após a chamada de função 1,
var
torna-se 2. Após a chamada de função 2,var
torna-se 3.O valor de
var
não é destruído entre as chamadas de funções.Se
var
tivesse entre variáveis não estáticas e locais, seria armazenado no segmento de pilha no programa C. Como o quadro da pilha da função é destruído após o retorno da função, o valor devar
também é destruído.Variáveis estáticas inicializadas são armazenadas no segmento de dados do programa C, enquanto variáveis não inicializadas são armazenadas no segmento BSS.
Outra informação sobre estática: se uma variável é global e estática, ela possui o tempo de vida do programa C, mas o escopo do arquivo. É visível apenas nesse arquivo.
Para tentar isso:
file1.c
file2.c
Agora tente vinculá-los usando:
Isso causaria um erro de vinculador, pois x tem o escopo do arquivo file1.c e o vinculador não conseguiria resolver a referência à variável x usada no arquivo2.c.
Referências:
fonte
static int var = 1;
mudar o valor de volta para uma de cada vezUma variável estática é uma variável especial que você pode usar em uma função e salva os dados entre as chamadas e não os exclui entre as chamadas. Por exemplo:
A saída:
fonte
printf("%d, ", count); count++;
por `printf ("% d, ", count ++) (não que isso importe: P).Um valor de variável estática persiste entre diferentes chamadas de função e seu escopo é limitado ao bloco local, uma var estática sempre inicializa com o valor 0
fonte
Existem 2 casos:
(1) Variáveis locais declaradas
static
: alocadas no segmento de dados em vez da pilha. Seu valor é retido quando você chama a função novamente.(2) Variáveis ou funções globais declaradas
static
: Unidade de compilação externa invisível (ou seja, são símbolos locais na tabela de símbolos durante o vínculo).fonte
As variáveis estáticas têm a propriedade de preservar seu valor mesmo depois de estarem fora do escopo! Portanto, as variáveis estáticas preservam o valor anterior no escopo anterior e não são inicializadas novamente no novo escopo.
Veja isso por exemplo - Uma variável int estática permanece na memória enquanto o programa está sendo executado. Uma variável normal ou automática é destruída quando uma chamada de função em que a variável foi declarada termina.
Isso produzirá: 1 2
Como 1 permanece na memória como foi declarado estático
Variáveis estáticas (como variáveis globais) são inicializadas como 0 se não forem inicializadas explicitamente. Por exemplo, no programa abaixo, o valor de x é impresso como 0, enquanto o valor de y é algo como lixo. Veja isso para mais detalhes.
Isso produzirá: 0 [some_garbage_value]
Estes são os principais que descobri que não foram explicados acima para um novato!
fonte
Na programação C,
static
é uma palavra-chave reservada que controla a vida útil e a visibilidade. Se declararmos uma variável como estática dentro de uma função, ela será visível apenas em toda a função. Nesse uso, a vida útil dessa variável estática será iniciada quando uma chamada de função e será destruída após a execução dessa função. você pode ver o seguinte exemplo:O programa acima nos dará esta saída:
Porque assim que chamarmos a função, ela inicializará o
count = 0
. E enquanto executamos o,counterFunction
ele destruirá a variável count.fonte