sirven que punteros puntero para los funciones ejemplos con cadenas arreglos aritmetica apuntadores c pointers language-lawyer variable-length-array

que - punteros en c ejemplos



¿Cuál es el tipo de puntero a una matriz de longitud variable en C? (1)

Con un VLA, el operador sizeof no es una constante de compilación. Se evalúa en tiempo de ejecución. En su pregunta, el tipo de &arr es int (*)[n]; - un puntero a una matriz de n valores del tipo int , donde n es un valor en tiempo de ejecución. Por lo tanto, como observa, &arr + 1 (los paréntesis no son necesarios, excepto alrededor de los comentarios entre paréntesis que indican que los paréntesis no son necesarios) es el comienzo de la matriz después de arr : la dirección es bytes sizeof(arr) más allá del valor de arr .

Usted podría imprimir el tamaño de arr ; le daría el tamaño apropiado ( printf() modifier z ). Podría imprimir la diferencia entre &arr + 1 y arr y obtendría el tamaño como un ptrdiff_t ( printf() t ).

Por lo tanto:

#include <stdio.h> int main(void) { int n; if (scanf("%d", &n) == 1) { int arr[n]; void* ptr = (&arr) + 1; printf("%p/n", arr); printf("%p/n", ptr); printf("Size: %zu/n", sizeof(arr)); printf("Diff: %td/n", ptr - (void *)arr); } return 0; }

Y dos ejecuciones de muestra (nombre del programa vla59 ):

$ vla59 23 0x7ffee8106410 0x7ffee810646c Size: 92 Diff: 92 $ vla59 16 0x7ffeeace7420 0x7ffeeace7460 Size: 64 Diff: 64 $

Sin recompilación, pero sizeof() es correcto cada vez que se ejecuta el programa. Se calcula en tiempo de ejecución.

De hecho, incluso puedes usar un bucle con un tamaño diferente cada vez:

#include <stdio.h> int main(void) { int n; while (printf("Size: ") > 0 && scanf("%d", &n) == 1 && n > 0) { int arr[n]; void* ptr = (&arr) + 1; printf("Base: %p/n", arr); printf("Next: %p/n", ptr); printf("Size: %zu/n", sizeof(arr)); printf("Diff: %td/n", ptr - (void *)arr); } return 0; }

vla11 de la muestra de vla11 :

$ vla11 Size: 23 Base: 0x7ffee3e55410 Next: 0x7ffee3e5546c Size: 92 Diff: 92 Size: 16 Base: 0x7ffee3e55420 Next: 0x7ffee3e55460 Size: 64 Diff: 64 Size: 2234 Base: 0x7ffee3e53180 Next: 0x7ffee3e55468 Size: 8936 Diff: 8936 Size: -1 $

Aquí hay un programa corto de C que solicita al usuario un número, crea una matriz de longitud variable de ese tamaño y luego utiliza la aritmética de punteros para pasar por encima de los elementos asignados:

#include <stdio.h> int main() { /* Read a size from the user; inhibits compiler optimizations. */ int n; scanf("%d", &n); // Yes, I should error-check. :-) /* We now have a VLA. */ int arr[n]; /* What is the type of &arr? */ void* ptr = (&arr) + 1; /* Seems like this skipped over things properly... */ printf("%p/n", arr); printf("%p/n", ptr); }

Puedes probar esto en ideone si quieres. La salida sugiere que la línea

void* ptr = (&arr) + 1;

toma la dirección de arr y, de forma consciente del tamaño, recorre todos los n elementos de la matriz de longitud variable.

Si esto no fuera una matriz de longitud variable, me sentiría completamente cómodo con cómo funciona esto. El compilador sabría el tipo de arr (sería int (*) [K] para alguna constante K ), así que cuando agregamos uno a &arr , podría saltar el número correcto de bytes.

Está claro cómo, en el tiempo de ejecución, podríamos evaluar (&arr) + 1 . El compilador oculta el tamaño de arr algún lugar de la pila, y cuando agregamos uno a (&arr) , sabe cargar ese tamaño para calcular cuántos bytes omitir.

Sin embargo, lo que no sé es qué es el lenguaje que dice el tipo de expresión &arr . ¿Se le asigna algún tipo estático que indica que es una matriz de longitud variable (algo como int (*) [??] )? ¿Dice la especificación "el tipo de expresión es int (*) [K] , donde K es del tamaño que se asigna a la matriz en tiempo de ejecución?" ¿La especificación no permite tomar la dirección de una matriz de longitud variable, y el compilador simplemente pasa a permitirlo?