punteros - ¿Por qué es el asterisco antes del nombre de la variable, en lugar de después del tipo?
punteros c++ (11)
Algo que nadie ha mencionado aquí hasta ahora es que este asterisco es en realidad el " operador de desreferencia " en C.
*a = 10;
La línea de arriba no significa que quiera asignar 10
a a
, significa que quiero asignar 10
a la ubicación de memoria a
apuntan. Y nunca he visto a nadie escribiendo
* a = 10;
¿Tienes? Entonces, el operador de eliminación de referencias casi siempre se escribe sin espacio. Esto es probablemente para distinguirlo de una multiplicación dividida en varias líneas:
x = a * b * c * d
* e * f * g;
Aquí *e
sería engañoso, ¿no?
Bien, ahora, ¿qué significa realmente la siguiente línea?
int *a;
La mayoría de la gente diría:
Significa que a
es un puntero a un valor int
.
Esto es técnicamente correcto, a la mayoría de la gente le gusta ver / leer de esa manera y esa es la forma en que los estándares C modernos lo definirían (tenga en cuenta que el lenguaje C es anterior a todos los estándares ANSI e ISO). Pero no es la única forma de verlo. También puede leer esta línea de la siguiente manera:
El valor desreferenciado de a
es de tipo int
.
De hecho, el asterisco en esta declaración también se puede ver como un operador de desreferencia, que también explica su ubicación. Y que a
es un puntero realmente no está declarado en absoluto, está implícito por el hecho de que lo único que realmente puede desreferenciar es un puntero.
El estándar C solo define dos significados para el operador *
:
- operador indirecto
- operador de multiplicación
Y la indirección es solo un significado único, no hay un significado adicional para declarar un puntero, solo hay indirección, que es lo que hace la operación de desreferencia, realiza un acceso indirecto, por lo que también dentro de una declaración como int *a;
esto es un acceso indirecto ( *
significa acceso indirecto) y, por lo tanto, la segunda afirmación anterior está mucho más cerca del estándar que la primera.
¿Por qué la mayoría de los programadores C nombran variables como esta?
int *myVariable;
en lugar de esto:
int* myVariable;
Ambos son validos Me parece que el asterisco es una parte del tipo, no una parte del nombre de la variable. ¿Alguien puede explicar esta lógica?
Ellos son EXACTAMENTE equivalentes. Sin embargo, en
int *myVariable, myVariable2;
Parece obvio que myVariable tiene tipo int * , mientras que myVariable2 tiene tipo int . En
int* myVariable, myVariable2;
Puede parecer obvio que ambos son de tipo int * , pero eso no es correcto ya que myVariable2
tiene tipo int .
Por lo tanto, el primer estilo de programación es más intuitivo.
En K & R, colocan el operador del puntero al lado del nombre de la variable en lugar del tipo. Personalmente, considero que ese libro es la máxima autoridad / biblia de C. También proviene de un fondo de Objective-C, sigo la * convención de nombre.
Eso es solo una cuestión de preferencia.
Cuando lee el código, es más fácil distinguir entre variables y punteros en el segundo caso, pero puede generar confusión cuando coloca variables y punteros de un tipo común en una sola línea (que a menudo se desalienta por las pautas del proyecto, porque disminuye la legibilidad).
Prefiero declarar punteros con su correspondiente signo al lado del nombre de tipo, por ejemplo
int* pMyPointer;
Para declarar múltiples punteros en una línea, prefiero int* a, * b;
que más intuitivamente declara "a" como un puntero a un número entero, y no mezcla estilos cuando también declara "b". Como alguien dijo, no declararía dos tipos diferentes en la misma declaración de todos modos.
Porque * se une más a la variable que al tipo:
int* varA, varB; // This is misleading
Sin embargo, incluso las mejores declaraciones de una sola línea me parecen contra-intuitivas, porque * es parte del tipo. Me gusta hacer esto en su lugar:
int* varA;
int varB;
Como de costumbre, cuanto menos compacte su código, más legible es. ;)
Porque tiene más sentido cuando tienes declaraciones como:
int *a, *b;
Si lo miras de otra manera, *myVariable
es de tipo int
, lo que tiene sentido.
Un gran gurú dijo una vez: "Léelo por el camino del compilador, debes hacerlo".
http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835
De acuerdo, esto fue sobre el tema de la colocación de const, pero la misma regla se aplica aquí.
El compilador lo lee como:
int (*a);
no como:
(int*) a;
Si adquiere el hábito de colocar la estrella junto a la variable, hará que sus declaraciones sean más fáciles de leer. También evita los ojos como:
int* a[10];
Voy a dar un paso aquí y decir que hay una respuesta directa a esta pregunta , tanto para las declaraciones de variables como para los tipos de parámetros y de retorno, que es que el asterisco debe ir junto al nombre: int *myVariable;
. Para apreciar por qué, mira cómo declaras otros tipos de símbolos en C:
int my_function(int arg);
para una función;
float my_array[3]
para una matriz.
El patrón general, al que se hace referencia como declaración después del uso , es que el tipo de símbolo se divide en la parte anterior al nombre, y las partes alrededor del nombre, y estas partes alrededor del nombre imitan la sintaxis que usaría para obtener un valor del tipo de la izquierda:
int a_return_value = my_function(729);
float an_element = my_array[2];
y: int copy_of_value = *myVariable;
.
C ++ lanza una llave en los trabajos con referencias, porque la sintaxis en el punto donde usas referencias es idéntica a la de los tipos de valores, por lo que podrías argumentar que C ++ toma un enfoque diferente de C. Por otro lado, C ++ conserva el mismo comportamiento de C en el caso de los punteros, por lo que las referencias realmente se destacan como las extrañas en este aspecto.
Ya respondí una pregunta similar en CP, y, como nadie mencionó eso, también aquí debo señalar que C es un lenguaje de formato libre , cualquiera que sea el estilo que elijas está bien, mientras que el analizador puede hacer una distinción de cada token. Esta peculiaridad de C dio lugar a un tipo de concurso muy especial llamado C ofuscación concurso .