tipos - vectores en c++ pdf
¿Qué significa el ''nombre de la matriz'' en el caso de la matriz de punteros de char? (4)
En la mayoría de los casos, un nombre de matriz decaerá al valor de la dirección de su primer elemento, y con el tipo que es lo mismo que un puntero al tipo de elemento. Por lo tanto, esperaría que un str
desnudo tenga un valor igual a &str[0]
con un puntero tipo a puntero a char
.
Sin embargo, este no es el caso para sizeof
. En este caso, el nombre de la matriz mantiene su tipo para sizeof
, que sería una matriz de 4 punteros a char
.
El tipo de devolución de sizeof
es un size_t
. Si tiene un compilador C99, puede usar %zu
en la cadena de formato para imprimir el valor devuelto por sizeof
.
En mi código:
char *str[] = {"forgs", "do", "not", "die"};
printf("%d %d", sizeof(str), sizeof(str[0]));
Obtengo la salida como 12 2
, así que mis dudas son:
- ¿Por qué hay una diferencia?
- Tanto
str
comostr[0]
son punteros de char, ¿verdad?
Es 16 4
en mi computadora, y puedo explicar esto: str
es una matriz de char*
, así sizeof(str)==sizeof(char*)*4
Sin embargo, no sé por qué tienes 12 2
.
Los dos punteros son diferentes. str
es una array of char pointers
, en su ejemplo es a ( char*[4]
), y str[0]
es un char pointer
.
El primer tamaño devuelve el tamaño de los cuatro punteros que contiene, y el segundo devuelve el tamaño del char*
.
En mis pruebas, los resultados son:
sizeof(str[0]) = 4 // = sizeof(char*)
sizeof(str) = 16
= sizeof(str[0]) + sizeof(str[1]) + sizeof(str[2]) + sizeof(str[3])
= 4 * sizeof(char*)
= 4 * 4
= 16
A través de la pregunta ya está respondida y aceptada, pero estoy agregando más descripción (que también responde a la pregunta original) que creo que será útil para los nuevos usuarios. (como busqué, esta descripción no se explica en ningún otro lugar (al menos en ) por lo tanto, ahora estoy agregando.
Primera lectura: operador de sizeof
6.5.3.4 El operador de tamaño, 1125:
Cuando aplica el operadorsizeof
a un tipo de matriz, el resultado es la cantidad total de bytes en la matriz.
De acuerdo con esto, cuando sizeof
se aplica al nombre de un identificador de matriz estática ( no asignado a través de malloc), el resultado es el tamaño en bytes de toda la matriz en lugar de solo la dirección. Esta es una de las pocas excepciones a la regla de que el nombre de una matriz se convierte / decae a un puntero al primer elemento de la matriz , y es posible simplemente porque el tamaño real de la matriz es fijo y conocido en tiempo de compilación, cuando sizeof
operador sizeof
evalúa.
Para entenderlo mejor, considere el siguiente código:
#include<stdio.h>
int main(){
char a1[6], // One dimensional
a2[7][6], // Two dimensional
a3[5][7][6]; // Three dimensional
printf(" sizeof(a1) : %lu /n", sizeof(a1));
printf(" sizeof(a2) : %lu /n", sizeof(a2));
printf(" sizeof(a3) : %lu /n", sizeof(a3));
printf(" Char : %lu /n", sizeof(char));
printf(" Char[6] : %lu /n", sizeof(char[6]));
printf(" Char[5][7] : %lu /n", sizeof(char[7][6]));
printf(" Char[5][7][6]: %lu /n", sizeof(char[5][7][6]));
return 1;
}
Su salida:
sizeof(a1) : 6
sizeof(a2) : 42
sizeof(a3) : 210
Char : 1
Char[5] : 6
Char[5][7] : 42
Char[5][7][6]: 210
Verifique arriba, trabajando en @ codepad , observe que el tamaño de char
es de un byte, si reemplaza char
con int
en el programa anterior, entonces cada salida se multiplicará por sizeof(int)
en su máquina.
Diferencia entre char* str[]
y char str[][]
y cómo se almacenan ambos en la memoria
Declaración-1: char *str[] = {"forgs", "do", "not", "die"};
En esta declaración str[]
es una matriz de punteros a char. Cada índice str[i]
apunta al primer carácter de las cadenas en {"forgs", "do", "not", "die"};
.
Lógicamente str
debe organizarse en la memoria de la siguiente manera:
Array Variable: Constant Strings:
--------------- -----------------
str: 201 202 203 204 205 206
+--------+ +-----+-----+-----+-----+-----+-----+
343 | |= *(str + 0) | ''f'' | ''o'' | ''r'' | ''g'' | ''s'' | ''/0''|
| str[0] |-------| +-----+-----+-----+-----+-----+-----+
| 201 | +-----------▲
+--------+ 502 503 504
| | +-----+-----+-----+
347 | str[1] |= *(str + 1) | ''d'' | ''o'' | ''/0''|
| 502 |-------| +-----+-----+-----+
+--------+ +-----------▲
| | 43 44 45 46
351 | 43 | +-----+-----+-----+-----+
| str[2] |= *(str + 2) | ''n'' | ''o'' | ''t'' | ''/0''|
| |-------| +-----+-----+-----+-----+
+--------+ +-----------▲
355 | |
| 9002 | 9002 9003 9004 9005
| str[3] | +-----+-----+-----+-----+
| |= *(str + 3) | ''d'' | ''i'' | ''e'' | ''/0''|
+--------+ | +-----+-----+-----+-----+
+-----------▲
Diagram: shows that str[i] Points to first char of each constant string literal.
Memory address values are assumption.
Nota: str[]
se almacena en las asignaciones de memoria continua y cada cadena se almacena en la memoria en una dirección aleatoria (no en el espacio continuo).
[RESPONDER]
De acuerdo con el código de Codepad siguiente:
int main(int argc, char **argv){
char *str[] = {"forgs", "do", "not", "die"};
printf("sizeof(str): %lu, sizeof(str[0]): %lu/n",
sizeof(str),
sizeof(str[0])
);
return 0;
}
Salida:
sizeof(str): 16, sizeof(str[0]): 4
En este código,
str
es una matriz para 4 direcciones de caracteres, donde cadachar*
tiene un tamaño de 4 bytes, por lo que, de acuerdo con la cita anterior, el tamaño total de la matriz es4 * sizeof(char*)
= 16 bytes.El tipo de datos de
str
eschar*[4]
.str[0]
no es más que puntero a char, por lo que sus cuatro bytes. El tipo de fecha destr[i]
eschar*
.
(nota: en alguna dirección del sistema puede ser de 2 bytes o 8 bytes)
En cuanto a la producción, también se debe leer el comment glglgl a la pregunta:
En cualquier arquitectura que seas, el primer valor debe ser 4 veces el segundo. En una máquina de 32 bits, debería obtener 16 4, en una de 64 bits, una 32 8. En una muy antigua o en un sistema integrado, incluso podría obtener 8 2, pero nunca 12 2, ya que la matriz contiene 4 elementos del mismo tamaño
Puntos adicionales:
- Como cada
str[i]
apunta a unchar*
(y string) es variable, astr[i]
se le puede asignar una nueva dirección de cadena, por ejemplo:str[i] = "yournewname";
es válido parai = 0 to < 4
.
Un punto más importante para notar:
En nuestro ejemplo anterior,
str[i]
apunta a un literal de cadena constante que no se puede modificar; por lo tantostr[i][j] = ''A''
no es válido (no podemos escribir en la memoria de solo lectura) y hacer esto será un error de tiempo de ejecución.
Pero supongamos que sistr[i]
apunta a una matriz de caracteres simple, entoncesstr[i][j] = ''A''
puede ser una expresión válida.
Considera seguir el código:char a[] = "Hello"; // a[] is simple array char *str[] = {"forgs", "do", "not", "die"}; //str[0][4] = ''A''; // is error because writing on read only memory str[0] = a; str[0][5] = ''A''; // is perfectly valid because str[0] // points to an array (that is not constant)
Compruebe aquí el código de trabajo: Codepad
Declaración-2: char str[][6] = {"forgs", "do", "not", "die"};
:
Aquí str
es una matriz bidimensional de caracteres (donde cada fila es igual en tamaño) de tamaño 4 * 6. (recuerde que debe dar el valor de la columna en la declaración de str
explícitamente, pero la fila es 4 porque el número de cadenas es 4)
En la memoria str[][]
será algo así como debajo en el diagrama:
str
+---201---202---203---204---205---206--+
201 | +-----+-----+-----+-----+-----+-----+|
str[0] = *(str + 0)--►| ''f'' | ''o'' | ''r'' | ''g'' | ''s'' | ''/0''||
207 | +-----+-----+-----+-----+-----+-----+|
str[1] = *(str + 1)--►| ''d'' | ''o'' | ''/0''| ''/0''| ''/0''| ''/0''||
213 | +-----+-----+-----+-----+-----+-----+|
str[2] = *(str + 2)--►| ''n'' | ''o'' | ''t'' | ''/0''| ''/0''| ''/0''||
219 | +-----+-----+-----+-----+-----+-----+|
str[3] = *(str + 3)--►| ''d'' | ''i'' | ''e'' | ''/0''| ''/0''| ''/0''||
| +-----+-----+-----+-----+-----+-----+|
+--------------------------------------+
In Diagram:
str[i] = *(str + i) = points to a complete i-row of size = 6 chars.
str[i] is an array of 6 chars.
Esta disposición de la matriz 2D en la memoria se denomina Row-Major : una matriz multidimensional en la memoria lineal está organizada de manera que las filas se almacenan una después de la otra. Es el enfoque utilizado por el lenguaje de programación C.
Observe las diferencias en ambos diagramas.
- En el segundo caso, se asigna una matriz de caracteres bidimensional completa en la memoria continua.
- Para cualquier
i = 0 to 2
, el valor destr[i]
ystr[i + 1]
es diferente en 6 bytes (esto es igual a la longitud de una fila). - La doble línea de límite en este diagrama significa que
str
representa 6 * 4 = 24 caracteres completos.
Ahora considere el código similar que publicó en su pregunta para una matriz de caracteres bidimensionales, verifique en Codepad :
int main(int argc, char **argv){
char str[][6] = {"forgs", "do", "not", "die"};
printf("sizeof(str): %lu, sizeof(str[0]): %lu/n",
sizeof(str),
sizeof(str[0])
);
return 0;
}
Salida:
sizeof(str): 24, sizeof(str[0]): 6
De acuerdo con el tamaño del tratamiento del operador con matriz, en la aplicación de 2-d tamaño de matriz debería devolver el tamaño completo de la matriz que es de 24 bytes.
Como sabemos, el operador
sizeof
devuelve el tamaño de toda la matriz al aplicar el nombre de la matriz. Entonces, parasizeof(str)
, devuelve = 24, que es el tamaño de una matriz 2D completa, consta de 24 caracteres (6 columnas * 4 filas).En esta declaración, el tipo de
str
eschar[4][6]
.Un punto más interesante es que
str[i]
representa un conjunto de chats y su tipo eschar[6]
. Ysizeof(str[0])
es el tamaño completo de la matriz = 6 (longitud de fila).
Puntos adicionales:
En la segunda declaración
str[i][j]
no es constante, y su contenido puede ser cambios, por ejemplo,str[i][j] = ''A''
es una operación válida.str[i]
es el nombre de la matriz char del tipochar[6]
es una constante y la asignación astr[i]
por ejemplostr[i] = "newstring"
es una operación ilegal (infectarlo será un error de tiempo de compilación).
Una diferencia más importante entre dos declaraciones:
En Declaration-1 : char *str[] = {"forgs", "do", "not", "die"};
, el tipo de &str
es char*(*)[4]
, su dirección de una matriz de punteros char.
En Declaration-2 : char str[][6] = {"forgs", "do", "not", "die"};
, el tipo de &str
es char(*)[4][6]
, su dirección de 2-D char array de 4 filas y 6 cols.
Si uno quiere leer una descripción similar para una matriz 1-D: ¿Qué devuelve sizeof(&array)
?