A linguagem de programação C ainda é usada?


96

Sou programador de C # e a maior parte do meu desenvolvimento é para sites, juntamente com alguns aplicativos do Windows. No que diz respeito a C, não o uso há muito tempo, pois não havia necessidade. Surpreendeu-me quando uma das minhas amigas disse que precisava aprender C para testar empregos, enquanto eu a ajudava a aprender C #.

Imaginei que alguém só aprenderia C para teste se houver desenvolvimento sendo feito em C. Pelo que sei, todo o desenvolvimento relacionado ao COM e ao design de hardware também é feito em C ++. Portanto, aprender C não faz sentido se você precisar usar C ++. Também não acredito em significado histórico, então por que perder tempo e dinheiro aprendendo C?

O C ainda é usado em qualquer tipo de desenvolvimento de software novo ou qualquer outra coisa?


46
Você já viu um compilador C ++ para PICs?
SK-logic

195
Eu sou o único que está triste por alguém igualar aprendizado a desperdiçar tempo e dinheiro?
Jetti

37
" No meu conhecimento, todo o desenvolvimento relacionado ao COM e ao design de hardware também é feito em C ++ " - Parece-me que você realmente não faz nenhum design de interface de hardware.
Ed S.

32
As pessoas esquecem que línguas a fantasia de mais alto nível que todos nós amamos são muitas vezes implementadas em C.
David Cowden

13
@ThomasEding Língua morta? Você certamente tem um conhecimento muito limitado de linguagens de programação se considerar C uma linguagem inoperante.
JesperE

Respostas:


214

C tem a vantagem de ser uma linguagem relativamente pequena , o que facilita a implementação de um compilador C (enquanto um compilador C ++ é um monstro para se escrever) e facilita o aprendizado da linguagem . Veja também o índice TIOBE , segundo o qual C ligeiramente à frente do C ++.

Na ordem decrescente de justificação (IMO), C ainda é muito usado para

  • Coisas incorporadas
    É muito mais fácil portar um compilador C para uma plataforma pequena do que portar um compilador C ++. Além disso, os advogados do C afirmam que o C ++ "faz muito pelas costas". No entanto, a IMO é FUD.

  • Programação de sistemas
    Novamente, isso geralmente ocorre devido a alegações de que é mais fácil "saber o que o compilador está fazendo". No entanto, muitos programas incorporados se beneficiariam, por exemplo, de modelos e outros recursos principais do C ++.

  • Software de código aberto
    Esse é principalmente um problema de atitude: o OSS sempre preferiu o C ao invés do C ++ (embora seja o oposto em grandes partes da indústria). O ódio irracional de Torvalds pode realmente ser a razão mais importante para isso no Linux .


16
É mais história do que atitude. Muitos dos que você pode considerar os pacotes de código aberto "essenciais" foram desenvolvidos originalmente quando o C ++ não estava tão amplamente disponível como agora e os recursos ainda eram escassos.
Blrfl

65
O índice TIOBE é uma piada. Os resultados do mecanismo de pesquisa não têm sentido.
precisa saber é o seguinte

29
@Sedate: Que os modelos geralmente causam inchaço no código é um mito, vindo dos tempos dos antigos compiladores C ++. Compiladores modernos dobrarão instâncias de modelo idênticas. OTOH, os modelos permitem a meta-programação de modelos, que executa o código no tempo de compilação, em vez do tempo de execução, resultando em menos código sendo gerado. Além disso, eles criam programas muito mais seguros (menos conversão), algo que geralmente é muito importante no domínio incorporado. O EC ++ foi espancado até a morte por especialistas em C ++ devido (entre outras coisas) à pura estupidez de jogar fora modelos.
SBI

18
@ James: Você quer dizer coisas como abstrações eficientes, programação genérica e segurança de tipos? Sim, quem iria querer isso.
Xeo 4/11/12

11
@JesperE Por acaso, mudei de emprego desde que escrevi isso e agora estou programando para dispositivos incorporados. Estamos usando C ++, e é notável o que a meta-programação STL e modelo pode fazer por você quando você tem hardware fraco e restrições em tempo real, além de necessidades de confiabilidade. (Estamos construindo usinas de energia.) Sim, você precisa saber se deve usar um std::vectorou um std::mappara um determinado código - mas não precisa implementá-lo sozinho, mas pode confiar em um teste bem-sucedido e de alto desempenho, e implementações de bibliotecas confiáveis, oferecendo altas abstrações.
S3

119

C é muito usado na programação de hardware incorporado, onde os recursos são escassos.

O kernel do Linux é escrito em C porque, de acordo com Linus Torvalds, o C ++ é uma linguagem horrível .


14
Eu acho que grande parte do kernel do Windows também é C. E muitos sistemas legados.
Coder

14
Para ser completo, Linus tentou C ++ no kernel. Isso era mais um problema do que uma vantagem. De qualquer forma, o desenvolvimento do kernel é um tópico realmente específico, que não significa que o C ++ seja ruim em geral.
deadalnix

75
Segundo outros , a argumentação de Linus é horrível.
SBI

36
Os argumentos de Linus podem ou não ser válidos, mas o kernel do Linux ainda está escrito em C :-) comum
Joonas Pulakka

15
Linus é um idiota.
Ubiyubix

94

Todas as linguagens modernas que eu já vi podem interagir com C:

  • C ++
  • Java
  • C #
  • Pitão
  • Haskell
  • Objetivo C

A necessidade de interagir com C deriva de:

  • C com uma ABI simples
  • C estar por um longo tempo

Isso significa que, como esses idiomas podem se comunicar com C, eles podem:

  • alavancar suas bibliotecas
  • comunicar-se através do C (por exemplo, Clang é escrito em C ++, mas oferece ligações Python conectadas à sua interface C).

E eu apostaria que todos eles confiam em C para seus tempos de execução (a menos que fiquem em assembléia? Duvidosos).

C é o Lingua Franca das linguagens de programação e um dos mais simples (em termos de ABI) não vinculados a uma arquitetura específica (como o assembly é), será necessária uma grande mudança para se livrar dele.


45

Na minha opinião, essa é uma pergunta míope, semelhante a "Meus amigos e eu ouvimos Reggae. Alguém realmente ainda ouve Rap?".

Toda língua lá fora tem seu uso. Idiomas diferentes definitivamente têm seus nichos. Mas perguntando sobre C! Tenho certeza de que menos pessoas usam C # que C diariamente (do ponto de vista totalmente tendencioso de trabalhar em uma loja onde ninguém usa C #).

Google rápido olhando para a popularidade relativa dos idiomas.
Tenho certeza de que nada disso é autoritário, mas podemos usá-lo para ver tendências:

http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
http://langpop.com/

Mesmo olhando para a proporção SO da pergunta nas tags:
https://stackoverflow.com/tags

  • C #: 209845
  • 16 outras tags
  • C: 38790

Portanto, C é o 18 tópico mais popular no SO (e existem muitos outros idiomas lá).

Nota: O índice TIOBE acima é atualizado constantemente há mais de uma década (e tem alguns dados que remontam a 3 décadas) deve medir os engenheiros que trabalham em cada idioma (embora eu não tenha idéia de quão preciso seja). Das 10 principais linguagens, exceto Java / Visual Basic, ela reflete o que as pessoas da minha loja sabem (embora nossas proporções sejam ligeiramente diferentes, pois temos um tamanho de amostra muito menor).


1
Essa resposta me confunde ... você continua sobre o C # e mostra as tags de pergunta SO, mas nada disso tem realmente a ver com o C sendo usado. A popularidade (especialmente no langpop, onde eles usam consultas de mecanismos de pesquisa para determinar a popularidade) realmente não mostra o uso moderno de um idioma, apenas as pesquisas modernas em um idioma. Você deve levar em consideração, nas pesquisas, que o C é usado com frequência nas universidades para as classes de nível inferior, a fim de aumentar o número de consultas e também as postagens de SO.
Jetti

3
@Jetti: É por isso que digo explicitamente: I am sure none of this is authoritative but we can use it to see trendsMas eu discordo da sua segunda declaração; C não é mais a língua principal ensinada nos institutos de ensino superior (se fosse então, o novo lote de graduados não seria tão inútil). As pessoas tendem a aprender Java / C # sharp hoje em dia. Além disso, o relatório Tiobe trata de trabalhos, não de consultas.
Martin York

Olhando para trás, parece haver uma má escolha de palavras da minha parte. Eu não quis dizer as classes de baixo número (classes iniciais), mas as classes de sistemas (arquitetura de computadores) é onde C é usado.
Jetti

4
A contagem de tags SO não define a popularidade do idioma em geral, simplesmente mostra a popularidade do idioma entre os usuários do SO .
Ed S.

4
@ Ed S. Obviamente. Mas a questão não é sobre popularidade. É sobre a existência de C como idioma. A contagem de tags SO mostra que definitivamente não é um idioma morto. O fato de C estar entre os 2 primeiros nos outros sites não o torna o primeiro / segundo idioma mais usado. Mas sua existência no top 10 é um marcador significativo de que não está morta. É claro que nada disso prova apenas fortes indicadores de que C ainda está sendo usado ativamente.
Martin York

23

Você pode precisar usar C quando estiver com poucos recursos e não precisar de recursos orientados a objetos.

Muitos softwares em uso atualmente ainda estão escritos em C, sem mencionar os drivers de hardware.

Segundo o índice Tiobe , C ainda é o idioma mais utilizado.


Como sugeriu tcrosley, você pode dar uma olhada nesta questão relacionada .


Você também deve verificar alguns artigos relacionados sobre as diferenças entre C e C ++, como este wiki ou este, por exemplo.


4
ahem !! esse é um ótimo ponto. Nunca pensei que "os recursos de POO realmente sobrecarregam o idioma". Obrigado por deixar claro esse ponto válido. Agora, eu posso entender, onde C é à frente dos outros
Pankaj Upadhyay

7
@Pankaj C ++ geralmente não adiciona necessariamente muito tempo de execução, grande parte da complexidade da linguagem é o princípio de "não pagar pelo que você não usa" - se você não usa exceções, as exceções não o fazem. abrandar ou adicionar tamanho ao seu código. O compilador é maior e mais complexa embora
Martin Beckett

2
re C no campo incorporado, ver também a esta pergunta e respostas: programmers.stackexchange.com/questions/84514/...
tcrosley

6
Você nunca precisa de recursos de OOP, ele simplesmente funciona bem em alguns cenários.
Ed S.

2
@ Joseph Faeti: Meu chefe concordaria porque meu chefe é um cara experiente e racional. Ele não acredita em programação religiosa.
Ed S.

20

Parece que você está tentando se convencer de que C é inútil e, portanto, pode ser ignorado. Vamos analisar sua pergunta:

"Imaginei que alguém só aprenderia C para testar apenas se houver desenvolvimento feito em C."

Não, existem muitas razões para aprender C. Mesmo que você não soubesse que eu ainda evitaria usar declarações gerais como essa, especialmente em conjunto com a lógica circular. Obviamente, é necessário conhecer o idioma em que o código está escrito para poder testá-lo / corrigi-lo adequadamente, mas isso pressupõe que o idioma ainda seja usado como um dado e é verdadeiro para qualquer idioma e não apenas para C.

"No meu conhecimento, todo o desenvolvimento relacionado ao COM e design de hardware também é feito em C ++."

Isso está incorreto.

"Portanto, aprender C não faz sentido se você precisar usar C ++. Também não acredito em significado histórico, então por que perder tempo e dinheiro aprendendo C?"

Essa é a lógica mais questionável de todas. Primeiro, o significado histórico é algo em que você deve acreditar, porque se soubesse que C é um subconjunto de C ++ e, por isso, conhecer C pode ajudá-lo a ser um programador C ++ melhor. É claro que o C também influenciou a maioria dos idiomas que vieram depois, para que os benefícios não parem por aí. Além disso, como C é tão importante, não pode ser considerado como tendo apenas significado histórico. Ainda é amplamente utilizado e, portanto, não pode ser relegado para uma posição secundária como essa. Você pode argumentar que não é uma linguagem que todo programador precise usar e tenha um conhecimento aprofundado e que seria correto, mas por favor, não construa seu argumento dizendo que você não acredita em algo sem examinar primeiro seus verdadeiros méritos.


7
C é um subconjunto de C ++ , é isso que você quis dizer? . C não é um subconjunto de C ++; De fato, eles são bem diferentes. Sim, C ++ é um aprimoramento de C, ou às vezes referido como C com classes e OOP , mas para dizer C é um subconjunto, não justifica
Pankaj Upadhyay

7
C ++ é principalmente um superconjunto de uma versão antiga do C, e o C seguiu uma direção um pouco diferente desde então. Alguns aspectos das linguagens foram em direções amplamente paralelas, mas outros não (e o C ++ tem muitas outras coisas além disso).
Donal Fellows

Concordo em votar para esclarecer esse fato, nem todos os programas C válidos são programas C ++ válidos, ou seja, C ++ não é um superconjunto de C. No entanto, é um superconjunto de como C estava no momento de tomar a decisão de ser um superconjunto, como Donal Fellows mencionou. Simplesmente não faz sentido dizer que é mais, quando não é mais verdade.
Joshua Hedges

16

Além dos sistemas incorporados, a maioria das linguagens mais recentes tem alguma maneira de interagir com C. Ao escrever uma biblioteca que você deseja ter facilidade em usar em todas essas linguagens, C é uma escolha óbvia. C ++, embora ele também possa interagir com algumas linguagens (como Python (somente CPython)), C ++ não pode interagir com um número maior de linguagens devido a alguns de seus recursos (principalmente nomes diferentes, mas os modelos não ajudam no problema). O ABI C é um dos mais fáceis de interface (eu sei que você pode escrever C ++ e usar "C" externo para a interface. Não me importo).

Também tem o benefício de que C e C ++ são realmente as melhores linguagens para programação de sistemas e os tempos de compilação em C são muito mais rápidos. Os tempos de compilação do C ++ são visivelmente os piores de qualquer idioma que eu já usei.

Agora, enquanto existem outras linguagens que desejam se tornar a linguagem popular de sistemas por aí (eu conheço D em particular), uma grande maioria do software é escrita em C / C ++. Idiomas como D exigem que alguém crie um wrapper em torno da biblioteca C, em vez de apenas usá-lo diretamente (como faria no C ++).


D pode chamar o código C diretamente, assim como o C ++. Tudo que você precisa se o protótipo da função (novamente, como C ++). Você acabou de escrever extern(C)em D, enquanto que em C ++ que você escreveextern "C"
Peter Alexander

@ Peter Alexander Estou ciente de extern (C) em D. É a isso que eu estava me referindo quando disse o arquivo wrapper. Você não pode incluir diretamente o cabeçalho C (o que você pode fazer no C ++, supondo que o cabeçalho C use extern "C" e possua os blocos #ifdef __cplusplus, o que a maioria faz). Existem outras incompatibilidades entre usar apenas extern (C) (principalmente como as strings são tratadas. Pelo que sei, elas não têm um terminador nulo em D. Portanto, você deve alterar especialmente a matriz ao transmiti-la para C).
Jsternberg

11

confira langpop.com , especialmente os gráficos de Freshmeat e Google Code. Isso mostra que C ainda está muito à frente.

O C ainda é popular em sistemas nos quais você precisa se aproximar do metal (por exemplo, sistema embarcado) e dos aplicativos que exigem desempenho.


4
NÃO ABRA ESTE URL! O site não existe mais e o URL é redirecionado para algumas páginas de spam irritantes.
Nikolay Suvandzhiev 18/01/19

11

Eu o uso quase todos os dias desenvolvendo para iPad / iPhone. Muitas bibliotecas são escritas em C e não possuem um equivalente em Objective-C. Então, sim, ele ainda é usado e por um dos dispositivos mais recentes do mercado.

Com o C, você pode programar muitos sistemas embarcados, é pequeno e prático e provavelmente estará disponível por muitos anos (ou seja, você não está perdendo tempo nem dinheiro aprendendo isso)


2
"Objective-C ainda é jovem", na verdade, é de meados da década de 1980, quase com a idade de C ++. A maioria das pessoas que o usa não o encontrou até 2007, no entanto.

É verdade que o que eu queria dizer é basicamente que existem muitas bibliotecas C que não têm um equivalente no Objective-C para iOS. De fato, a própria linguagem não é jovem (verificada no Wiki). Obrigado por apontar isso.
Valentin Radu

7

Geralmente para o sistema incorporado C ainda é amplamente utilizado.

Esta pergunta dá outro exemplo.

O índice Tiobe , que tenta classificar o idioma por popularidade / uso , coloca consistentemente C em primeiro lugar.


2º Lugar (depois do Java).
Martin York

7
Interessante que C ++ e Java pareçam ter uma tendência decrescente de popularidade nos últimos 10 anos, enquanto C permanece mais ou menos estático.
Paul R

7

Portabilidade.

Faça uma lista de todos os sistemas que você acha que executam o código C e, em seguida, uma lista semelhante para todos os outros idiomas de que você gosta.

Se você veio com a mesma resposta que eu, então a conclusão é sim.


5

Bem, eu acho que C é a linguagem mais poderosa, pelas seguintes razões!

1) No primeiro C, é uma linguagem de sistemas (o que significa que pode ser usada para fazer programação de baixo nível com tempo de execução mínimo ou nenhum).

2) Velocidade da aplicação resultante. O código fonte C pode ser otimizado muito mais que os idiomas de nível superior porque o conjunto de idiomas é relativamente pequeno e muito eficiente. É o mais próximo possível da programação em linguagem assembly, sem programação em linguagem assembly. e você pode até usar assembly e C juntos!

3) C possui qual é a sua aplicação na programação de firmware (hardware). Isso se deve à sua capacidade de usar / trabalhar com montagem e se comunicar diretamente com controladores, processadores e outros dispositivos.

4) C é um componente básico para muitos outros idiomas atualmente conhecidos. Pesquise a história do C e você descobrirá que ele existe há algum tempo (como as linguagens de programação continuam assim). Dê uma olhada no Python, por exemplo, uma linguagem de programação de alto nível totalmente orientada a objetos. Está escrito em C (talvez também em C ++). Isso informa se você deseja saber o que está acontecendo em outros idiomas; é essencial entender C e como ele funciona.

Uma linguagem de aplicativos é usada para programação de alto nível, por exemplo, escrever um processador de texto ou jogo. Exemplos de linguagens de aplicativos são Java, C #. O motivo é que eles contêm coleta de lixo, digitação automática, validação em tempo de execução etc. - onde o foco é a produtividade.

Uma linguagem de sistemas é usada para programação de baixo nível. por exemplo, um microcontrolador, um driver e um kernel do sistema operacional. Os exemplos incluem montagem C. Eles requerem pouco ou nenhum tempo de execução para executar o código diretamente no hardware, e o foco é que o programador tenha controle direto sobre o hardware.

No geral, está declinando como uma linguagem de aplicativos, mas ainda se mantém forte como uma linguagem de sistemas.


1

Ah, sim, é usado. Eu trabalho na área de processamento de pacotes de rede. Estive em duas empresas diferentes onde processamos pacotes de rede. Portanto, estamos operando no nível Ethernet ou IP, não no nível acima do TCP.

Curiosamente, nas duas empresas, C foi escolhido em vez de C ++. Em uma das empresas, um dos dois produtos foi construído sobre o kernel do Linux, enquanto o outro produto foi construído no espaço do usuário do Linux. Obviamente, o produto do kernel usado C como kernel do Linux é programado em C, mas eles escolheram usar o C para o produto do espaço do usuário. Ambos os produtos foram desenvolvidos a partir do ano 2000 (o produto kernel um pouco antes de 2000 e o produto userspace um pouco depois de 2000).

Na empresa em que fui depois disso, o produto foi construído em C, não em C ++. Na verdade, é a continuação de um projeto a partir de meados dos anos 90, embora, devido às recentes demandas de melhoria de desempenho, tenha sido decidido que basicamente tudo será reescrito. Tivemos a opção de selecionar C ++ devido a essa reescrita, mas não o fizemos.

No campo do processamento de pacotes de rede, o desempenho conta muito. Portanto, quero implementar minha própria tabela de hash com desempenho superior às tabelas de hash existentes. Eu, não o autor da tabela de hash, sou quem seleciona qual função de hash deve ser usada. Talvez eu queira desempenho e opte pelo MurMurHash3 . Talvez eu queira segurança e opte pelo SipHash . Alocadores de memória são obviamente personalizados. De fato, todas as estruturas de dados importantes que usamos foram implementadas de forma personalizada para obter o melhor desempenho possível.

Embora não exista nada que impeça o uso do C ++, geralmente é uma má idéia. Uma única exceção lançada por pacote reduzirá a taxa de processamento de pacotes para níveis inaceitáveis! Portanto, não podemos usar as exceções do C ++. Muito devagar. Já estamos usando o tipo de código C orientado a objetos implementando estruturas de dados como estruturas e, em seguida, implementando funções que operam nessas estruturas. O C ++ permitiria ter funções virtuais, mas, novamente, as chamadas de função virtual reduziriam o desempenho se usadas em qualquer lugar. Portanto, é melhor ser explícito e ter um ponteiro de função se forem necessárias chamadas de função virtual.

C ++ fará muitas coisas pelas suas costas: alocação de memória etc. Por outro lado, em C isso geralmente não acontece. Você pode escrever uma função que aloca memória, mas geralmente é aparente na interface da função que a alocação está acontecendo.

Como exemplo do tipo de micro otimizações que você pode fazer ao programar em C, dê uma olhada na macro container_of no kernel do Linux. Claro, você poderia usar container_of no código C ++, mas quem faz isso? Quero dizer, é totalmente aceitável na maioria dos programas em C, mas os programadores típicos em C ++ propõem imediatamente outra coisa, como uma lista vinculada que aloca os nós do link como blocos separados. Não queremos isso porque cada bloco de memória alocado é ruim para o desempenho.

Talvez a única coisa que nos beneficiaria em C ++ é que o C ++ permite a metaprogramação de modelos, o que significa que às vezes você pode evitar chamadas de função virtual enquanto ainda possui um parâmetro de função e permitir que o compilador embuta as funções. Mas a metaprogramação de modelos é complicada e conseguimos atender a todos os requisitos em C; portanto, o benefício desse recurso em C ++ não é tão crítico.

Em uma das empresas, na verdade tínhamos uma linguagem compilada personalizada na qual parte dos recursos foram implementados. Adivinhe qual era o idioma de destino do compilador? Montagem? Não, tivemos que suportar arquiteturas de 32 e 64 bits. C ++? Certamente você está brincando. Obviamente, era C com o goto computado do GCC . Portanto, a linguagem personalizada foi compilada em C (ou na verdade a variante gcc de C que suportava goto computado), e o compilador C produziu o assembly.


0

Eu ainda uso o C diariamente e um dos principais motivos é a interoperabilidade com outros idiomas e um SDK projetado para ser usado por plugins criados por todos os tipos de compiladores em vários idiomas.

Não consigo escrever uma API C ++ que use classes com construtores e destruidores e vtables, sobrecarga de funções, lança exceções, etc. e configurações próprias.

Não consigo escrever um SDK de C # que possa ser chamado de Python, por exemplo, ou um SDK de Python que possa ser chamado de C #.

C é o único idioma aqui que me permite criar uma API que pode ser chamada a partir de qualquer um desses idiomas. Dito isto, costumo usar C ++ para implementar essas interfaces C (embora às vezes eu apenas as implemente em C).

Além disso, às vezes acho C a linguagem mais fácil de trabalhar para coisas como estruturas de dados de baixo nível e alocadores de memória. Toda a segurança extra de tipo que você obtém no C ++ não ajuda se você estiver gravando um alocador de memória projetado para agrupar bits e bytes alinhados. E contra o sistema de tipos avançados do C ++ e o tratamento de exceções, não é fácil rolar suas próprias estruturas de dados - basta ver quanto esforço é necessário para escrever uma estrutura de dados tão trivial como std::vectorse você quiser torná-la segura contra exceções e evitar chamar ctors e dtors em elementos que você não inseriu no contêiner (estou falando como alguém que implementou toda a biblioteca padrão C ++). Quando apenas uma matriz cultivável é muito difícil de implementar, imagine o trabalho necessário para implementar uma BVH com qualidade de produção.

Prefiro C ++ ao C quando quero usar estruturas de dados existentes ou implementar estruturas de nível superior usando as existentes, mas se vou implementar uma estrutura de dados de nível inferior no núcleo de um mecanismo que não tem utilidade para estruturas de dados existentes, C definitivamente torna isso muito mais fácil de fazer com seu sistema de tipo simplista, que permite apenas memcpycoisas aqui e memmoveali, mallocum bloco contíguo e reallocali, sem se preocupar com construtores, destruidores e exceções lançadas.

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.