Esta pregunta puede parecer bastante duplicada; sin embargo, de hecho he realizado una encuesta seria en este sitio y todavía no puedo entenderlo.
char str[] = "test"; printf("%p\n", str); printf("%p\n", &str); Sé que str en sí mismo es un puntero que apunta a la ubicación inicial que almacena "t". Por lo tanto espero que printf("%p\n", str); muestra esta dirección (por ejemplo 000000FFE94FFC34 ). A continuación, deseo saber en mi sistema operativo, en qué ubicación de memoria almacena la información exacta 000000FFE94FFC34 . (es decir, la dirección de str en sí).
Sin embargo, la salida de la tercera línea es la misma que la anterior. Parece un comportamiento bastante extraño. ¿Y cómo puedo averiguar la dirección de str en sí? Supongo que esto se puede lograr usando otro puntero nuevo que apunte al puntero que quiero, es decir, char **super_pointer = str; pero creo que es una forma innecesariamente complicada.
Vamos a dibujarlo con los punteros agregados, para que sea más fácil de entender:
+--------+--------+--------+--------+--------+ | cadena[0] | cadena[1] | cadena[2] | cadena[3] | cadena[4] | +--------+--------+--------+--------+--------+ ^ | &str[0] | &str
Como puede ver, el puntero al primer elemento ( &str[0] que es a lo que decae str simple) apunta a la misma ubicación que la matriz en sí ( &str ).
Pero (y es un pero importante): ¡Los tipos son muy diferentes!
El tipo de &str[0] es char * .
El tipo de &str es char (*)[5] .
En otra nota dices que
...
stren sí es un puntero...
Esto está mal . str en sí mismo es la matriz, que puede decaer en un puntero a su primer elemento.
Sé que str en sí mismo es un puntero que apunta a la ubicación inicial que almacena "t".
Como escribió, "str sí mismo" no es un puntero, es una matriz. Pero los designadores de matrices usados en expresiones, con raras excepciones, se convierten en punteros a sus primeros elementos.
Del Estándar C (6.3.2.1 Valores L, matrices y designadores de función)
3 Excepto cuando es el operando del operador sizeof o el operador unario &, o es un literal de cadena usado para inicializar una matriz, una expresión que tiene tipo ''matriz de tipo'' se convierte en una expresión con tipo ''puntero para escribir'' que apunta al elemento inicial del objeto de matriz y no es un valor l. Si el objeto de la matriz tiene una clase de almacenamiento de registros, el comportamiento no está definido.
en esta llamada
printf("%p\n", str); el designador de matriz str utilizado como expresión de argumento se convierte en un puntero a su primer elemento. De hecho, esta llamada es equivalente a
printf("%p\n", &str[0]);Es decir, esta llamada genera la dirección inicial de la extensión de la memoria ocupada por la matriz.
Esta llamada
printf("%p\n", &str);que es mejor escribir como y la llamada anterior como
printf("%p\n", ( void * )&str);también genera la dirección inicial de la extensión de la memoria ocupada por la matriz.
¿Cuál es la diferencia?
La expresión str utilizada en la llamada de printf tiene el tipo char * mientras que la expresión &str tiene el tipo char ( * )[5] .
La llamada interpreta ambas expresiones como expresiones del tipo void * .
Para hacer esto más claro, considere una matriz bidimensional
char str[2][6] = { "test1", "test2" };Las direcciones de la matriz en su conjunto y de su primera "fila" y de su primer carácter de la primera "fila" son coincidentes.
Esa es la expresión &sgtr que tiene el tipo char ( * )[2][6] y la expresión &str[0] que tiene el tipo char ( * )[6] y la expresión &str[0][0] que tiene el escriba char * produce el mismo valor: hhe dirección inicial de la extensión de memoria ocupada por la matriz..