2012-01-20 11 views
11

Cuando declarando punteros en C, hay 2 (edit: 3) variantes:¿Existe una convención para las declaraciones de puntero en C?

Variante A:
int* ptr;

Variante B:
int *ptr;

Variante C:
int * ptr;

  • En A, el operador de direccionamiento indirecto se ha agregado al tipo.
  • En B, el operador de direccionamiento indirecto se ha antepuesto a la variable.
  • En C, el operador indirecto se coloca libremente entre el tipo y la variable.

La forma en que se declara un puntero difiere según el tipo de documentación que leo. Algunos autores parecen tener preferencia por ciertas variantes, otros usan varios.

  • ¿Es correcto suponer que no hay diferencia en la funcionalidad entre las diferentes variantes?
  • En caso afirmativo, ¿existe una convención para la variante que se debería usar en C?
+3

No sé por qué la gente vota para cerrar esto.Suena como una pregunta legítima para mí, pero luego solo he estado pirateando a C desde 1980. –

+1

@ PeterRowell: el único problema con este tipo de preguntas triviales es que uno puede encontrar la respuesta en línea con google o cualquier otra búsqueda motor en cuestión de segundos. Y cualquier libro decente sobre C debe explicar esto también. ¿Por qué no usarlos? No voté para cerrarlo, sin embargo. –

+1

posible duplicado de [¿Importa dónde coloque el asterisco al declarar punteros en C++?] (Http://stackoverflow.com/questions/5449908/does-it-matter-where-i-place-the-asterisk-when -declaring-pointers-in-c) –

Respuesta

11

No hay absolutamente ninguna diferencia en la funcionalidad entre

int* ptr; 

y

int *ptr; 

cual se utiliza depende de usted, hay varios estilos de codificación en conflicto a elegir.

+1

+1. Esta es la respuesta correcta en lo que se refiere a SO. No hay diferencia, y la elección es tuya. –

+0

Si desea obtener información técnica, usar 'int * ptr;' también es equivalente. Siempre que el asterisco esté entre el nombre del tipo y el nombre de la variable, el espacio en blanco no importa. – bta

+0

@DanFego: es la respuesta correcta en lo que respecta al compilador. Existen razones válidas para usar una u otra forma, y ​​SO es un buen lugar para debatir esas razones. –

6

Solo importa cuando piense declarar varias variables del mismo tipo en la misma línea. Por ejemplo, si desea que varios punteros int, que tiene que hacer esto:

int *a, *b, *c; 

punto de vista estilístico, sin embargo, esto es confuso cuando sólo está declarando una sola variable. Muchas personas les gusta ver el tipo seguido del nombre de la variable, y el tipo se supone que es puntero a int, no int, por lo que prefieren:

int* a; 
int* b; 
int* c; 

Es en última instancia, depende de usted si usted prefiere una forma sobre la otro. En 20 años de programación C profesionalmente, he visto que aproximadamente el 50% de las personas eligen una sobre la otra.

+0

Esta (las dos variantes anteriores) es una manera muy clara de tratar con la regla de asociación de asterisco incómoda. Evito escribir 'int * a, b;', 'int a, * b;', y 'int * a, * b;' porque son muy exigentes con la atención, no porque no sé lo que cada uno de ellos significa . Además, compilar con todas las advertencias habilitadas y mantener el código de advertencia de limpieza ayuda a evitar el uso no deseado de enteros como punteros y viceversa. –

+0

@ user1118321 Gracias por publicar una de las pocas respuestas que realmente resuelven el problema: declarar más de una variable en la misma línea. Estoy estrictamente en contra de poner el * con el tipo porque muestra que el desarrollador en realidad no entiende la sintaxis. – doug65536

0

Tiene razón, ambos significan exactamente lo mismo para el compilador. Ambas declaraciones producirán una variable del tipo (int *).

Por lo que es correcto: ¡Latas de gusanos! Ese es un tema de debate por lo general. Si trabaja para una empresa o en OSS, probablemente sea mejor pasar a un estilo de codificación definido. Si no hay uno, generalmente utilizo el estilo LNT (no dejar rastro) para hacer coincidir cualquier estilo que evidentemente haya sido usado en esta parte de la base de códigos.

Se puede argumentar que para el lector es más fácil de entender. Por ejemplo int* ptr; pone el * más cerca de la int que se comunica con mayor claridad la que estamos hablando de un tipo (int *) ...

1

En C, el espacio en blanco no importa, excepto donde se necesita para separar tokens. Ambas variantes son sintácticamente correctas.

La variante 1 asocia el operador del puntero con el tipo, lo cual es lo suficientemente lógico. Para mí, eso sería suficiente si no hubiera razón por la cual la Variante 2 tiene sentido.

La variante 2 es coherente con la estructura de las declaraciones C. En la gramática C, el operador del puntero pertenece al declarador (es decir, con el nombre), no al tipo. Esto importa al declarar múltiples variables en la misma declaración. También hay una cantidad de casos más esotéricos en los que importa.

Por lo tanto, para mí, la Variante 2 es más consistente con C. Pero cualquiera de las variantes es defendible, y ambas variantes son convencionales.

4

Ambos significan lo mismo que otros han dicho. Aunque hay una trampa esperándote. Considere este código:

int* a, b; 

Se podría pensar que este declaró a los punteros a int. No, pero si no. De hecho, a es int*, pero b es int. Esta es una de las razones por las que muchos programadores de C prefieren poner el * al lado de la variable en lugar del tipo. Cuando se escribe así:

int *a, b; 

que son menos propensos a ser engañados en cuanto a lo a y b son.

Habiendo dicho todo eso, muchos estándares de codificación insisten en que usted declare no más de una variable por línea, i, e.

int* a; 
int b; 

Si sigue la regla de una variable por línea a continuación, definitivamente no hay posibilidad de confusión.

4
T *a; 

es la manera estilo C preferido para declarar un puntero a T como se utiliza en Kernighan & libro de Ritchie sobre C.

T* a; 

es el C++ manera estilo preferido a un puntero declare a T como se usa en el libro de Stroustrup sobre C++.

Ambas anotaciones son equivalentes.

+1

+1 para apelar a la autoridad ;-) –

12

algo que nadie más ha mencionado es que

int *ptr; 

corresponde más estrechamente a la gramática de la lengua.

  • int *ptr; es una declaración , que consiste en:
    • un declaración-especificadorint, seguido por
    • un declarador, *ptr.

(Que en realidad se salta un número de pasos, pero tiene la idea básica de diámetro.)

Desde declaración sigue su uso, lo que esto significa es que *ptr es de tipo int. De esto se sigue que ptr es del tipo int*.

Se podría argumentar que esto hace que sea mejor que

int* ptr; 

por la misma razón que

x = y+z; 

es mejor que

x=y + z; 

Por supuesto que puede escribir

int* ptr; 

y léelo como "ptr es del tipo int*". Y muchos programadores hacen exactamente eso, y se llevan bien (tiende a ser el estilo preferido en C++). Al compilador no le importa de qué manera lo haces, y cualquiera que lea tu código no debería tener problemas para entenderlo de ninguna manera.

Pero cualquiera que sea el espaciamiento que elija, es necesario comprender lo que int *ptr; realmente significa, de manera que cuando se ve

int *ptr, i; 

en algún otro código (como se verá inevitablemente), comprenderá inmediatamente que ptr es un puntero y i es un int.

Y si está trabajando con otros programadores en un proyecto, debe seguir cualquier convención existente en los estándares de codificación, o si no hay uno, la forma en que el código ya está escrito. Yo personalmente prefiero int *ptr; a int* ptr;, pero usar una mezcla de ambos estilos es mucho peor que usar uno de forma consistente.

2

Las declaraciones de C se basan en los tipos de expresiones , no en objetos.

Si usted tiene un puntero a un int llamado pi, y desea acceder al valor entero que apunte a, hay que eliminar la referencia al puntero, como en:

x = *pi; 
printf("%d", *pi); 
*pi = 1 + 2; 

etc.Tipo de la expresión *pi es int: por lo tanto, la declaración debe decir lo

int *pi; 

Ahora vamos a suponer que tenía una matriz de punteros a char; para llegar a cualquier carácter, es necesario primer subíndice en la matriz, a continuación, eliminar la referencia al resultado:

c = *pc[i]; 
if (*pc[j] == 'a') {...} 

etc. Una vez más, el tipo de la expresión *pc[i] es char, por lo que la declaración dice lo

char *pc[N]; 

Tanto *pi y *pc[N] son conocidos como declaradores y especifique la información de tipo adicional no propuesta por el especificador de tipo. IOW, la matriz y el puntero-ness de pc se especifican como parte del declarador, mientras que el char -ness viene dado por el especificador de tipo.

En cuanto a la cuestión de cuál es el estilo es adecuado ...

Ninguno de los dos es "correcto", pero yo (y muchos otros programadores C) prefieren escribir T *p en contraposición a T* p, ya que refleja más de cerca la gramática del lenguaje (el * es parte del declarador) y ayuda a evitar confusiones al declarar varios elementos. He visto ahora demasiados ejemplos de personas escribiendo T* a, b; y esperando que b sea un puntero.

La respuesta habitual a esa crítica es "no declare más de un artículo por línea". Mi respuesta a esa respuesta es "escriba sus declaradores correctamente y no tendrá ningún problema".

Hay una escuela de pensamiento diferente entre muchos programadores de C++, que prefieren el estilo T* p, y tengo que decir que hay algunos casos (limitados a C++) donde puede que el código sea más legible.

Sin embargo, eso solo funciona con punteros simples a T: el paradigma se descompone rápidamente cuando comienza a tratar con matrices de punteros, punteros a matrices o punteros a funciones o punteros a matrices de punteros a funciones, etc. Quiero decir, escribir algo como

T* (*(*p)[N])(); // p is a pointer to an array of pointers to functions 
       // returning pointers to T. 

solo indica un pensamiento confuso. Aunque, si muy muy muy siente que debe seguir el paradigma T* p, siempre se puede crear una serie de typedefs:

EDITAR

Vamos a intentarlo de nuevo:

typedef T* TPtr;       // pointer to T 
typedef TPtr TPtrFunc();     // function returning pointer to T 
typedef TPtrFunc* TPtrFuncPtr;    // pointer to function returning 
              // pointer to T 
typedef TPtrFuncPtr TPtrFuncPtrArray[N]; // N-element array of pointer to function 
              // returning pointer to T 

TPtrFuncPtrArray* p; 

Por el amor de Dios, no hagas eso.

Cuestiones relacionadas