unidades suma sacar resultado rapido raiz que proceso para número numeros numero multidimensionales hallar elevar ejemplos cuadrados cuadrado cuadrada como cifras cifra calcular calculadora bidimensionales arreglos aplico c arrays pointers c99 variable-length-array

suma - raiz cuadrada de 4



No puedo entender esta forma de calcular el cuadrado de un número (5)

Obviamente, un truco ... pero una forma de cuadrar un número sin usar el operador * (este era un requisito del concurso de codificación).

(&a)[n]

es equivalente a un puntero a int en la ubicación

(a + sizeof(a[n])*n)

y así toda la expresión es

(&a)[n] -a = (a + sizeof(a[n])*n -a) /sizeof(int) = sizeof(a[n])*n / sizeof(int) = sizeof(int) * n * n / sizeof(int) = n * n

He encontrado una función que calcula el cuadrado de un número:

int p(int n) { int a[n]; //works on C99 and above return (&a)[n] - a; }

Devuelve el valor de n 2 . La pregunta es, ¿cómo hace eso? Después de una pequeña prueba, descubrí que entre (&a)[k] y (&a)[k+1] es sizeof(a) / sizeof(int) . ¿Porqué es eso?


Para comprender este truco, primero debe comprender la diferencia del puntero, es decir, ¿qué sucede cuando se restan dos punteros que apuntan a elementos de la misma matriz ?

Cuando se sustrae un puntero de otro, el resultado es la distancia (medida en elementos de la matriz) entre los punteros. Entonces, si p apunta a a[i] q apunta a a[j] , entonces p - q es igual a i - j .

C11: 6.5.6 Operadores aditivos (p9):

Cuando se restan dos punteros , ambos deben apuntar a elementos del mismo objeto de matriz, o uno más allá del último elemento del objeto de matriz; El resultado es la diferencia de los subíndices de los dos elementos de la matriz . [...]
En otras palabras, si las expresiones P y Q apuntan, respectivamente, a los elementos i -th y j -th de un objeto de matriz, la expresión (P)-(Q) tiene el valor i−j siempre que el valor se ajuste a un objeto de tipo ptrdiff_t .

Ahora espero que conozca la conversión del nombre de la matriz a puntero, a convierte en puntero al primer elemento de la matriz a . &a es la dirección de todo el bloque de memoria, es decir, es una dirección de la matriz a . La siguiente figura lo ayudará a comprender ( lea esta respuesta para obtener una explicación detallada ):

Esto le ayudará a comprender por qué &a tiene la misma dirección y cómo (&a)[i] es la dirección de la matriz i (de igual tamaño que la de a ).

Entonces, la declaración

return (&a)[n] - a;

es equivalente a

return (&a)[n] - (&a)[0];

y esta diferencia dará el número de elementos entre los punteros (&a)[n] y (&a)[0] , que son n matrices de cada uno de n elementos int . Por lo tanto, los elementos de la matriz total son n*n = n 2 .

NOTA:

C11: 6.5.6 Operadores aditivos (p9):

Cuando se restan dos punteros, ambos deben apuntar a elementos del mismo objeto de matriz, o uno más allá del último elemento del objeto de matriz ; El resultado es la diferencia de los subíndices de los dos elementos de la matriz. El tamaño del resultado está definido por la implementación , y su tipo (un tipo entero con signo) es ptrdiff_t definido en el encabezado <stddef.h> . Si el resultado no es representable en un objeto de ese tipo, el comportamiento es indefinido.

Como (&a)[n] no apunta a elementos del mismo objeto de matriz ni a uno pasado el último elemento del objeto de matriz, (&a)[n] - a invocará un comportamiento indefinido .

También tenga en cuenta que, mejor cambiar el tipo de retorno de la función p a ptrdiff_t .


Si tiene dos punteros que apuntan a dos elementos de la misma matriz, entonces su diferencia dará el número de elementos entre estos punteros. Por ejemplo, este fragmento de código generará 2.

int a[10]; int *p1 = &a[1]; int *p2 = &a[3]; printf( "%d/n", p2 - p1 );

Ahora consideremos la expresión

(&a)[n] - a;

En esta expresión, a tipo tiene int * y apunta a su primer elemento.

La expresión &a tiene el tipo int ( * )[n] y apunta a la primera fila de la matriz bidimensional con imagen. Su valor coincide con el valor de los tipos aunque son diferentes.

( &a )[n]

es el enésimo elemento de esta matriz bidimensional con imagen y tiene el tipo int[n] Es decir, es la enésima fila de la matriz con imagen. En la expresión (&a)[n] - a se convierte a la dirección de su primer elemento y tiene el tipo `int *.

Entonces, entre (&a)[n] y a hay n filas de n elementos. Entonces la diferencia será igual a n * n .


a es una matriz (variable) de n int .

&a es un puntero a una matriz (variable) de n int .

(&a)[1] es un puntero de int one int pasado el último elemento de la matriz. Este puntero es n int elementos después de &a[0] .

(&a)[2] es un puntero de int one int pasado el último elemento de matriz de dos matrices. Este puntero tiene 2 * n elementos int después de &a[0] .

(&a)[n] es un puntero de int one int pasado el último elemento de matriz de n matrices. Este puntero es n * n int elementos después de &a[0] . Simplemente resta &a[0] o a y tienes n .

Por supuesto, este es un comportamiento técnicamente indefinido, incluso si funciona en su máquina, ya que (&a)[n] no apunta dentro de la matriz o más allá del último elemento de la matriz (como lo requieren las reglas C de la aritmética del puntero).


Expression | Value | Explanation a | a | point to array of int elements a[n] | a + n*sizeof(int) | refer to n-th element in array of int elements ------------------------------------------------------------------------------------------------- &a | a | point to array of (n int elements array) (&a)[n] | a + n*sizeof(int[n]) | refer to n-th element in array of (n int elements array) ------------------------------------------------------------------------------------------------- sizeof(int[n]) | n * sizeof(int) | int[n] is a type of n-int-element array

Así,

  1. tipo de (&a)[n] es int[n] puntero
  2. tipo de a puntero int

Ahora la expresión (&a)[n]-a realiza una sustracción de puntero:

(&a)[n]-a = ((a + n*sizeof(int[n])) - a) / sizeof(int) = (n * sizeof(int[n])) / sizeof(int) = (n * n * sizeof(int)) / sizeof(int) = n * n