@Ingetledigtnamn: Om du jobbar med små inbyggda system, typ 8/16-bitars mikrokontrollers, borde du redan vara smärtsamt medveten om att man knappast kan lita på att sådana system följer ANSI C. Oavsett om de gör det eller ej måste det finnas en ABI (formell eller ad-hoc), utan en sådan är det inte ens möjligt att skriva en kompilator. En av de viktigaste uppgifterna för en ABI är att specificera de CPU-specifika detaljerna kring hur man gör ett funktionsanrop.
Har jobbat med en kompilatorer för DSPer där man ibland undrar om de som skrivit kompilatorn överhuvudtaget testat något mer komplicerat än "Hello world", där var ett stort problem just att de inte heller följde ANSI-C, vad man i praktiken hade var ett "C-likt" språk. Finns andra exempel där tillverkaren inte ens hävdar att det är rent C utan "based on ANSI-C" som t.ex. Neuron C (Neuron C används i klass av 8-bitars mikrokontrollers som är förvånansvärt kraftfulla).
Det sagt, om ABI säger att man ska köra Pascall-calling convention eller något totalt vansinnigt som att register/stack-användning är totalt olika beroende på antal argument så skulle det jag skrev i mitt första inlägg bli helt fel (men det skulle också omöjliggöra stdarg.h vilket är en del av ANSI-C). Än så länge har jag aldrig stött på ett system där det inte skulle gå att anropa en funktion som tar, säg ett argument av typ "int" via en pekare med typen "funktion som tar två argument av typen int".
Tar man 32/64-bitars CPUer så har de i praktiken en ABI som alla följer, ARM definierar en för sina modeller, MIPS gör samma sak, PowerPC har det i ISA-specifikationen, SPARC har ju till och med namngett register så det bara finns ett rimligt sätt att hantera argument. Alla dessa har en ABI som gör det jag postade väldefinierat och korrekt.
Det jag skrev i första inlägget är som sagt odefinierat i ANSI-C, men inte p.g.a det du refererar till. Läs exakt vad de meningar från C11 standarden (som för tillfället implementeras av noll kompilatorer, men C89 säger ungefär samma sak fast med färre ord) som du markerade säger:
"If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters."
Vad detta säger är att detta inte är tillåtet
int foo(int x, int y); /* prototyp för 'foo' */
void bar()
{
foo(1);
foo(1,2,3);
}
"If the expression that denotes the called function has a type that does not include a prototype, the integral promotions are performed on each argument and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not agree with the number of parameters, the behavior is undefined."
Vad detta säger är att detta kommer bli fel
i någon C-fil finns, ingen "static" så extern länkning
double foo(float x, float y)
{
return x * y;
}
...
i en annan fil anropar jag "foo" utan att ha en prototyp, detta kompilerar då det inte finns något formellt fel
void bar()
{
/* argumenten kommer skickas via heltalsregister alt.
* som heltal på stacken ("promotion" är till "int" i detta fall),
* men mottagaren förväntar sig 2st SP flytta, inte 3 intsl!!!
*/
char x = 10;
double ret = foo(x, 20, 30);
...
}
Standarden säger ändå att det jag skrev initialt är odefinierat (av ANSI-C), raden i fråga är denna från kapitel J.2 "Undefined behavior" i C11
"A pointer is used to call a function whose type is not compatible with the referenced type"
Och det p.g.a definitionen av vad som är "compatible", även om det finns ett "loophole" i form av att funktioner som använder sig av K&R stil inte tar med sin argumentlista i jämförelsen över vad som är "compatible". Så skulle kunna skriva om exemplet i K&R stil och på så sätt vara ANSI-C kompatibel, rätt uppenbart att detta är ett område man helt enkelt inte detaljgranskat.
I korthet: i praktiken kommer det fungera på var enda kompilator för var enda CPU-arkitektur där det är möjligt att göra indirekta anrop. Finns det någon ASIC/FPGA som inte stödjer indirekta anrop går det överhuvudtaget inte att jobba med pekare till funktioner så problemställningen är irrelevant.