2012-07-19 12 views
30

Sé que las matrices en C son solo indicadores de datos almacenados secuencialmente. Pero qué diferencias implican la diferencia en la notación [] y *. Me refiero a TODOS los posibles contextos de uso. Por ejemplo:C/C++ int [] vs int * (punteros vs. notación de matriz). ¿Cuál es la diferencia?

char c[] = "test"; 

si proporciona esta instrucción en un cuerpo de la función que asignará la cadena en una pila, mientras que

char* c = "test"; 

apuntará a un conjunto de datos (sólo lectura) segmento.

Puede enumerar todas las diferencias entre estas dos anotaciones en TODOS los contextos de uso para formar una vista general clara.

+2

Aunque el título es exactamente el mismo, esta pregunta es en realidad mucho más informativa. ¡Deberíamos volver a abrirlo! – ltjax

+0

@ltjax Y tienes razón. Mi culpa por ser gatillo feliz. Votado volver a abrir. – Mysticial

+2

'' char * c = "test"; '' es un código no estándar. El correcto es '' const char * c = "test"; '' –

Respuesta

19

Según el estándar C99:

un tipo de matriz describe un conjunto no vacío de forma contigua asignado de objetos con un tipo de objeto miembro en particular, llamado el elemento type.36) tipos de matriz se caracterizan por su elemento escriba y por la cantidad de elementos en la matriz. Se dice que un tipo de matriz es derivado de su tipo de elemento, y si su tipo de elemento es T, el tipo de matriz a veces se denomina '' matriz de T ''. La construcción de un tipo de matriz de un tipo de elemento se denomina '' derivación de tipo de matriz ''.


un tipo de puntero puede derivar de un tipo de función, un tipo de objeto, o un tipo incompleto, llamado el tipo referenciado. Un puntero tipo describe un objeto cuyo valor proporciona una referencia a una entidad de del tipo al que se hace referencia. Un tipo de puntero derivado del tipo de referencia T a veces se denomina '' puntero a T ''. La construcción de un tipo de puntero de un tipo al que se hace referencia se denomina '' derivación del tipo de puntero ''.

De acuerdo con las declaraciones estándar

char s[] = "abc", t[3] = "abc"; 
char s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' }; 

son idénticos. El contenido de las matrices es modificable. Por otro lado, la declaración const char *p = "abc"; define p con el tipo '' puntero a char constante '' y lo inicializa para apuntar a un objeto con el tipo '' matriz constante de char '' (en C++) con longitud 4 cuyos elementos están inicializados con una cadena de caracteres literal. Si se intenta utilizar p para modificar el contenido de la matriz, el comportamiento no está definido.

Según 6.3.2.1 Array subscripting eliminación de referencias y la matriz subscripting son idénticos:

La definición del operador subíndice [] es que E1 [E2] es idéntica a (* ((E1) + (E2))) .

Las diferencias de matrices vs punteros son:

  • puntero no tiene información del tamaño de la memoria detrás de él (no hay manera portátil para conseguirlo)
  • una matriz de tipo incompleto no puede ser construido
  • un tipo de puntero se puede derivar de una un tipo incompleto
  • un puntero puede definir una estructura recursiva (ésta es la consecuencia de los dos anteriores)

Estos enlaces pueden ser útiles para el sujeto:

+3

"puntero constante a char" ¿no debería ser "puntero a char constante"? Después de todo, el puntero es modificable. – elmo

+0

Se arregló. Gracias. –

+1

"y lo inicializa para que apunte a un objeto con el tipo '' array constante de char ''". En C++, pero no en C. En C, el objeto '" abc "' tiene el tipo 'char [4]'. Sin embargo, intentar modificarlo es UB. Sería bueno señalar la diferencia. –

0

En realidad las matrices son equivalentes a punteros constantes.

Además, char c [] asigna memoria para la matriz, cuya dirección base es c en sí misma. No se asigna memoria separada para almacenar esa dirección.

Escribir char * c asigna memoria para la cadena cuya dirección base se almacena en c. Además, se usa una ubicación de memoria separada para almacenar c.

+0

Las matrices no son punteros. – tenfour

+0

@tenfour: http://www.cplusplus.com/doc/tutorial/pointers/ – Cygnus

+1

Es obvio que ambos sabemos de lo que estamos hablando, pero es imprudente decir que son equivalentes. Las matrices se degradan en punteros, pero eso no es lo mismo que * ser * un puntero. Del mismo modo, 'MyClass' no es equivalente a' int', incluso si hay una conversión implícita. – tenfour

2

char [] denota el tipo "array de desconocido unido de char", mientras que char * denota el tipo " puntero a char ". Como ha observado, cuando una definición de una variable de tipo "array of unknown bound of char" se inicializa con una cadena literal, el tipo se convierte en "array [N] of char" donde N tiene el tamaño apropiado. Lo mismo se aplica en general a la inicialización de la matriz agregada:

int arr[] = { 0, 1, 2 }; 

arr se convierte en el tipo "array [3] de int".

En una definición de tipo definido por el usuario (struct, class o union), array-de-desconocido unido tipos están prohibidos en C++, aunque en algunas versiones de C que se les permite que el última miembro de un struct , donde se pueden usar para acceder a la memoria asignada más allá del final de la estructura; este uso se llama "arreglos flexibles".

La construcción de tipo recursivo es otra diferencia; uno puede construir punteros y matrices de char * (por ejemplo, char **, char (*)[10]), pero esto es ilegal para matrices de límite desconocido; uno no puede escribir char []* o char [][10] (aunque char (*)[] y char [10][] están bien).

Finalmente, la calificación de cv funciona de manera diferente; dado typedef char *ptr_to_char y typedef char array_of_unknown_bound_of_char[], cv-qualifiying la versión del puntero se comportará como se esperaba, mientras que cv-qualifying la versión del array migrará la cv-qualification al tipo de elemento: es decir const array_of_unknown_bound_of_char es equivalente a const char [] y no el char (const) [] ficticio. Esto significa que en una definición de función, donde la descomposición de matriz a la aguja opera en los argumentos antes de construir el prototipo,

void foo (int const a[]) { 
    a = 0; 
} 

es legal; no hay forma de que el parámetro array-of-unknown-bound no sea modificable.

1

La porción entera quedará claro si sabe que

Declaring a pointer variable does not create the type of variable, it points at. It creates a pointer variable.

Así, en uso, si necesita una cadena a continuación, es necesario que especifique una matriz de caracteres y un puntero se puede utilizar más adelante.

7
char c[] = "test"; 

Esto creará una matriz que contiene la prueba de la cuerda para que pueda modificar/cambiar cualquier carácter, dicen

c[2] = 'p'; 

pero,

char * c = "test" 

Es una cadena literal - es un const char.
Por lo tanto, hacer cualquier modificación a este literal de cadena nos da segfault. Entonces

c[2] = 'p'; 

es ilegal ahora y nos da segfault.

+1

'' char * c = "test" '' es un código C incorrecto que produce una advertencia: conversión obsoleta de constante de cadena a 'char *' [-Wwrite-strings]. Use '' const char * '' en su lugar. –

+1

sí, solo estaba dando la otra diferencia que estaba pidiendo – neel