Estoy un poco confundido acerca de algo. Tenía la impresión de que la forma correcta de leer una cadena C scanf()
seguía las líneas de
(No importa el posible desbordamiento del búfer, es solo un ejemplo simple)
char string[256];
scanf( "%s" , string );
Sin embargo, lo siguiente parece funcionar también,
scanf( "%s" , &string );
¿Es solo mi compilador (gcc), pura suerte o algo más?
scanf
, y tanto la pregunta como la respuesta aceptada se centran en eso, y omita las restricciones críticamente importantes para la longitud máxima de entrada que deberían usarse en el código real (pero que están fuera del punto de esta pregunta).Respuestas:
Una matriz "decae" en un puntero a su primer elemento, por lo que
scanf("%s", string)
es equivalente ascanf("%s", &string[0])
. Por otro lado,scanf("%s", &string)
pasa un puntero achar[256]
, pero apunta al mismo lugar.Luego
scanf
, al procesar la cola de su lista de argumentos, intentará extraer achar *
. Eso es lo correcto cuando ha pasadostring
o&string[0]
, pero cuando ha pasado&string
depende de algo que el estándar del lenguaje no garantiza, a saber, los punteros&string
y los&string[0]
punteros a objetos de diferentes tipos y tamaños que comenzar en el mismo lugar: se representan de la misma manera.No creo haber encontrado un sistema en el que eso no funcione, y en la práctica probablemente estés a salvo. Sin embargo, está mal y podría fallar en algunas plataformas. (Ejemplo hipotético: una implementación de "depuración" que incluye información de tipo con cada puntero. Creo que la implementación de C en las "Máquinas Lisp" de Symbolics hizo algo como esto).
fuente
&string
funcione de la misma manera questring
(en lugar de provocar daños aleatorios en la memoria, como afirman incorrectamente otras respuestas):printf("%x\n%x\n", string, &string);
string
es un puntero y&string
es la dirección de ese puntero, por lo que los dos NO son intercambiables. Como explica Gareth, incluso en el caso de la descomposición de la matriz,string
y&string
técnicamente no son del mismo tipo (aunque sean intercambiables para la mayoría de las arquitecturas), y gcc le dará una advertencia para su segundo ejemplo si lo activa-Wall
.Creo que esto a continuación es exacto y puede ayudar. Siéntase libre de corregirlo si encuentra algún error. Soy nuevo en C.
incluyendo el carácter nulo de terminación
'\0'
&str
,&str[0]
ystr
, los tres representan la misma ubicación en la memoria, que es la dirección del primer elemento de la matrizstr
char * strPtr = & str [0]; // declaración e inicialización
Alternativamente, puede dividir esto en dos:
strPtr
es un puntero a unchar
strPtr
puntos en la matrizstr
strPtr
es una variable con su propia dirección en la memoriastrPtr
es una variable que almacena el valor de la dirección&str[0]
strPtr
La propia dirección en la memoria es diferente de la dirección de memoria que almacena (dirección de la matriz en la memoria aka & str [0])&strPtr
representa la dirección de strPtr en síCreo que podría declarar un puntero a un puntero como:
declara e inicializa con la dirección del puntero strPtr
Alternativamente, podría dividirse en dos:
*vPtr
apunta al puntero strPtr*vPtr
es una variable con su propia dirección en la memoria*vPtr
es una variable que almacena el valor de dirección y strPtrstr++
, lastr
dirección es unaconst
, pero se puede hacerstrPtr++
fuente