Waarom staat C conversies toe tussen incompatibele aanwijzertypen?

Ik vraag me af waarom C99 conversies tussen incompatibele aanwijzertypen toestaat:

void f(int* p)
{
}

void c(char* p)
{
   f(p);
}

Staat C11 ze ook toe? Zijn conformerende implementaties vereist om dergelijke conversies te diagnosticeren?

0

2 antwoord

C99 staat geen impliciete conversie toe tussen pointers van verschillende typen (behalve van/naar void * ). Dit is wat de C99 Rationale zegt:

Het is ongeldig om een ​​aanwijzer naar een object van elk type naar een aanwijzer te converteren naar een object van een ander type zonder een expliciete cast.

Dit is een gevolg van de regels voor toewijzing, die een beperking heeft die een van de volgende zal hebben (als er verwijzingen zijn) (C99 6.5.16.1 "Eenvoudige toewijzing"):

      
  • beide operanden zijn verwijzingen naar gekwalificeerde of niet-gekwalificeerde versies van compatibele typen en het type waarnaar links wordt verwezen heeft alle   qualifiers van het type waarnaar door het recht wordt verwezen;
  •   
  • één operand is een verwijzing naar een object of een incompleet type en de andere is een verwijzing naar een gekwalificeerde of niet-gekwalificeerde versie van de ongeldige versie, en   het type waarnaar links verwijst heeft alle kwalificaties van het type   naar rechts gewezen;
  •   
  • de linker operand is een aanwijzer en de rechterkant is een nul-aanwijzerconstante
  •   

Het doorgeven van een aanwijzer als argument aan een prototype functie volgt dezelfde regels omdat (C99 6.5.2.2/7 "Functieaanroepen"):

Als de uitdrukking die de opgeroepen functie aangeeft, een type heeft   bevat een prototype, de argumenten worden impliciet omgezet, zoals   bij opdracht, naar de typen van de bijbehorende parameters

Zowel C90 en C11 hebben dezelfde formulering.

Ik geloof dat veel compilers (inclusief GCC) deze beperking versoepelen door slechts een waarschuwing te geven omdat er te veel oude code is die ervan afhangt. Houd er rekening mee dat void * een uitvinding was van de ANSI C-standaard, dus een standaardvoorwaarde en waarschijnlijk veel postnormale code die over het algemeen wordt gebruikt char * of < code> int * als een 'generiek' aanwijzertype.

1
toegevoegd

Er bestaat niet zoiets als "incompatibele" aanwijzer types.

Het mooie van C is dat het de programmeur toestaat te doen wat hij wil. Het is aan de programmeur om te beslissen wat compatibel en onverenigbaar is. Andere talen die beweren dat ze de combinatie van " klasse " of " type " dwingen, doen dit op een beperkte manier. Op het moment dat naar de objecten mag worden verwezen, wordt een aanwijzer gebruikt en kan een klassenmismanagement van invloed zijn.

0
toegevoegd
Dit antwoord is onjuist. Er zijn veel niet-compatibele aanwijzertypen, C heeft eigenlijk een veel strenger typingssysteem voor aanwijzers dan voor reguliere variabelen. Dit wordt voornamelijk gereguleerd door de regels in C11 6.3.2.3 met betrekking tot pointerconversie, maar ook door de regels voor toewijzing zoals geciteerd in een ander antwoord.
toegevoegd de auteur Lundin, de bron