Onde a palavra-chave C auto é usada?


104

Nos meus tempos de faculdade, li sobre a autopalavra - chave e, com o passar do tempo, realmente esqueci qual é. É definido como:

define uma variável local como tendo um tempo de vida local

Eu nunca descobri que ele está sendo usado em qualquer lugar, ele é realmente usado e se sim, então onde é usado e em que casos?

Respostas:


90

autoé um modificador semelhante static. Ele define a classe de armazenamento de uma variável. No entanto, como o padrão para variáveis ​​locais é auto, normalmente você não precisa especificá-lo manualmente.

Esta página lista diferentes classes de armazenamento em C.


13
Só estava olhando para isso novamente depois que alguém votou positivamente em minha resposta. Você diz que "normalmente não precisa especificá-lo manualmente". Só tenho que perguntar: há realmente uma circunstância em que auto pode ser especificada, mas não acontecerá por padrão?
Jerry Coffin

2
@JerryCoffin Não em C. Em C ++ 11, ele é reaproveitado e você pode usá-lo para obter inferência de tipo de variável local com eficácia.
Mehrdad Afshari

2
Um uso possível é na declaração de funções aninhadas no GNU C - embora isso seja um sequestro da definição original de auto. tigcc.ticalc.org/doc/keywords.html#auto
josiah

2
A página vinculada está desatualizada. Desde C11, também há _Thread_localdetalhes: en.cppreference.com/w/c/language/storage_duration e stackoverflow.com/a/14289720/6557621
MCCCS

132

Se você leu a lista IAQ (perguntas infrequentes), sabe que o auto é útil principalmente para definir ou declarar um veículo:

auto my_car;

Um veículo que está constantemente estacionado ao ar livre:

extern auto my_car;

Para quem não tem senso de humor e quer "apenas os fatos, senhora": a resposta curta é que nunca há motivo para usar auto. A única vez que você tem permissão para usar autoé com uma variável que já tem autoclasse de armazenamento, então você está apenas especificando algo que aconteceria de qualquer maneira. Tentar usar autoem qualquer variável que ainda não tenha a autoclasse de armazenamento resultará na rejeição do código pelo compilador. Suponho que, se você quiser ser técnico, sua implementação não precisa ser um compilador (mas é) e, teoricamente, pode continuar a compilar o código depois de emitir um diagnóstico (mas não vai).

Pequeno adendo de kaz :

Também existe:

static auto my_car;

que requer um diagnóstico de acordo com a ISO C. Correto, pois declara que o carro está quebrado. O diagnóstico é gratuito, mas desligar a luz do painel vai custar oitenta dólares. (Vinte ou menos, se você comprar seu próprio dongle USB para diagnóstico on-board do eBay).

O referido extern auto my_cartambém requer um diagnóstico e, por isso, nunca é executado através do compilador, a não ser pelos funcionários municipais encarregados da fiscalização do estacionamento.

Se você vê muito extern static auto ...em qualquer base de código, você está em uma má vizinhança; procure um emprego melhor imediatamente, antes que todo o lugar se transforme em Rust.


@self .: O ISO não parece conhecer um "ISO 2011". O que você acha que pode padronizar?
Jerry Coffin

6
Ainda bem que eu não tinha café, cola, cerveja preta ou algum outro líquido escuro na boca. Você me deveria uma tela de computador, @JerryCoffin, se fosse esse o caso. MELHOR RESPOSTA DE SEMPRE!
David Hammen

2
@Dan: Honestamente, você demorou "um bom tempo" para ler 5 linhas de texto e chegar à parte em que diz: "a resposta curta é que nunca há razão para usar o automóvel"? Seriamente? Dado o comentário imediatamente anterior ao seu, parece que pelo menos algumas pessoas consideram uma contribuição positiva.
Jerry Coffin

@JerryCoffin eu já expliquei isso, leia meu comentário novamente. A retrospectiva é 20/20.
Dan Bechard

2
Recentemente, passei por um sério incêndio (fechei duas pistas) que sugere a necessidade dechar auto my_car;
total

46

A autopalavra-chave é inútil na linguagem C. Está aí porque antes da linguagem C existia uma linguagem B na qual essa palavra-chave era necessária para declarar variáveis ​​locais. (B foi desenvolvido para NB, que se tornou C).

Aqui é o manual de referência para B .

Como você pode ver, o manual está repleto de exemplos de autouso. Isso ocorre porque não existe uma intpalavra-chave. É necessário algum tipo de palavra-chave para dizer "esta é uma declaração de uma variável", e essa palavra-chave também indica se é local ou externo ( autoversus extrn). Se você não usar um ou outro, terá um erro de sintaxe. Quer dizer, x, y;não é uma declaração por si só, mas auto x, y;é.

Como as bases de código escritas em B tiveram que ser portadas para NB e C conforme a linguagem era desenvolvida, as versões mais recentes da linguagem carregavam alguma bagagem para compatibilidade com versões anteriores aprimorada que se traduzia em menos trabalho. No caso de auto, os programadores não tiveram que localizar todas as ocorrências autoe removê-las.

É óbvio no manual que o agora obsoleto "int implícito" cruft em C (ser capaz de escrever main() { ... }sem nenhum intna frente) também vem de B. Esse é outro recurso de compatibilidade com versões anteriores para suportar código B. As funções não têm um tipo de retorno especificado em B porque não há tipos. Tudo é uma palavra, como em muitas linguagens de montagem.

Observe como uma função pode simplesmente ser declarada extrn putchare a única coisa que a torna uma função que o identificador usa : ela é usada em uma expressão de chamada de função como putchar(x), e é isso que diz ao compilador para tratar essa palavra sem tipo como um ponteiro de função.


24

Em C autoestá uma palavra-chave que indica que uma variável é local para um bloco. Como esse é o padrão para variáveis ​​com escopo de bloco, ele é desnecessário e muito raramente usado (acho que nunca vi isso usar fora dos exemplos em textos que discutem a palavra-chave). Eu estaria interessado se alguém pudesse apontar um caso em que o uso de autofoi necessário para obter uma análise ou comportamento correto.

No entanto, no padrão C ++ 11, a autopalavra-chave foi 'sequestrada' para dar suporte à inferência de tipo, onde o tipo de uma variável pode ser obtido do tipo de seu inicializador:

auto someVariable = 1.5;   // someVariable will have type double

A inferência de tipo está sendo adicionada principalmente para oferecer suporte à declaração de variáveis ​​em modelos ou retornada de funções de modelo, onde tipos baseados em um parâmetro de modelo (ou deduzidos pelo compilador quando um modelo é instanciado) podem ser bastante difíceis de declarar manualmente.


1
“A variável é local para um bloco” - isso não é verdade. Todas as variáveis ​​declaradas em um bloco são locais para esse bloco (com relação ao escopo). Eles podem estar associados a outras variáveis ​​no programa, mas a declaração só é visível naquele bloco. autoé sobre a classe de armazenamento que não tem nada a ver com visibilidade.
fuz

12

Com o antigo compilador Aztec C, era possível transformar todas as variáveis ​​automáticas em variáveis ​​estáticas (para aumentar a velocidade de endereçamento) usando uma chave de linha de comando.

Mas as variáveis ​​declaradas explicitamente com autoforam deixadas como estão nesse caso. (Obrigatório para funções recursivas que, de outra forma, não funcionariam corretamente!)


7

A autopalavra-chave é semelhante à inclusão de ponto e vírgula em Python, era exigida por uma linguagem anterior ( B), mas os desenvolvedores perceberam que era redundante porque a maioria das coisas era auto.

Suspeito que foi deixado para ajudar na transição de B para C. Em suma, um uso é para compatibilidade de linguagem B.

Por exemplo em B e 80s C:

/* The following function will print a non-negative number, n, to
   the base b, where 2<=b<=10.  This routine uses the fact that
   in the ASCII character set, the digits 0 to 9 have sequential
   code values.  */

printn(n, b) {
        extrn putchar;
        auto a;

        if (a = n / b)        /* assignment, not test for equality */
                printn(a, b); /* recursive */
        putchar(n % b + '0');
}

1

A palavra-chave automática é um exemplo de classe de armazenamento (algum tipo de técnica que decide a vida útil da variável e do local de armazenamento). Ele tem um comportamento pelo qual a variável criada pela Ajuda dessa palavra-chave tem vida útil (tempo de vida) reside apenas entre as chaves

{
    auto int x=8;        
    printf("%d",x);  // here x is 8

    { 
        auto int x=3;
        printf("%d",x);  // here x is 3
    }              

    printf("%d",x);  // here x is 8
}          

0

autosó pode ser usado para variáveis ​​com escopo de bloco. extern auto inté lixo porque o compilador não pode determinar se isso usa uma definição externa ou se substitui o externo por uma definição automática (também auto e extern são durações de armazenamento totalmente diferentes, como static auto int, o que também é lixo, obviamente). Ele sempre pode escolher interpretá-lo de uma maneira, mas, em vez disso, opta por tratá-lo como um erro.

Existe um recurso que autofornece e que permite a regra 'tudo é um int' dentro de uma função. Ao contrário de fora de uma função, onde a=3é interpretado como uma definição int a =3porque as atribuições não existem no escopo do arquivo, a=3é um erro dentro de uma função porque, aparentemente, o compilador sempre interpreta como uma atribuição a uma variável externa ao invés de uma definição (mesmo se houver há extern int adeclarações para a frente na função ou no escopo do arquivo), mas um especificador como static, const, volatileou autoimplicaria que é uma definição e o compilador leva-lo como uma definição, exceto autonão tem os efeitos colaterais dos outros especificadores. auto a=3é, portanto, implicitamente auto int a = 3. Na verdade,signed a = 3tem o mesmo efeito e unsigned a = 3é sempre um int não assinado.

Observe também que ' autonão tem efeito sobre se um objeto será alocado a um registrador (a menos que algum compilador particular preste atenção a ele, mas isso parece improvável)'


-1

Tenho certeza de que você está familiarizado com os especificadores de classe de armazenamento em C, que são "extern", "estático", "registrar" e "automático". A definição de "auto" é praticamente fornecida em outras respostas, mas aqui está um possível uso da palavra-chave "auto" que não tenho certeza, mas acho que depende do compilador. Veja, com relação aos especificadores de classe de armazenamento, há uma regra. Não podemos usar vários especificadores de classe de armazenamento para uma variável. É por isso que variáveis ​​globais estáticas não podem ser externadas. Portanto, eles são conhecidos apenas por seu arquivo. Quando você vai para a configuração do compilador, pode habilitar o sinalizador de otimização para velocidade. uma das maneiras que o compilador otimiza é, ele procura variáveis ​​sem especificadores de classe de armazenamento e, em seguida, faz uma avaliação com base na disponibilidade de memória cache e alguns outros fatores para ver se deve tratar essa variável usando o especificador de registro ou não. Agora, e se quisermos otimizar nosso código para velocidade, sabendo que uma variável específica em nosso programa não é muito importante e não queremos que o compilador a considere nem mesmo como um registro. No entanto, ao colocar auto, o compilador não será capaz de adicionar o especificador de registro a uma variável desde que digitei "register auto int a;" OU "registro automático int a;" levanta o erro de usar vários especificadores de classe de armazenamento. Para resumir, pensei que auto pode proibir o compilador de tratar uma variável como registro por meio de otimização. E se quisermos otimizar nosso código para velocidade, sabendo que uma variável específica em nosso programa não é muito importante e não queremos que o compilador a considere nem mesmo como um registro. No entanto, ao colocar auto, o compilador não será capaz de adicionar o especificador de registro a uma variável desde que digitei "register auto int a;" OU "registro automático int a;" levanta o erro de usar vários especificadores de classe de armazenamento. Para resumir, pensei que auto pode proibir o compilador de tratar uma variável como registro por meio de otimização. E se quisermos otimizar nosso código para velocidade, sabendo que uma variável específica em nosso programa não é muito importante e não queremos que o compilador a considere nem mesmo como um registro. No entanto, ao colocar auto, o compilador não será capaz de adicionar o especificador de registro a uma variável desde que digitei "register auto int a;" OU "registro automático int a;" levanta o erro de usar vários especificadores de classe de armazenamento. Para resumir, pensei que auto pode proibir o compilador de tratar uma variável como registro por meio de otimização. levanta o erro de usar vários especificadores de classe de armazenamento. Para resumir, pensei que auto pode proibir o compilador de tratar uma variável como registro por meio de otimização. levanta o erro de usar vários especificadores de classe de armazenamento. Para resumir, pensei que auto pode proibir o compilador de tratar uma variável como registro por meio de otimização.

Esta teoria não funcionou para o compilador GCC, no entanto, não tentei outros compiladores.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.