sobre la expresión “& anArray” en c

Primero, leí eso:

  • array
  • &array
  • &array[0]

Todos serán iguales siempre que “array” sea realmente un array. Así que intenté:

 int main(){ char ar[]={'a','b','c','\0'}; printf("argument: &ar %s\n",&ar); printf("argument: &ar[1] %s\n",&ar[1]); } 

La salida:

 argument:&ar abc argument:&ar[1] bc 

Parece que &ar se toma como un puntero al primer elemento en lugar de un puntero a “ar”, que a su vez es un puntero al primer elemento si no me equivoco.

Porque eso no debería ser cómo se trata el (puntero a un char), lo intenté:

 char a='s'; char *pa=&a; printf("argument: &pa %c\n",&pa); 

La salida para %c ni siquiera es un carácter. Tampoco debería ser cómo se trata un puntero al primer elemento de una matriz. Lo intenté:

 char *pa=&ar[0]; char **ppa= &pa; printf("argument: &pa %s\n", ppa); 

La salida para %s es, como es lógico, sin sentido; pero ¿por qué no ha sido absurdo? Porque si ar fuera un puntero, ¿no debería ser un puntero a un puntero como lo es ppa ?

Mis preguntas:

  1. ¿Se ignora simplemente “&” cuando se coloca antes de un nombre de matriz? ¿Son los nombres de matriz simplemente especiales en esto?
  2. Si es así, ¿cómo verifica el comstackdor que el identificador que sigue a “&” es una referencia a una matriz? ¿Realmente lo busca en una lista de matrices para declarar?

Parece que &ar se toma como un puntero al primer elemento en lugar de un puntero a “ar”, que a su vez es un puntero al puntero del primer elemento si no me equivoco.

Estas equivocado &ar es un puntero a la matriz ar , pero la matriz ar no es un puntero de ningún tipo (es una matriz), por lo que &ar no es un puntero a un puntero.

Una matriz es una secuencia contigua de objetos; en el caso de ar , es un conjunto contiguo de 4 caracteres. &ar es un puntero a este conjunto de 4 caracteres , lo que necesariamente significa que apunta al mismo lugar que &ar[0] , un puntero al primer char en ese conjunto. Sin embargo, tiene un tipo diferente: &ar tiene tipo char (*)[4] que significa “puntero a la matriz de 4 caracteres” y &ar[0] tiene tipo char * , que significa “puntero a char”.

La confusión surge porque en casi todas las expresiones, ar evalúa como un puntero al primer elemento de la matriz (las excepciones a esto son cuando es el operando de unary & operator o el operador sizeof ). Esto no significa que ar sea un puntero, aunque no lo es, solo que en la mayoría de los casos se evalúa como un valor de puntero.

Si su código fue comstackdo sin advertencias, no está haciendo un uso completo de su comstackdor. Te ayudará si lo pides. Aprenda cómo comstackrlo con advertencias y cómo solucionar los problemas que diagnostica. Compilé el código a continuación con uno u otro de estos comandos:

 gcc -O3 -g -std=c99 -Wall -Wextra -m64 array-stuff.c -o array-stuff gcc -O3 -g -std=c99 -Wall -Wextra -m32 array-stuff.c -o array-stuff 

Ese es un buen punto de partida para un código limpio con GCC. De hecho, -Wall without -Wextra es bastante bueno.

Aquí hay una adaptación de su código (en un archivo array-stuff.c ), aunque la mayoría es diferente:

 #include  #include  int main(void) { // DC4M = Doesn't compile for me, because I compile with stringent warnings char ar[16] = { 'a', 'b', 'c', '\0' }; // Note explicit size printf("%-18s %s\n", "Code:", "char ar[16] = { 'a', 'b', 'c', '\0' };"); //printf("argument: &ar %s\n", &ar); // DC4M printf("argument: &ar[1] %s\n", &ar[1]); printf("%-18s 0x%" PRIXPTR "\n", "ar:", (uintptr_t)ar); printf("%-18s 0x%" PRIXPTR "\n", "&ar:", (uintptr_t)&ar); printf("%-18s 0x%" PRIXPTR "\n", "(ar+1):", (uintptr_t)(ar+1)); printf("%-18s 0x%" PRIXPTR "\n", "(&ar+1):", (uintptr_t)(&ar+1)); printf("%-18s 0x%" PRIXPTR "\n", "&ar[1]:", (uintptr_t)(&ar[1])); printf("%-18s 0x%" PRIXPTR "\n", "&(ar[1]):", (uintptr_t)(&(ar[1]))); printf("%-18s 0x%" PRIXPTR "\n", "(&ar)[1]:", (uintptr_t)((&ar)[1])); printf("%-18s %zu\n", "sizeof(ar):", sizeof(ar)); printf("%-18s %zu\n", "sizeof(&ar):", sizeof(&ar)); printf("%-18s %zu\n", "sizeof(void*):", sizeof(void*)); printf("%-18s %zu\n", "sizeof(ar[1]):", sizeof(ar[1])); printf("%-18s %zu\n", "sizeof(&ar[1]):", sizeof(&ar[1])); printf("%-18s %zu\n", "sizeof(&(ar[1])):", sizeof(&(ar[1]))); printf("%-18s %zu\n", "sizeof((&ar)[1]):", sizeof((&ar)[1])); { char a = 's'; char *pa = &a; printf("%-18s %s\n", "Code:", "char a = 's';"); printf("%-18s %s\n", "Code:", "char *pa = &a;"); //printf("argument: &pa %c\n", &pa); // DC4M printf("%-18s 0x%" PRIXPTR "\n", "&pa:", (uintptr_t)&pa); printf("%-18s 0x%" PRIXPTR "\n", "&a:", (uintptr_t)&a); printf("%-18s 0x%" PRIXPTR "\n", "pa:", (uintptr_t)pa); } { char *pa = &ar[0]; char **ppa = &pa; //printf("argument: &pa %s\n", ppa); // DC4M printf("%-18s %s\n", "Code:", "char *pa = &ar[0];"); printf("%-18s %s\n", "Code:", "char **ppa = &pa;"); printf("%-18s 0x%" PRIXPTR "\n", "&pa:", (uintptr_t)&pa); printf("%-18s 0x%" PRIXPTR "\n", "ppa:", (uintptr_t)ppa); printf("%-18s 0x%" PRIXPTR "\n", "*ppa:", (uintptr_t)*ppa); printf("%-18s 0x%" PRIXPTR "\n", "&ppa:", (uintptr_t)&ppa); } } 

Esta es la salida de una máquina Mac OS X 10.7.4 con una comstackción de 64 bits:

 Code: char ar[16] = { 'a', 'b', 'c', ' argument: &ar[1] bc ar: 0x7FFF6C9DE570 &ar: 0x7FFF6C9DE570 (ar+1): 0x7FFF6C9DE571 (&ar+1): 0x7FFF6C9DE580 &ar[1]: 0x7FFF6C9DE571 &(ar[1]): 0x7FFF6C9DE571 (&ar)[1]: 0x7FFF6C9DE580 sizeof(ar): 16 sizeof(&ar): 8 sizeof(void*): 8 sizeof(ar[1]): 1 sizeof(&ar[1]): 8 sizeof(&(ar[1])): 8 sizeof((&ar)[1]): 16 Code: char a = 's'; Code: char *pa = &a; &pa: 0x7FFF6C9DE560 &a: 0x7FFF6C9DE56F pa: 0x7FFF6C9DE56F Code: char *pa = &ar[0]; Code: char **ppa = &pa; &pa: 0x7FFF6C9DE558 ppa: 0x7FFF6C9DE558 *ppa: 0x7FFF6C9DE570 &ppa: 0x7FFF6C9DE550 

Y esta es la salida de una comstackción de 32 bits:

 Code: char ar[16] = { 'a', 'b', 'c', ' argument: &ar[1] bc ar: 0xC008A670 &ar: 0xC008A670 (ar+1): 0xC008A671 (&ar+1): 0xC008A680 &ar[1]: 0xC008A671 &(ar[1]): 0xC008A671 (&ar)[1]: 0xC008A680 sizeof(ar): 16 sizeof(&ar): 4 sizeof(void*): 4 sizeof(ar[1]): 1 sizeof(&ar[1]): 4 sizeof(&(ar[1])): 4 sizeof((&ar)[1]): 16 Code: char a = 's'; Code: char *pa = &a; &pa: 0xC008A668 &a: 0xC008A66F pa: 0xC008A66F Code: char *pa = &ar[0]; Code: char **ppa = &pa; &pa: 0xC008A664 ppa: 0xC008A664 *ppa: 0xC008A670 &ppa: 0xC008A660 

Cuando entienda cómo llegaron a los diversos números, estará bien encaminado para entender las cosas.

Tenga en cuenta que &array[1] se interpreta como &(array[1]) ; es diferente de (&array)[1] en tipo y tamaño. Los operadores de posfijo, como los subíndices de matriz, se unen más estrechamente que los operadores unarios, como los operadores de dirección ( & ) e indirección ( * )

El formato printf% s significa “El argumento correspondiente es un puntero a char. Imprima la cadena en esa ubicación ”. Y una cadena, para este propósito, es una secuencia de caracteres que termina en un carácter nulo.

Cuando pasó &ar a printf, pasó la dirección de la ‘a’ (aunque el tipo es incorrecto; printf espera un puntero a carácter y pasa un puntero a matriz de caracteres, pero tienen el misma dirección), y printf vio la cadena ‘a’, ‘b’, ‘c’, ‘\ 0’, por lo que imprimió “abc”. Lo mismo hubiera sucedido si pasara ar o &ar[0] ; Los que evalúan a la misma dirección.

Cuando pasó &ar[1] a printf, pasó un puntero a donde está la ‘b’, y printf vio la cadena ‘b’, ‘c’, ‘\ 0’, por lo que imprimió “bc”.

Si desea pasar solo el único carácter en una ubicación, use el formato% c y pase un carácter (en lugar de un puntero a carácter). Por ejemplo, si usa el formato% c con *ar , se imprimirá ‘a’ y, si usa% c con *&ar[1] , se imprimirá ‘b’.

Parece que & ar se toma como un puntero al primer elemento en lugar de un puntero a “ar”, que a su vez es un puntero al primer elemento si no me equivoco.

Cuando se usa en una expresión, ar actúa como un puntero al primer elemento de la matriz, igual que &ar[0] . &ar y ar son la misma dirección (el primer carácter de la matriz está en la misma dirección que el inicio de la matriz), aunque tienen diferentes tipos (puntero a matriz de carácter y puntero a característica).

la salida para% c no es ni siquiera un carácter

Es un personaje, simplemente no es lo que esperabas y tal vez no sea un personaje normal o un personaje imprimible. % c espera que se le pase un argumento de carácter, pero usted le pasó un argumento de dirección.

Si es así, ¿cómo verifica el comstackdor que el identificador que sigue a “&” hace referencia a una matriz, en realidad la busca en una lista de matrices que se ha declarado?

El análisis es más complicado que eso (esencialmente, el identificador se identifica como una matriz conocida antes de que se considere &, luego se evalúa la expresión combinada de & y el identificador). Sin embargo, el efecto es que &ar evalúa a la misma dirección que el primer elemento.