Forma correcta de declarar variables de puntero en C / C ++ [cerrado]

91

Noté que algunas personas usan la siguiente notación para declarar variables de puntero.

(a) char* p;

en vez de

(b) char *p;

Yo uso (b). ¿Qué es lo racional detrás de la notación (a)? La notación (b) tiene más sentido para mí porque el puntero de carácter no es un tipo en sí mismo. En cambio, el tipo es carácter y la variable puede ser un puntero al carácter.

char* c;

Parece que hay un tipo char * y la variable c es de ese tipo. Pero, de hecho, el tipo es char y * c (la ubicación de memoria señalada por c) es de ese tipo (char). Si declara varias variables a la vez, esta distinción se vuelve obvia.

char* c, *d;

Esto se ve raro. Tanto c como d son el mismo tipo de punteros que apuntan a un carácter. En esto ya que el próximo parece más natural.

char *c, *d;

Gracias.

Keeda
fuente
7
¿Qué quiere decir que el puntero char no es un tipo? ¿Estás diciendo que un puntero no es un tipo?
Benjamin Lindley
1
Creo que es una cuestión de preferencia a menos que esté viendo una guía de estilo en particular (es decir, su empresa puede tener un cierto estándar de codificación que debe seguir). Tiendo a mezclarlo entre la opción by algo en el medio. A veces siento que no se char *tve bien, así que puedo hacerlo char * t;. Sin embargo, también lo he visto con frecuencia char* t;.
RageD
1
Además, su razonamiento "el tipo es char y * c (la ubicación de memoria señalada por c) es de ese tipo (char)" parecería indicar que se está declarando un char, cuando en realidad no lo hay. Si se trata como tal, como a veces lo hacen los principiantes, seguramente conducirá a violaciones de acceso a la memoria.
Benjamin Lindley
1
Ambos son todavía suficientemente descriptivo, (b) muestra * p es de tipo chary (a) muestra p es unpointer to a char
Una Persona
1
Con más de una década de experiencia en la industria, hoy fue la primera vez que surgió esto, y solo en la lectura de artículos de otros profesionales de la industria. Entonces, obviamente, nunca he tenido una conversación tan religiosa sobre estos como la que he tenido con pestañas v espacios, comentarios por def o dec, o cualquiera de los otros temas de "es bueno no tener nada más importante sobre qué discutir". . Siendo esa mi perspectiva, he preferido, tan tarde en el juego de mi carrera, ir con "char * p" la mayoría de las veces. Sí, espacio antes, espacio después. Principalmente, como lo encuentro, reduce los errores, ya que hace que el puntero sea más obvio.
Kit10

Respuestas:

102

Bjarne Stroustrup dijo:

La elección entre "int * p;" y "int * p;" no se trata de lo que está bien y lo que está mal, sino de estilo y énfasis. C enfatizó expresiones; Las declaraciones a menudo se consideraban poco más que un mal necesario. C ++, por otro lado, tiene un gran énfasis en los tipos.

Un "programador típico de C" escribe "int * p;" y lo explica "* p es lo que es el int" enfatizando la sintaxis, y puede apuntar a la gramática de declaración de C (y C ++) para argumentar a favor de la corrección del estilo. De hecho, el * se une al nombre p en la gramática.

Un "programador típico de C ++" escribe "int * p;" y explica que "p es un puntero a un int" enfatizando el tipo. De hecho, el tipo de p es int *. Claramente prefiero ese énfasis y lo veo como importante para usar bien las partes más avanzadas de C ++.

Fuente: http://www.stroustrup.com/bs_faq2.html#whitespace

Recomendaría el último estilo porque en la situación en la que está declarando varios punteros en una sola línea (su cuarto ejemplo), tener el asterisco con la variable será lo que está acostumbrado.

Veintiuna
fuente
34
Otros recomiendan nunca declarar varios objetos en la misma declaración. :-)
Bo Persson
5
Enfatizo la lógica detrás de la sintaxis, por lo que prefiero:, es int *pdecir: cuando pse desreferencia, obtengo un int. Entonces, múltiples declaraciones separadas por tienen ,sentido: int *p, *q, r(cuando po qse desreferencia, obtengo una int, cuando rse hace referencia, obtengo una int). Además, la sintaxis del puntero de función tiene sentido: int (*f)()(cuando fse desreferencia y se llama, obtengo un int). Y esto tiene sentido: int *p, (*f)().
Druesukker
2
Esto me ayudó a darme cuenta de que hay validez en el otro lado del argumento. Siendo, sobre todo, un programador de alto nivel, hago hincapié en el tipo; y prefiero int*. Para mí, int *p, (*f)()no tiene mucho sentido, pero puedo ver cómo sería para algunas personas en algunas situaciones.
Asimilador
1
@Druesukker, creo que su declaración tiene más sentido que cualquiera de las anteriores.
Muntashir Akon
1
@Druesukker Pero la lógica no funciona exactamente para void*(y no funciona en absoluto para referencias de C ++).
jamesdlin
57

Yo personalmente prefiero colocar el *con el resto del tipo.

char* p;  // p is a pointer to a char.

La gente argumentará "pero luego se char* p, q;vuelve engañosa", a lo que yo digo, "así que no hagas eso".

ikegami
fuente
Muy buen argumento para el char * p; elección :) No me importa ninguno de ellos siempre que no sea difícil de leer como el ejemplo que mostró, en cuyo caso no deberían estar haciendo eso.
Jesus Ramos
1
¿Y cuándo quiere generar el valor? Lo haces cout << *p;. Entonces, ¿por qué no poner la estrella antes p durante la declaración *p:? En mi opinión, sería menos confuso.
user1170330
13
@ user1170330, porque en un lugar es parte de la definición de tipo y es un operador de desreferencia en el otro. No hay relación. En todo caso, es bueno que se vean diferentes, ya que diferentes cosas deberían verse diferentes.
ikegami
32

No hay diferencia en cómo escribir. Pero si desea declarar dos o más punteros en una línea, es mejor usar la variante (b), porque está claro lo que desea. Mira abajo:

int *a;
int* b;      // All is OK. `a` is pointer to int ant `b` is pointer to int
char *c, *d; // We declare two pointers to char. And we clearly see it.
char* e, f;  // We declare pointer `e` and variable `f` of char type.
             // Maybe here it is mistake, maybe not. 
// Better way of course is use typedef:
typedef char* PCHAR;
PCHAR g, h;  // Now `g` and `h` both are pointers.
// If we used define construction for PCHAR we'd get into problem too.
George Gaál
fuente
5
typedefno es una mejor manera "por supuesto". Algunas personas pueden preferirlo, pero es problemático si hay varias personas trabajando con su código. Si no estoy acostumbrado PCHAR, podría escribir algo como PCHAR *p;, que sería un char**y no lo que pretendo. En general, si quieres un char**, tendrías que escribir PCHAR*o definir un nuevo tipo, y luego comienza a volverse estúpido.
BlackJack
3
Si se necesita algún tipo de puntero complejo, como un puntero, para funcionar, es muy buena idea hacer typedefs. En este caso, hacen que el código sea mucho más simple. Por otro lado, el uso de PCHAR es un ejemplo más sintético que la práctica diaria. Pero claramente hace lo que quieres. y luego comienza a volverse estúpido. Dirija todas las quejas a Stroustrup :-)
George Gaál
Si escribió PCHAR * p para definir un puntero a char, sería obvio que no sabe lo que está haciendo y no leyó el tipo def. La respuesta está en su opinión. Hay otro beneficio para typedef; en C se trata de las formas fáciles de hacer que las cosas sean opacas. públicamente tener el símbolo definido como VOID ptr, en privado el type def es otra cosa ... Prefiero ajustar una typedef de vez en cuando y luego ajustar todo a lo largo del código cuando cambiamos algo sobre uno de los tipos ... pero C ++ 11 aborda gran parte de eso con auto
UpAndAdam
Para alguien que intenta volver a jugar con C ++ cinco años después de la universidad, esta es una de las mejores respuestas.
Panzercrisis
10

El compromiso es

char * p;

Usos de K&R

char *p;

Depende de usted, a menos que esté siguiendo un estándar de codificación; en ese caso, debe seguir lo que hacen los demás.

jnnnnn
fuente
4
Aprendí de la manera difícil que char * x, y no significa que y es un char *. Ahora puedo ver por qué K&R sigue dicho estilo.
Rahul Kadukar
¿Qué es K&R y por qué importa lo que utilice una única fuente de código? Yo uso char* p;. es una cuestión de estilo, no de convenciones o reglas. para mí tiene más sentido que p sea de tipo char*, por lo que obviamente el * debería estar con el tipo.
FalcoGer
@FalcoGer He agregado un enlace para K&R. No importa lo que utilice una única fuente de código. Su equipo podría molestarse con usted si no sigue su estándar porque los está haciendo trabajar más duro para comprender su código. En estos días, espero que los equipos lo estén usando de clang-formattodos modos.
jnnnnn
2

Todo es una cuestión de preferencia, personalmente en proyectos en los que veo el carácter * Tiendo a declarar varios punteros en líneas separadas. No existe una forma "correcta" real de hacer esto y todo se reduce a las preferencias. Algunos dicen que es más fácil de leer (a) mientras que otros dicen que (b) es más fácil declarar más variables del mismo tipo en la misma línea.

Encuentro que (b) es más común, y en algunos casos he visto

char * a;

o algo como esto. De nuevo preferencia. Lo que sea con lo que se sienta cómodo o cualquier uso del proyecto en el que estoy trabajando, lo usaré (a menos que lo escriba yo mismo, en cuyo caso uso (a))

Jesús Ramos
fuente