¿Por qué C usa el asterisco para los punteros? [cerrado]

21

Ahora estoy aprendiendo sobre C.

Me resulta extraño que los creadores hayan elegido el asterisco ( *) como símbolo de los punteros en lugar de un símbolo que en realidad se parece a un puntero ( ->).

Teniendo en cuenta lo confusos que pueden ser la desreferenciación y los punteros de función, ¿hay alguna razón histórica o incluso práctica para usar el asterisco?

Noob Saibot
fuente
10
Tenga en cuenta que ->se está utilizando en el lenguaje C como operador de desreferencia, al acceder a los campos en una estructura: struct_pointer->fieldque es la abreviatura de (*struct_pointer).field.
amon
@amon: Solo se aplica a la structsdesreferenciación, lo que me pareció extraño. Es un símbolo de puntero, ¿verdad? ¿Por qué no ( <-) para desreferenciar? ¿Soy realmente el único que piensa de esta manera?
Noob Saibot
1
Dadas las dos excelentes respuestas en esta pregunta, incluida una con una respuesta directa del diseñador del lenguaje, es difícil justificar realmente el cierre como "basado en la opinión". Por lo tanto, he nominado para reabrir.
Jules
En mi humilde opinión, el estilo Pascal es mejor. ^se usa y puede pensarse en una flecha girada y leerse como "apuntar a", el mismo significado ->pero más corto. ^integersignifica "puntero al entero" para la declaración de tipo, y var^significa "la memoria varapunta a" para desreferenciar. La posición del símbolo es más lógica que C cuando se lee de izquierda a derecha, lo que siempre pone después del tipo y antes del nombre de la variable. Pascal también usa @para tomar direcciones, que es mejor que &, porque @vares "la dirección en la que se encuentra var"
phuclv

Respuestas:

59

¿Por qué C usa el asterisco para los punteros?

Simplemente, porque B lo hizo.

Como la memoria es una matriz lineal, es posible interpretar el valor en una celda como un índice en esta matriz, y BCPL proporciona un operador para este propósito. En el idioma original se deletreaba rv, y más tarde !, mientras que B usa el unario *. Por lo tanto, si pes una celda que contiene el índice de (o la dirección de), o apunta a) otra celda, se *prefiere al contenido de la celda apuntada, ya sea como un valor en una expresión o como el objetivo de una asignación.

Del desarrollo del lenguaje C

Eso es. En este punto, la pregunta es tan poco interesante como "¿por qué Python 3 usa .para llamar a un método? ¿Por qué no ->?" Bueno ... porque Python 2 usa .para llamar a un método.

Rara vez existe un lenguaje de la nada. Tiene influencias y se basa en algo que vino antes.


Entonces, ¿por qué B no utilizó !para desreferenciar un puntero como lo hizo su predecesor BCPL?

Bueno, BCPL era un poco prolijo. En lugar de &&o ||BCPL utilizado logandy logor. Esto se debió a que la mayoría de los teclados no tienen teclas o no y en realidad era la palabra NEQV(consulte el Manual de referencia de BCPL ).

B parece haber sido parcialmente inspirado para ajustar la sintaxis en lugar de tener palabras largas para todos estos operadores lógicos que los programadores hicieron con bastante frecuencia. Y así, la !desreferencia se convirtió en *algo que !podría usarse para la negación lógica. Tenga en cuenta que hay una diferencia entre el *operador unario y el *operador binario (multiplicación).


Bueno, ¿qué hay de otras opciones, como ->?

El ->fue tomado para azúcar sintáctico alrededor de las deserciones de campo struct_pointer->fieldque es(*struct_pointer).field

Otras opciones como <-podrían crear análisis ambiguos. Por ejemplo:

 foo <- bar

¿Es eso para ser leído como:

(foo) <- (bar)

o

(foo) < (-bar)

Es muy probable que crear un operador unario que esté compuesto por un operador binario y otro operador unario tenga problemas, ya que el segundo operador unario puede ser un prefijo para otra expresión.

Además, de nuevo es importante tratar de mantener las cosas que se escriben con frecuencia al mínimo. Me odio a tener que escribir:

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

Esto también se vuelve difícil de leer.

Otros personajes podrían haber sido posibles (el @no se usó hasta que el Objetivo C se lo apropió ). Aunque de nuevo, esto va al núcleo de 'C utiliza *porque B lo hizo'. ¿Por qué no usó B @? Bueno, B no usó todos los personajes. No había ningún bppprograma (compare cpp ) y otros caracteres estaban disponibles en B (como el #que luego usó cpp).

Si puedo arriesgarme a adivinar por qué, es por dónde están las llaves. De un manual sobre B :

Para facilitar la manipulación de direcciones cuando parece aconsejable, B proporciona dos operadores de direcciones unarios, *y &. &es el operador de dirección, también lo &xes la dirección de x, suponiendo que tenga una. *es el operador de indirección; *xsignifica "usar el contenido de x como una dirección".

Tenga en cuenta que &es shift-7 y *shift-8. Su proximidad entre sí puede haber sido una pista para el programador sobre lo que hacen ... pero eso es solo una suposición. Uno tendría que preguntarle a Ken Thompson por qué se hizo esa elección.


Entonces, ahí lo tienes. C es así porque B era. B es así porque quería cambiar de cómo era BCPL.

Comunidad
fuente
2
...¡increíble! Esta es una gran respuesta, @MichaelT! Me mostraste razones tanto históricas como prácticas, e incluso cosas que no entendía pero que podía investigar. Gracias. +1
Noob Saibot
@NoobSaibot La elección del personaje no es tan importante como el hecho de que el operador es un operador de anteponer en lugar de posponer. Esto requiere muchos parens adicionales (aunque el azúcar sintáctico -> ayuda) que puede conducir a errores tontos pero molestos incluso para un programador de C ++ experimentado.
Trixie Wolf
1
También puede mencionar que C encontró un uso para casi todos los caracteres de puntuación Ascii. No hubo muchos repuestos. Supongo @que habría sido otra posibilidad.
david.pfx
1
@ david.pfx Me he expandido en eso, aunque no fue C quien tomó esa decisión ... fue B. Y, bueno, adiviné por qué (proximidad del teclado &y *). B tampoco lo usó, #así que hubo algunos repuestos más por entonces ... también hay $.
1
@ david.pfx El tutorial B que encontré fue escrito por BW Kernighan. Desafortunadamente, a Dennis Ritchie ya no se le puede preguntar (falleció en octubre del '11), mientras que Kernighan aparentemente sigue siendo profesor en el Departamento de CS en Princeton. Ken Thompson (el otro creador de B) trabaja en Google ... También puede haber problemas con algunos teclados (indicados por los trigrafos de C para lo que podríamos considerar teclas comunes) lo que sugiere que no todos estaban disponibles ( No estoy seguro si '@' fue).
55

Un estudiante me preguntó si &y me *eligieron porque estaban uno al lado del otro en el teclado (algo que nunca antes había notado). Muchas búsquedas en Google me llevaron a la documentación de B y BCPL, y a este hilo. Sin embargo, no pude encontrar mucho en absoluto. Parecía que había muchas razones para *B, pero no pude encontrar nada &.

Entonces, siguiendo la sugerencia de @ MichaelT, le pregunté a Ken Thompson:

De: Ken Thompson <[email protected]>

cerca del teclado: no.
c copiado de b so & y * son iguales allí.
b consiguió * de idiomas anteriores: algunos ensamblados,
bcpl y creo que pl / 1.
Creo que usé & porque el nombre (ampersand)
suena como "dirección". b fue diseñado para ejecutarse con
un teletipo modelo 33 teletipo. (Código de 5 bits en baudios)
por lo que se restringió el uso de símbolos.

chmullig
fuente
19
+1 por contactar a Ken Thompson e informar aquí.
stakx