Las matrices y los punteros son animales completamente diferentes. En la mayoría de los contextos, una expresión que designa una matriz se trata como un puntero.
En primer lugar, un poco de lenguaje estándar (n1256):
6.3.2.1 Lvalues, matrices y designadores de función
...
3, excepto cuando es el operando del operador
sizeof
o la unario
&
operador, o es una cadena literal utilizado para inicializar una matriz, una expresión que tiene el tipo " matriz de
tipo "se convierte en una expresión con tipo" puntero a
tipo "que apunta al elemento inicial del objeto de matriz y no es un valor l. Si el objeto de matriz tiene una clase de almacenamiento de registro, el comportamiento no está definido.
La cadena literal "esta es una prueba" es una matriz de 15 elementos de char
. En la declaración
char *string1 = "this is a test";
string1
se declara como un puntero a
char
. Según el idioma anterior, el tipo de la expresión
"esto es una prueba" se convierte de
char [15]
a
char *
, y el valor del puntero resultante se asigna a
string1
.
En la declaración
char string2[] = "this is a test";
sucede algo diferente. Más lenguaje estándar:
6.7.8 Inicialización
...
14 Matriz de tipo carácter puede ser inicializado por una cadena de caracteres literales, opcionalmente entre llaves. Los caracteres sucesivos del literal de cadena de caracteres (incluido el carácter nulo de terminación si hay espacio o si el conjunto es de tamaño desconocido) inicializan los elementos del conjunto.
...
22 Si se inicializa una matriz de tamaño desconocido, su tamaño está determinado por el elemento indexado más grande con un inicializador explícito. Al final de su lista de inicializadores, la matriz ya no tiene un tipo incompleto.
En este caso, string2
se declara como una matriz de char
, su tamaño se calcula a partir de la longitud del inicializador, y los contenido de la cadena literal se copian a la matriz.
Aquí está un mapa de memoria hipotética para ilustrar lo que está sucediendo:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
no name 0x080't' 'h' 'i' 's'
0x080' ' 'i' 's' ' '
0x080'a' ' ' 't' 'e'
0x0800123C 's' 't' 0
...
string1 0x12340000 0x08 0x00 0x12 0x30
string2 0x12340004 't' 'h' 'i' 's'
0x12340008 ' ' 'i' 's' ' '
0x1234000C 'a' ' ' 't' 'e'
0x1234000F 's' 't' 0
literales de cadena tienen medida estática; es decir, la memoria para ellos se reserva al inicio del programa y se mantiene hasta que finaliza el programa. Intentar modificar el contenido de un literal de cadena invoca un comportamiento indefinido; la plataforma subyacente puede o no permitirlo, y la norma no impone restricciones al compilador. Lo mejor es actuar como si los literales fueran siempre no escribibles.
En mi mapa de memoria de arriba, la dirección del literal de cadena se establece un poco desde las direcciones de string1
y string2
para ilustrar esto.
De todos modos, puede ver que string1
, que tiene un tipo de puntero, contiene la dirección de la cadena literal. string2
, al ser un tipo de matriz, contiene una copia del contenido de la cadena literal.
Como se conoce el tamaño de string2
en tiempo de compilación, sizeof
devuelve el tamaño (número de bytes) en la matriz.
El especificador de conversión %i
no es el correcto para las expresiones del tipo size_t
. Si está trabajando en C99, use %zu
. En C89, utilizaría %lu
y echó la expresión de unsigned long
:
C89: printf("%lu, %lu\n", (unsigned long) sizeof string1, (unsigned long) sizeof string2);
C99: printf("%zu, %zu\n", sizeof string1, sizeof string2);
Tenga en cuenta que es un operador sizeof
, no es una llamada a la función; cuando el operando es una expresión que denota un objeto , los paréntesis no son necesarios (aunque no duelen).
Además, 'sizeof' devuelve' size_t', que, a diferencia del 'int' esperado por'% i', no está firmado. El formato correcto para las variables 'size_t' es'% zu'. –
¡La matriz no es un pinter! ¡Recuerda eso! – Hauleth