C é fortemente tipado?


88

Para citar a Wikipedia :

Duas linguagens comumente usadas que suportam muitos tipos de conversão implícita são C e C ++, e às vezes é afirmado que essas são linguagens de tipagem fraca. No entanto, outros argumentam que essas linguagens impõem restrições suficientes sobre como operandos de diferentes tipos podem ser misturados, de modo que os dois devem ser considerados como linguagens fortemente tipadas.

Existe uma resposta mais definitiva?


188
Para um programador C, digitar forte significa pressionar as teclas com mais força.
Dan Dyer

2
C está no lado fraco no contínuo de digitação. Mas há itens suficientes em ambos os lados que você pode argumentar de qualquer maneira. Enquanto você está nisso, você também pode perguntar (vi ou emacs, netbeans ou eclipse, etc.)
Cervo

4
A situação na Wikipedia era ruim o suficiente para que me sentisse compelido a editar várias páginas da Wikipedia. Talvez as coisas estejam um pouco melhores agora. Talvez.
Norman Ramsey

40
Re: Comentário de Dan (para dar crédito onde é devido) O livro de Peter van der Linden "Expert C Programming" contém a seguinte linha: "Até hoje, muitos programadores de C acreditam que 'digitação forte significa apenas bater com mais força no teclado."
Alexandros Gezerlis

Muito boa pergunta !!!
Destrutor

Respostas:


154

"Fortemente tipado" e "fracamente tipado" são termos que não possuem um significado técnico amplamente aceito Os termos que têm um significado bem definido são

  • Digitado dinamicamente significa que os tipos são anexados aos valores em tempo de execução e uma tentativa de misturar valores de diferentes tipos pode causar um "erro de tipo em tempo de execução". Por exemplo, se em Scheme você tentar adicionar um a true escrevendo, (+ 1 #t)isso causará um erro. Você encontrará o erro apenas se tentar executar o código ofensivo.

  • Digitado estaticamente significa que os tipos são verificados em tempo de compilação e um programa que não possui um tipo estático é rejeitado pelo compilador. Por exemplo, se no ML você tentar adicionar um a verdadeiro escrevendo 1 + true, o programa será rejeitado com uma mensagem de erro (provavelmente enigmática). Você sempre obtém o erro, mesmo se o código nunca puder ser executado.

Diferentes pessoas preferem diferentes sistemas de acordo em parte com o quanto valorizam a flexibilidade e quanto se preocupam com erros em tempo de execução.

Às vezes, "fortemente tipado" é usado vagamente para significar "digitado estaticamente", e "digitado fracamente" é usado incorretamente para significar "digitado dinamicamente". Um uso melhor para o termo "fortemente tipado" é que "você não pode contornar ou subverter o sistema de tipos", enquanto "fracamente tipado" significa "existem lacunas no sistema de tipos". Perversamente, a maioria das linguagens com sistemas de tipos estáticos têm lacunas, enquanto muitas linguagens com sistemas de tipos dinâmicos não têm lacunas.

Nenhum desses termos está relacionado de forma alguma com o número de conversões implícitas disponíveis em um idioma.

Se você deseja falar precisamente sobre linguagens de programação, é melhor evitar os termos "fortemente tipado" e "fracamente tipado". Eu diria que C é uma linguagem que é tipificada estaticamente, mas que tem muitas lacunas. Uma lacuna é que você pode converter livremente qualquer tipo de ponteiro para qualquer outro tipo de ponteiro. Você também pode criar uma lacuna entre quaisquer dois tipos de sua escolha, declarando uma união C que tem dois membros, um para cada um dos tipos em questão.

Escrevi mais sobre tipagem estática e dinâmica em why-interpreted-langs-are-principalmente-ducktyped-while-compilado-have-strong-typ .


2
De onde você tirou as definições que sugere para tipagem forte / fraca (a brecha)?
Sydius

2
Por que você precisa de uma "brecha" em um ambiente de digitação dinâmico?
Chris Conway

4
@Sydius: Por ter passado grande parte dos últimos 20 anos saindo com pessoas que projetam, constroem e analisam linguagens de programação e sistemas de tipos. Esse é o meu trabalho remunerado :-)
Norman Ramsey

@Chris: Eu nunca vi uma linguagem digitada dinamicamente com 'brecha'. O uso comum de brecha é trabalhar com um sistema de tempo de execução ou SO, por exemplo, pegar um endereço bruto e convertê-lo em um ponteiro para um valor de linguagem bem comportado. Você poderia fazer isso em um ambiente dinâmico, mas não sei de nenhuma tentativa.
Norman Ramsey

1
@NormanRamsey Acho que Chris estava se referindo com sua pergunta a:whereas "weakly typed" means "there are loopholes in the type system
Nir Alfasi

23

É difícil classificar todos os idiomas em tipificados "fracamente" ou "fortemente" - é mais um continuum. Mas, em comparação com outras linguagens, C é fortemente tipado. Cada objeto tem um tipo de tempo de compilação, e o compilador irá informá-lo (em voz alta) se você estiver fazendo algo com um objeto que seu tipo não permite. Por exemplo, você não pode chamar funções com os tipos errados de parâmetros, acessar membros de struct / union que não existem, etc.

Mas existem alguns pontos fracos. Uma das principais fraquezas são as typecasts - elas basicamente dizem que você vai bagunçar os tipos de objetos e o compilador deve ficar quieto (quando puder). void*também é outra fraqueza - é um indicador genérico para um tipo desconhecido e, quando você os usa, deve ser extremamente cuidadoso para estar fazendo a coisa certa. O compilador não pode verificar estaticamente a maioria dos usos de void*. void*também pode ser convertido em um ponteiro para qualquer tipo sem uma conversão (apenas em C, não em C ++), que é outro ponto fraco.


Boa resposta, embora "typecasts ... e o compilador devem ser silenciosos" me incomoda. Um typecast não é como desligar um aviso; na verdade, muda a interpretação do valor que está sendo referenciado.
Tall Jeff

15
Você está confundindo "estático" e "forte" em relação à digitação. Esses dois conceitos são independentes um do outro.
bendin

1
Dennis Richie (autor C) chamou C de 'fortemente tipado e fracamente verificado'
TimZaman

11

A literatura não é clara sobre isso. Eu acho que fortemente tipado não é sim / não, existem vários graus de tipificação forte.

Uma linguagem de programação possui uma especificação de como executa os programas. Às vezes, não está claro como executar com certos programas. Por exemplo, programas que tentam subtrair uma string de um número. Ou programas que dividem por zero. Existem várias maneiras de lidar com essas condições. Algumas linguagens têm regras para lidar com esses erros (por exemplo, eles lançam uma exceção). Outras linguagens simplesmente não têm regras para lidar com essas situações. Essas linguagens geralmente têm sistemas de tipos para evitar a compilação de programas que levam a um comportamento não especificado. E também existem linguagens que têm comportamento não especificado e não têm um sistema de tipos para evitar esses erros em tempo de compilação (se você escrever um programa que atinge um comportamento não especificado, ele pode lançar os mísseis).

Então:

Linguagens que especificam o que acontece em tempo de execução em cada caso (como adicionar um número a uma string) são chamadas de tipo dinâmico. As linguagens que evitam a execução de programas com erros em tempo de compilação são digitadas estaticamente. Linguagens que não especificam o que acontece e também não possuem um sistema de tipos para evitar erros são chamadas de digitação fraca.

Então o Java é estaticamente tipado? Sim, porque seu sistema de tipos não permite subtrair uma string de um número. Não, porque permite que você divida por zero. Você pode evitar a divisão por zero em tempo de compilação com um sistema de tipos. Por exemplo, criando um tipo de número que não pode ser zero (por exemplo, NonZeroInt), e só permite a divisão por números que têm esse tipo.

Então C é fortemente tipado ou fracamente tipado? C é fortemente tipado porque o sistema de tipos não permite alguns erros de tipo. Mas é mal digitado em outros casos, quando é indefinido o que acontece (e o sistema de tipo não protege você).


Eu gosto do seu alinhamento de dinâmico e estático como formas de forte e fraco. No entanto, não tenho certeza se entendi seu ponto sobre sistemas tipados estaticamente parando a divisão por zero. Se meu tipo estaticamente intreceber um valor do usuário ou argumentos de linha de comando ou um arquivo, não há nada que o compilador possa fazer para impedir que seja zero!
Rikki

1
Existem sistemas de tipo estático que evitam isso, mas a maioria das linguagens são fracamente ou dinamicamente "tipadas" em relação à divisão por zero, porque é um comportamento indefinido (C) ou lançam uma exceção (Java).
Jules,

11

C é considerado como fracamente tipado, porque você pode converter qualquer tipo em qualquer outro tipo por meio de uma conversão, sem um erro do compilador. Você pode ler mais sobre o assunto aqui .


2
A Wikipedia é enganosa aqui. C é fortemente tipado, os tipos são muito válidos e o compilador irá barf se você errar, entretanto, C também oferece recursos para você contornar isso. Compare com linguagens como BCPL, que têm apenas um tipo de 'byte'.
gbjbaanb de

12
Digitar fracamente não significa que uma linguagem não tenha nenhum tipo, apenas significa que os tipos podem ser coagidos implicitamente de um tipo para outro. Compare com Python, uma linguagem fortemente tipada na qual você deve converter explicitamente os tipos com chamadas de função.
mipadi

ser capaz de lançar algo em C também contribui para que ele seja um tipo fraco. ?? Tenho essa dúvida para sempre
Suraj Jain

8

C é mais fortemente tipado que Javascript e menos fortemente tipado que Ada.

Eu diria que cai mais no lado fortemente tipado do continuum. mas outra pessoa pode discordar (mesmo que esteja errada).

Que tal isso para definitivo?


Foi uma resposta um tanto irônica. Mas elabore sobre o que está errado.
Michael Burr

1
Javascript é fortemente tipado. Simplesmente não é digitado estaticamente. Todas as verificações de tipo ocorrem em tempo de execução (dinâmico, não estático), mas ocorrem e o impedem de corromper a memória (um aspecto da tipagem forte).
encerramento de

5
Bem, como indica a excelente resposta de Norm Ramsey, "fortemente tipado" e "fracamente tipado" não são termos particularmente bem definidos. Além disso, na medida em que o Javascript é fortemente tipado, alguns podem acreditar que ("4" / ​​"2") sendo uma expressão Javascript válida pode indicar o contrário.
Michael Burr

5

C é considerado estaticamente tipado (você não pode ter uma mudança de variável de int para float). Depois que uma variável é declarada, ela é travada dessa maneira.

Mas ele é considerado fracamente tipado porque os tipos podem ser invertidos.

O que é 0? '\ 0', FALSE, 0.0, etc.

em muitas linguagens você não pode dizer IF (variável) porque as condições só aceitam valores booleanos de expressões booleanas. Estes são digitados com mais força. O mesmo se aplica a ir entre caracteres e inteiros.

basicamente c tem dois tipos de dados simples principais, inteiros e números de ponto flutuante (embora várias precisões). Todo o resto, booleanos, enums (não é simples, mas se encaixa), etc. são implementados como um desses. Até os caracteres são basicamente inteiros.

Compare com outras linguagens onde existem tipos de string, tipos enum que só podem ser atribuídos aos valores definidos, tipos booleanos onde apenas expressões que geram booleanos ou verdadeiro / falso podem ser usadas.

Mas você pode argumentar que, em comparação com Perl, C é fortemente tipado. Portanto, é um daqueles argumentos famosos (vi vs emacs, linux vs windows, etc.). C # é mais forte do que C. Basicamente, você pode argumentar de qualquer maneira. E suas respostas provavelmente irão para os dois lados :) Além disso, alguns livros / páginas da web dirão que C está mal tipado, e alguns dirão que C é fortemente tipado. Se você acessar a wikipedia, a entrada C diz "digitação parcialmente fraca". Eu diria que, em comparação com Python, C é mal tipado. Portanto, Python / C #, C, Perl no continuum.


Explique o seu raciocínio de que Perl é menos fortemente tipado do que C.
user51568

imprimir "Testando" + 0 # perl fará 0; $ var = "string"; $ var = 1; $ var = 123,4; Que tipo de variável é?
Cervo

Em C char * test = "testando"; printf (teste + 0); ainda será uma string, só que em C o índice mudará se em vez de zero eu usar um número. Ainda é muito fraco, mas um pouco mais forte que o perl. char * test; teste = 0; teste = 123,4; test = "c"; ... meu compilador gera erros
Cervo

o erro diz que um elenco é necessário. Ainda assim, é um pouco mais forte de verificação de tipo do que Perl, então, no continuum, eu tenho que dizer que C é mais fortemente tipado do que Perl. Você ainda pode fazer o teste = (char *) e então usar 0, 123,4, 'C', etc. Mas é um erro apenas fazer isso.
Cervo

4

Muitas respostas boas aqui. Quero trazer à tona um ponto importante do Real World Haskell :

É útil estar ciente de que muitas comunidades linguísticas têm suas próprias definições de “tipo forte”. No entanto, falaremos brevemente e em termos gerais sobre a noção de força nos sistemas de tipos.

(recorte)

Os fogos de artifício em torno dos sistemas de tipos têm suas raízes no inglês comum, onde as pessoas atribuem noções de valor às palavras “fraco” e “forte”: geralmente pensamos na força como melhor do que na fraqueza. Muitos mais programadores falam inglês simples do que o jargão acadêmico, e muitas vezes os acadêmicos realmente estão atirando em qualquer tipo de sistema que não lhes agrade. O resultado geralmente é aquele passatempo popular da Internet, uma guerra de insultos.

Portanto, observe as respostas sobre C e C ++, mas lembre-se de que 'forte' e 'fraco' não mapeiam para 'bom' e 'ruim'.


4

De acordo com Dennis Ritchie ( criador de C ) e Brian Kernighan, C não é uma linguagem fortemente tipada. As linhas a seguir são do livro A linguagem de programação C, página 3, parágrafo 5

C não é uma linguagem fortemente tipada, mas conforme ela evoluiu, sua verificação de tipo foi fortalecida.


3

Na minha opinião, C / C ++ são fortemente tipados. Os tipos de hacks que permitem a conversão de tipos (void *) existem por causa da proximidade do C com a máquina. Em outras palavras, você pode chamar comandos assembler de Pascal e manipular ponteiros e Pascal ainda é considerado uma linguagem fortemente tipada. Você pode chamar executáveis ​​assembler e C de Java por meio de JNI, mas isso não torna o Java com tipos fracos.

C apenas tem assembler "embutido" nele com ponteiros brutos e tal.


3

O termo fortemente tipado não tem uma definição acordada. Portanto, a menos que você defina o que entende por "fortemente tipado", é impossível responder à sua pergunta.

Na minha experiência, os termos "fortemente tipado" e "fracamente tipado" são usados exclusivamente por trolls, porque sua falta de definições permite que os trolls os redefinam no meio da argumentação para se adequar à sua agenda. Exceto para iniciar flamewars, esses termos são praticamente inúteis.

Você também pode querer dar uma olhada em Quais são os principais aspectos de uma linguagem fortemente tipada? aqui no StackOverflow.


3
Discordo. "Fortemente tipado" significa que é possível determinar o tipo de dados de um valor e apenas as operações apropriadas para esse tipo são permitidas. Endereço "dinamicamente" e "estaticamente" quando essa determinação pode ser feita.
joel.neely

2
Você fazer perceber a ironia de tentar refutar a afirmação de que não há como acordado definição introduzindo ainda uma outra definição, certo?
Jörg W Mittag

1
@Jorg: Não estou tentando apresentar outro; apenas mencionando aquele comumente usado nos círculos em que me movo.
joel.neely

1

Existe um continuum com múltiplas vias paralelas entre "fracamente tipado" e "fortemente tipado", dois termos que nem mesmo estão bem definidos.

C é tipificado estaticamente , no sentido de que o compilador sabe qual é o tipo declarado de cada variável local e membro de estrutura.

Linguagens digitadas dinamicamente podem ainda ser fortemente tipadas, se cada objeto tiver um tipo específico, mas não há como o compilador saber esse tipo.


0

Qual é o motivo da sua consulta? A razão de eu perguntar é que essa é uma pequena diferença e seu uso particular de "fortemente tipado" pode precisar de mais ou menos esclarecimento. Eu definitivamente diria que Java e outras linguagens têm restrições mais rígidas na conversação de tipo implícito.


Principalmente curiosidade, mas estou me candidatando a uma posição C e gostaria de saber caso me questionem sobre isso.
Sydius

Então, provavelmente, a resposta mais longa que fornece as nuances do que "fortemente tipado" é a melhor abordagem, em vez de apenas dizer "sim" ou "não".
BobbyShaftoe

0

É difícil fornecer uma resposta concreta quando não existe uma definição concreta de "fortemente tipado". Eu diria que C é fortemente tipado em que cada variável e cada expressão tem um tipo, mas fracamente tipado em que permite alterar os tipos usando casts e reinterpretar a representação de um tipo como outro.


Existe uma defesa oficial. para fortemente tipado. Diz que um sistema. é ST quando se garante que não há erro de tipo de tempo de execução. Exemplo: ML, Haskell. Isso é útil para fazer o sistema omitir tags de tipo dentro dos objetos e, no entanto, aplicar os operadores nos tipos corretos. Porque sabemos antes da execução que não há necessidade de tags nos objetos. Como C tem elenco e acesso de ponteiro para memorando arbitrário, C não é st
alinsoar

0

Eu diria que C é tão fortemente tipado quanto dita seu compilador / plataforma. Por exemplo, se você estiver construindo em uma plataforma estrita, cancelar a referência de um ponteiro de trocadilho provavelmente irá falhar:

void m_free(void **p)
{
        if (*p != NULL) {
                free(*p);
                *p = NULL;
        }
}

....
char *str = strdup("foo");
m_free((void **) &foo);

Agora, se você dissesse ao compilador para pular o aliasing estrito, não seria um problema, mas não muito portátil. Portanto, nesse sentido, forçar os limites da linguagem é possível, mas provavelmente não é a melhor ideia. Isso vai um passo além do casting típico, ou seja, o casting int tão longo e realmente mostra uma das possíveis armadilhas do vazio.

Então, eu diria que C é basicamente digitado estritamente, mas seus vários compiladores presumem que o programador sabe melhor e permite alguma flexibilidade. Isso realmente depende do compilador, alguns não perceberiam esse potencial ops. Nesse sentido, o compilador escolhido realmente desempenha um papel ao responder à pergunta. O que é correto geralmente difere do que seu compilador permitirá que você faça.



-1

Não fortemente tipado.

Considere o que o seguinte protótipo de função informa sobre os tipos de dados dos argumentos:

void func (int n, char ch, ...);

Nada. Portanto, sugiro que a tipificação forte não se aplica aqui.


Hã? Ele informa que existe um int, seguido por um char, seguido por qualquer número de argumentos de qualquer tipo. Isso não é "nada".
Lawrence Dol

O ... não diz nada sobre os tipos de argumentos que são passados. É verdade que o tipo da função em si é conhecido. Isso é o que o Software Monkey disse.
Johannes Schaub - litb de

Esses "vários argumentos de qualquer tipo" são do que estou falando. Uma corrente é tão forte quanto seu elo mais fraco.
joel.neely

-3

Eu diria que é fortemente tipos, pois cada expressão tem um tipo que não é uma função de seu valor; ei pode ser conhecido antes do tempo de execução.

OTOH Não tenho certeza se essa é a descrição correta de fortemente tipado. A única afirmação mais forte que vejo razão para uma linguagem fazer seria a garantia de que você não pode subverter o sistema de tipos em tempo de execução por meio de reinterpretar conversões de tipos, uniões, chamadas para outras linguagens, ponteiros, linguagem assembly, etc. Linguagens como esta existem, mas são tão deficientes que parecem não ser de muito interesse para programadores fora da alta segurança e da academia. Como apontado por alguém, para realmente fazer isso direito, você começa a precisar ter tipos como nonZeroInte outros enfeites. Que nojo.


3
O que não é? Minha definição de fortemente tipado ou C?
BCS de
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.