Al compilar, C descarta [1] la mayoría de tipos de información, dejando solo las compensaciones. Por lo tanto, su función sería compilar a algo como esto, en pseudocódigo:
changeCount:
assign *(*(stack_ptr + offset_element) + offset_Count) + 1
to *(stack_ptr + offset_element) + offset_Count;
assign 1 to return_value;
pop
El stack_ptr es la ubicación del marco de pila que se creó cuando se llama a ChangeCount, la offset_element es la ubicación del argumento elemento, en relación con el stack_ptr, pero ¿qué es offset_Count? Tenga en cuenta que todo lo que sabe el compilador sobre su código es exactamente lo que ha mostrado en su ejemplo; elemento es un puntero genérico, no realmente un puntero a nada. Tendrá que indicar al compilador qué elemento que hace referencia, mediante colada o asignarlo a una variable [2]:
typedef struct { int Count; } counted_t;
int changeCount(void* element)
{
counted_t* counted = element;
counted.Count++;
return 1;
}
Esta función generará esencialmente el mismo código (pseudo) que el anterior, pero el compilador ahora sabe cuál debe ser el desplazamiento del conteo.
Menciona que hay tres posibilidades para el tipo de elemento que apunta. Hay un par de formas de manejar eso: ya sea una unión distinguida o una estructura "heredada". Para una unión distinguida, utilice, por ejemplo, una estructura con un elemento que sea una enumeración que identifique cuál de las tres posibilidades y otro elemento sea una unión de las tres estructuras posibles; esto es más o menos lo que los lenguajes ML (OCaml, Haskell, etc.) llamar a un tipo de datos algebraico o qué unión hay en Pascal. Por "herencia", podría utilizar las definiciones de tipo:
typedef struct { counted_t counted; int i; } counted_int_t;
typedef struct { counted_t counted; double d; } counted_double_t;
typedef struct { counted_t counted; char* s; } counted_charptr_t;
En este caso, se puede utilizar la función ChangeCount arriba y pasar un puntero a una counted_int_t, counted_double_t o counted_charptr_t.
Lo que sucede es que el compilador establecerá las tres estructuras con el elemento Count en las estructuras "descendientes" en el mismo lugar , siempre que el elemento counted_t sea el primero. (Al menos, en cada compilador que he usado y en cada bit de código que he visto. Creo que esto lo convirtió en el estándar C en algún momento, pero es una expresión muy normal.)
[1] Excepto por la información de depuración, si le ha dicho al compilador que lo emita. Sin embargo, su programa no tendrá acceso a esa información, por lo que no sería útil en este caso.
[2] La operación x ++ (postincremento) incrementa la variable (bien, lvalue) a la que se aplica; la asignación en el código original es innecesaria.
¿Por qué no simplemente escribe 'element.Count ++' en lugar de llamar a la función? – LnxPrgr3
No es directamente relevante para la pregunta, pero el comportamiento de 'element.Count = element.Count ++;' no está definido. En aras de la simplicidad, declararé la regla así: no puede modificar un valor más de una vez en la misma expresión. Para detalles completos, vea "6.5 Expressions" en el estándar C. –