sirven que punteros puntero para operaciones los ejemplo dev declaracion con cadenas arreglos aritmetica apuntadores c arrays pointers

que - punteros a cadenas



En C, ¿están los punteros de matrices o se utilizan como punteros? (6)

Si ''y'' es un puntero constante, ¿por qué tiene un tamaño de 20, como la secuencia de valores a los que apunta?

Debido a que z es la dirección de la variable, y siempre devolverá 8 para su máquina. Debe usar el puntero de desreferencia (&) para obtener el contenido de una variable.

EDITAR: una buena distinción entre los dos: http://www.cs.cf.ac.uk/Dave/C/node10.html

Según entendí, las matrices eran simplemente punteros constantes de una secuencia de valores, y cuando declaraba una matriz en C, estaba declarando un puntero y asignando espacio para la secuencia a la que apunta.

Pero esto me confunde: el siguiente código:

char y[20]; char *z = y; printf("y size is %lu/n", sizeof(y)); printf("y is %p/n", y); printf("z size is %lu/n", sizeof(z)); printf("z is %p/n", z);

cuando se compila con Apple GCC da el siguiente resultado:

y size is 20 y is 0x7fff5fbff930 z size is 8 z is 0x7fff5fbff930

(mi máquina es de 64 bits, los punteros tienen 8 bytes de longitud).

Si ''y'' es un puntero constante, ¿por qué tiene un tamaño de 20, como la secuencia de valores a los que apunta? ¿El nombre de la variable ''y'' es reemplazado por una dirección de memoria durante el tiempo de compilación siempre que sea apropiado? ¿Son las matrices, entonces, algún tipo de azúcar sintáctico en C que simplemente se traduce a cosas del puntero cuando se compila?



Aquí está el lenguaje exacto del estándar C ( n1256 ):

6.3.2.1 Valores L, matrices y designadores de funciones
...
3 Excepto cuando es el operando del operador sizeof o unary & operator, o es un literal de cadena usado para inicializar una matriz, una expresión que tiene el tipo '''' array of type '''' se convierte en una expresión con el tipo '''' pointer escribir '''' que apunta al elemento inicial del objeto array y no es un valor l. Si el objeto de matriz tiene una clase de almacenamiento de registro, el comportamiento no está definido.

Lo importante a recordar aquí es que hay una diferencia entre un objeto (en términos C, que significa algo que ocupa memoria) y la expresión utilizada para referirse a ese objeto.

Cuando declaras una matriz como

int a[10];

el objeto designado por la expresión a es una matriz (es decir, un bloque contiguo de memoria lo suficientemente grande como para contener 10 valores int ), y el tipo de la expresión a es "matriz de 10 elementos de int ", o int [10] . Si la expresión a aparece en un contexto que no sea como el operando del sizeof & operadores, su tipo se convierte implícitamente a int * , y su valor es la dirección del primer elemento.

En el caso del operador sizeof , si el operando es una expresión de tipo T [N] , entonces el resultado es el número de bytes en el objeto de matriz, no en un puntero a ese objeto: N * sizeof T

En el caso del operador & , el valor es la dirección de la matriz, que es la misma que la dirección del primer elemento de la matriz, pero el tipo de la expresión es diferente: dada la declaración T a[N]; , el tipo de la expresión &a es T (*)[N] , o apunta a la matriz de elementos N de T. El valor es el mismo que a o &a[0] (la dirección de la matriz es la misma que la dirección del primer elemento en la matriz), pero la diferencia en tipos importa. Por ejemplo, dado el código

int a[10]; int *p = a; int (*ap)[10] = &a; printf("p = %p, ap = %p/n", (void *) p, (void *) ap); p++; ap++; printf("p = %p, ap = %p/n", (void *) p, (void *) ap);

verá la salida en el orden de

p = 0xbff11e58, ap = 0xbff11e58 p = 0xbff11e5c, ap = 0xbff11e80

IOW, avanzando p agrega sizeof int (4) al valor original, mientras que el avance ap agrega 10 * sizeof int (40).

Lenguaje más estándar:

6.5.2.1 Suscripción de matriz

Restricciones

1 Una de las expresiones tendrá el tipo '''' puntero al tipo de objeto '''', la otra expresión tendrá un tipo entero, y el resultado tendrá el tipo '''' tipo ''''.

Semántica

2 Una expresión de postfijo seguida de una expresión entre corchetes [] es una designación con subíndice de un elemento de un objeto de matriz. La definición del operador de subíndice [] es que E1[E2] es idéntico a (*((E1)+(E2))) . Debido a las reglas de conversión que se aplican al operador binario + , si E1 es un objeto de matriz (de manera equivalente, un puntero al elemento inicial de un objeto de matriz) y E2 es un número entero, E1[E2] designa el elemento E2 -ésimo de E1 (contando desde cero).

Por lo tanto, cuando subescribe una expresión de matriz, lo que sucede bajo el capó es que se computa el desplazamiento desde la dirección del primer elemento en la matriz y el resultado se desreferencia. La expresion

a[i] = 10;

es equivalente a

*((a)+(i)) = 10;

que es equivalente a

*((i)+(a)) = 10;

que es equivalente a

i[a] = 10;

Sí, la matriz de subscripción en C es conmutativa; por el amor de Dios, nunca hagas esto en el código de producción.

Como la subscripción de matriz se define en términos de operaciones de puntero, puede aplicar el operador de subíndice a las expresiones de tipo de puntero y tipo de matriz:

int *p = malloc(sizeof *p * 10); int i; for (i = 0; i < 10; i++) p[i] = some_initial_value();

Aquí hay una tabla práctica para recordar algunos de estos conceptos:

Declaration: T a[N]; Expression Type Converts to Value ---------- ---- ------------ ----- a T [N] T * Address of the first element in a; identical to writing &a[0] &a T (*)[N] Address of the array; value is the same as above, but the type is different sizeof a size_t Number of bytes contained in the array object (N * sizeof T) *a T Value at a[0] a[i] T Value at a[i] &a[i] T * Address of a[i] Declaration: T a[N][M]; Expression Type Converts to Value ---------- ---- ------------ ----- a T [N][M] T (*)[M] Address of the first subarray (&a[0]) &a T (*)[N][M] Address of the array (same value as above, but different type) sizeof a size_t Number of bytes contained in the array object (N * M * sizeof T) *a T [M] T * Value of a[0], which is the address of the first element of the first subarray (same as &a[0][0]) a[i] T [M] T * Value of a[i], which is the address of the first element of the i''th subarray &a[i] T (*)[M] Address of the i-th subarray; same value as above, but different type sizeof a[i] size_t Number of bytes contained in the i''th subarray object (M * sizeof T) *a[i] T Value of the first element of the i''th subarray (a[i][0]) a[i][j] T Value at a[i][j] &a[i][j] T * Address of a[i][j] Declaration: T a[N][M][O]; Expression Type Converts to ---------- ---- ----------- a T [N][M][O] T (*)[M][O] &a T (*)[N][M][O] *a T [M][O] T (*)[O] a[i] T [M][O] T (*)[O] &a[i] T (*)[M][O] *a[i] T [O] T * a[i][j] T [O] T * &a[i][j] T (*)[O] *a[i][j] T a[i][j][k] T

A partir de aquí, el patrón para las matrices de mayor dimensión debería ser claro.

Entonces, en resumen: las matrices no son punteros. En la mayoría de los contextos, las expresiones de matriz se convierten a tipos de puntero.


En

char hello[] = "hello there" int i;

y

char* hello = "hello there"; int i;

En la primera instancia (actualización de la alineación) se almacenarán 12 bytes para hello con el espacio asignado inicializado para hello allí, mientras que en el segundo hello se almacenará en otro lugar (posiblemente espacio estático) y hello se inicializa para apuntar a la cadena dada.

hello[2] así como *(hello + 2) devolverá ''e'' en ambos casos sin embargo.


Las matrices no son punteros, aunque en la mayoría de las expresiones un nombre de matriz se evalúa como un puntero al primer elemento de la matriz. Entonces, es muy, muy fácil usar un nombre de matriz como un puntero. A menudo verá el término ''decaimiento'' utilizado para describir esto, como en "la matriz descompuesta en un puntero".

Una excepción es como el operando al operador sizeof , donde el resultado es el tamaño de la matriz (en bytes, no en elementos).

Un par de cuestiones adicionales relacionadas con esto:

Un parámetro de matriz para una función es una ficción: el compilador realmente pasa un puntero simple (esto no se aplica a los parámetros de referencia a matriz en C ++), por lo que no puede determinar el tamaño real de una matriz transferida a una función: usted debe pasar esa información de otra manera (tal vez usando un parámetro adicional explícito, o usando un elemento centinela, como lo hacen las cadenas C)

Además, una expresión común para obtener la cantidad de elementos en una matriz es usar una macro como:

#define ARRAY_SIZE(arr) ((sizeof(arr))/sizeof(arr[0]))

Esto tiene el problema de aceptar ya sea un nombre de matriz, donde funcionará, o un puntero, donde dará un resultado sin sentido sin advertencia del compilador. Existen versiones más seguras de la macro (particularmente para C ++) que generarán una advertencia o error cuando se use con un puntero en lugar de una matriz. Vea los siguientes artículos SO:

Nota: C99 Los VLA (matrices de longitud variable) pueden no seguir todas estas reglas (en particular, se pueden pasar como parámetros con el tamaño de matriz conocido por la función llamada). Tengo poca experiencia con VLA, y hasta donde sé, no son ampliamente utilizados. Sin embargo, sí quiero señalar que la discusión anterior podría aplicarse de manera diferente a los VLA.


sizeof se evalúa en tiempo de compilación, y el compilador sabe si el operando es una matriz o un puntero. Para las matrices, da la cantidad de bytes ocupados por la matriz. Su matriz es un char[] (y sizeof(char) es 1), por lo que sizeof le da la cantidad de elementos. Para obtener el número de elementos en el caso general, una expresión común es (aquí para int ):

int y[20]; printf("number of elements in y is %lu/n", sizeof(y) / sizeof(int));

Para punteros sizeof da la cantidad de bytes ocupados por el tipo de puntero sin formato.