Waarom moet ik het datatype elke keer specificeren in C naar printf() en scanf()?

Zoals je kunt zien in het onderstaande codefragment, heb ik één variabele charen één variabele intgedeclareerd. Wanneer de code wordt gecompileerd, moet deze de gegevenstypen van variabelen stren iidentificeren.

Waarom moet ik tijdens het scannen van mijn variabele nogmaals vertellen dat het een string of integer is door %sof %dop te geven voor scanf? Is de compiler niet volwassen genoeg om dat te herkennen toen ik mijn variabelen declareerde?

#include <stdio.h>
int main ()
{
  char str [80];
  int i;
  printf ("Enter your family name: ");
  scanf ("%s",str);  
  printf ("Enter your age: ");
  scanf ("%d",&i);
  return 0;
}

Antwoord 1, autoriteit 100%

Omdat er geen draagbare manier is voor een variabele argumentfunctie, zoals scanfen printfom de typen variabele argumenten te kennen, zelfs niet hoeveel argumenten er worden doorgegeven.

p>

Zie C FAQ: Hoe kan ik ontdekken met hoeveel argumenten een functie daadwerkelijk is aangeroepen?


Dit is de reden dat er ten minste één vast argument moet zijn om het aantal, en misschien de typen, van de variabele argumenten te bepalen. En dit argument (de standaard noemt het parmN, zie C11(ISO/IEC 9899:201x) §7.16 Variabele argumenten ) speelt deze speciale rol en wordt doorgegeven aan de macro va_start. Met andere woorden, je kunt geen functie hebben met een prototype zoals dit in standaard C:

void foo(...);

Antwoord 2, autoriteit 23%

De reden waarom de compiler niet de benodigde informatie kan leveren, is simpelweg omdat de compiler hier niet bij betrokken is. Het prototype van de functies specificeert de typen niet, omdat deze functies variabele typen hebben. De daadwerkelijke gegevenstypen worden dus niet bepaald tijdens het compileren, maar tijdens runtime.
De functie haalt dan het ene argument na het andere uit de stapel. Aan deze waarden is geen type-informatie gekoppeld, dus de enige manier waarop de functie weet hoe de gegevens moeten worden geïnterpreteerd, is door gebruik te maken van de door de beller verstrekte informatie, de format-tekenreeks.

De functies zelf weten niet welke datatypes worden doorgegeven, noch weten ze het aantal doorgegeven argumenten, dus printfkan dit op geen enkele manier zelf beslissen.

p>

In C++ kun je operator overloading gebruiken, maar dit is een heel ander mechanisme. Omdat hier de compiler de juiste functie kiest op basis van de datatypes en de beschikbare overbelaste functie.

Om dit te illustreren, ziet printfer, wanneer gecompileerd, er als volgt uit:

push value1
 ...
 push valueN
 push format_string
 call _printf

En het prototype van printfis dit:

int printf ( const char * format, ... );

Er wordt dus geen type-informatie overgedragen, behalve wat er in de format-string staat.


Antwoord 3, autoriteit 12%

printfis geen intrinsieke functie. Het maakt niet per se deel uit van de C-taal. Het enige dat de compiler doet, is code genereren om printfaan te roepen, waarbij hij welke parameters dan ook doorgeeft. Omdat C geen reflectiebiedt als een mechanisme om type-informatie tijdens runtime te achterhalen, moet expliciet de benodigde informatie verstrekken.


Antwoord 4, autoriteit 11%

Compiler is misschien slim, maar functies printfof scanfzijn dom – ze weten niet wat voor soort parameter je voor elke oproep doorgeeft. Daarom moet je elke keer %sof %ddoorgeven.


Antwoord 5, autoriteit 8%

De eerste parameter is een opmaaktekenreeks. Als u een decimaal getal afdrukt, kan het er als volgt uitzien:

  • "%d"(decimaal getal)
  • "%5d"(decimaal getal opgevuld tot breedte 5 met spaties)
  • "%05d"(decimaal getal opgevuld tot breedte 5 met nullen)
  • "%+d"(decimaal getal, altijd met een teken)
  • "Value: %d\n"(sommige inhoud voor/na het nummer)

etc, zie bijvoorbeeld Plaatsaanduidingen op Wikipedia opmakenom een ​​idee te krijgen in welke tekenreeksen kan bevatten.

Er kan hier ook meer dan één parameter zijn:

"%s - %d"(een tekenreeks, dan wat inhoud, dan een cijfer)


Antwoord 6, autoriteit 7%

Is de compiler niet volwassen genoeg om dat te identificeren toen ik mijn . verklaarde
variabel?

Nee.

Je gebruikt een taal die decennia geleden is opgegeven. Verwacht geen moderne designesthetiek van C, want het is geen moderne taal. Moderne talen hebben de neiging om een ​​kleine hoeveelheid efficiëntie in compilatie, interpretatie of uitvoering in te ruilen voor een verbetering in bruikbaarheid of duidelijkheid. Komt uit een tijd waarin computerverwerkingstijd duur en schaars was, en het ontwerp weerspiegelt dit.

Het is ook waarom C en C++ de talen bij uitstek blijven als je er echt om geeft om snel, efficiënt of dicht bij het metaal te zijn.


Antwoord 7, autoriteit 3%

scanfals prototype int scanf ( const char * format, ... );zegt dat gegeven gegevens worden opgeslagen volgens het parameterformaat op de locaties die worden aangegeven door de aanvullende argumenten .

Het heeft niets te maken met de compiler, het draait allemaal om de syntaxis die is gedefinieerd voor scanf. Het parameterformaat is vereist om scanfte laten weten welke grootte moet worden gereserveerd voor gegevens die moeten worden opgeslagen. ingevoerd.


8

printfen scanfzijn I / O-functies die zijn ontworpen en gedefinieerd op een manier om een ​​regelring en een lijst met argumenten te ontvangen.

De functies kennen niet het type parameter dat er is doorgegeven, en Compiler kan deze informatie ook niet doorgeven.

Other episodes