Por que C usa o asterisco para ponteiros? [fechadas]

21

Só agora estou aprendendo sobre C.

Acho estranho que os criadores tenham escolhido o asterisco ( *) como símbolo para ponteiros, em vez de um símbolo que realmente se parece com um ponteiro ( ->).

Considerando como podem ser confusos os desvios de referência e os indicadores de função, existe uma razão histórica ou mesmo prática para usar o asterisco?

Noob Saibot
fonte
10
Observe que ->está sendo usado na linguagem C como um operador de desreferência - ao acessar campos em uma struct:, struct_pointer->fieldque é a abreviação de (*struct_pointer).field.
amon
@ amon: Aplica-se apenas a structsdesreferenciamento, o que me pareceu estranho. É um símbolo de ponteiro, certo? Por que não ( <-) para desreferenciar? Eu sou realmente o único que pensa assim?
Noob Saibot
1
Dadas as duas excelentes respostas nesta pergunta, incluindo uma com uma resposta diretamente do designer de idiomas, é difícil justificar o fechamento como "baseado em opiniões". Por isso, fui indicado para reabrir.
Jules
O estilo IMHO Pascal é melhor. ^é usado e pode ser pensado em uma seta girada e lido como "apontar para", mesmo significado, ->porém mais curto. ^integersignifica "ponteiro para número inteiro" para declaração de tipo e var^significa "a memória varaponta para" para desreferenciação. A posição do símbolo é mais lógica que C ao ler da esquerda para a direita, que sempre coloca após o tipo e antes do nome da variável. Usos também Pascal @para a tomada de endereço, que é melhor do que &, porque @varé "o endereço em que var está localizado"
phuclv

Respostas:

59

Por que C usa o asterisco para ponteiros?

Simplesmente - porque B sim.

Como a memória é uma matriz linear, é possível interpretar o valor em uma célula como um índice nessa matriz, e o BCPL fornece um operador para essa finalidade. No idioma original, foi escrito rv, e mais tarde !, enquanto B usa o unário *. Portanto, se pé uma célula que contém o índice de (ou endereço de) ou o ponteiro para outra célula, *prefere-se ao conteúdo da célula apontada, como um valor em uma expressão ou como o destino de uma atribuição.

Do desenvolvimento da linguagem C

É isso aí. Nesse ponto, a pergunta é tão desinteressante quanto "por que o python 3 usa .para chamar um método? Por que não ->?" Bem ... porque o Python 2 costuma .chamar um método.

Raramente existe uma linguagem do nada. Ele tem influências e é baseado em algo que veio antes.


Então, por que B não usou !para remover o ponteiro de um ponteiro como o seu BCPL predecessor?

Bem, o BCPL era um pouco prolixo. Em vez de &&ou ||BCPL usado logande logor. Isso ocorreu porque a maioria dos teclados não possui teclas ou não é igual à palavra NEQV(consulte o Manual de referência da BCPL ).

B parece ter sido parcialmente inspirado para reforçar a sintaxe, em vez de ter palavras longas para todos esses operadores lógicos que os programadores faziam com bastante frequência. E assim !a desreferência se tornou *para que !pudesse ser usada para negação lógica. Observe que há uma diferença entre o *operador unário e o *operador binário (multiplicação).


Bem, e outras opções, como ->?

O ->foi levado para o açúcar sintático torno derefrences campo struct_pointer->fieldque é(*struct_pointer).field

Outras opções como <-poderiam criar análises ambíguas. Por exemplo:

 foo <- bar

Isso deve ser lido como:

(foo) <- (bar)

ou

(foo) < (-bar)

É muito provável que criar um operador unário composto por um operador binário e outro operador unário tenha problemas, pois o segundo operador unário pode ser um prefixo para outra expressão.

Além disso, é novamente importante tentar reduzir ao mínimo as coisas que estão sendo digitadas. Eu odiaria ter que escrever:

int main(int argc, char->-> argv, char->-> envp)

Isso também se torna difícil de ler.

Outros caracteres podem ter sido possíveis ( @não foram usados ​​até o Objetivo C se apropriar ). Porém, novamente, isso vai para o núcleo de 'C usa *porque B fez'. Por que B não usou @? Bem, B não usou todos os personagens. Não havia nenhum bppprograma (compare cpp ) e outros caracteres estavam disponíveis em B (como o #que mais tarde foi usado pelo cpp).

Se posso arriscar um palpite sobre o porquê - é por causa de onde estão as chaves. De um manual em B :

Para facilitar a manipulação de endereços quando parecer aconselhável, B fornece dois operadores de endereço unário, *e &. &é o operador de endereço, assim &xcomo o endereço de x, supondo que ele tenha um. *é o operador indireto; *xsignifica "use o conteúdo de x como endereço".

Observe que &é o turno-7 e o *turno-8. A proximidade entre eles pode ter sido uma dica para o programador sobre o que eles fazem ... mas isso é apenas um palpite. Alguém teria que perguntar a Ken Thompson sobre por que essa escolha foi feita.


Então, aí está. C é assim porque B era. B é assim porque queria mudar a forma como o BCPL era.

Comunidade
fonte
2
...impressionante! Esta é uma ótima resposta, @MichaelT! Você me mostrou razões históricas e práticas, e até coisas que eu não entendi direito, mas pude examinar. Obrigado. +1
Noob Saibot
@NoobSaibot A escolha do caractere não é tão importante quanto o fato de o operador ser um operador de pré-prefixo e não de pós-adipamento. Isso requer muitos parênteses extras (embora o açúcar -> sintático ajude), o que pode levar a erros tolos e irritantes, mesmo para um programador C ++ experiente.
Trixie Wolf
1
Você também pode mencionar que C encontrou um uso para quase todos os caracteres de pontuação Ascii. Não havia muitas peças de reposição. Eu acho @que teria sido outra possibilidade.
David.pfx
1
@ david.pfx Eu expandi isso - embora não tenha sido C que fez essa escolha ... foi B. E, bem, eu adivinhei o porquê (proximidade do teclado &e *). B também não usou, #então havia mais algumas peças de reposição por aí ... há também $.
1
@ david.pfx O tutorial B que encontrei foi escrito por BW Kernighan. Infelizmente, Dennis Ritchie não pode mais ser solicitado (faleceu em outubro de 11), enquanto Kernighan aparentemente ainda é professor no Departamento de CS de Princeton. Ken Thompson (o outro criador de B) trabalha no Google ... Também pode ter havido um problema com alguns teclados (indicados pelos trigramas de C para o que consideraríamos teclas comuns) sugerindo que nem todos estavam disponíveis ( Não tenho certeza se '@' foi).
55

Um aluno me perguntou se &e fui *escolhido porque eles estavam próximos um do outro no teclado (algo que eu nunca havia notado antes). Muita pesquisa no Google me levou à documentação B e BCPL e a esta discussão. No entanto, não consegui encontrar muita coisa. Parecia que havia muitas razões para *B, mas não consegui encontrar nada &.

Então, seguindo a sugestão de @ MichaelT, perguntei a Ken Thompson:

De: Ken Thompson <[email protected]>

próximo no teclado: não.
c copiado de b então & e * são os mesmos lá.
b obteve * de idiomas anteriores - alguns assembly,
bcpl e acho pl / 1.
acho que usei e porque o nome (e comercial)
soa como "endereço". b foi projetado para ser executado com
um teletipo modelo 33. (Código baud-o de 5 bits),
portanto, o uso de símbolos era restrito.

chmullig
fonte
19
+1 por entrar em contato com Ken Thompson e relatar aqui.
stakx