Waarom compileert een functie zonder parameters (vergeleken met de feitelijke functiedefinitie)?

Ik ben net iemands C-code tegengekomen waarvan ik niet weet waarom deze wordt gecompileerd. Er zijn twee punten die ik niet begrijp.

  1. Het functie-prototypeheeft geen parameters vergeleken met de daadwerkelijke functiedefinitie.

  2. De parameter in de functiedefinitieheeft geen type.


#include <stdio.h>
int func();
int func(param)
{
    return param;
}
int main()
{
    int bla = func(10);    
    printf("%d", bla);
}

Waarom werkt dit?
Ik heb het in een aantal compilers getest en het werkt prima.


Antwoord 1, autoriteit 100%

Alle andere antwoorden zijn correct, maar alleen voor voltooiing

Een functie wordt op de volgende manier gedeclareerd:

 return-type function-name(parameter-list,...) { body... }

return-typeis het type variabele dat de functie retourneert. Dit kan geen arraytype of functietype zijn. Indien niet gegeven, dan int
wordt verondersteld
.

functienaamis de naam van de functie.

parameterlijstis de lijst met parameters die de functie aanneemt, gescheiden door komma’s. Als er geen parameters zijn gegeven, dan is de functie
neemt er geen en moet worden gedefinieerd met een lege set van
haakjes of met het trefwoord void. Als er geen variabel type vooraan staat
van een variabele in de parameterlijst, dan wordt int aangenomen
. Arrays en
functies worden niet doorgegeven aan functies, maar worden automatisch geconverteerd
naar wijzers. Als de lijst wordt afgesloten met een weglatingsteken (,…), dan
er is geen vast aantal parameters. Opmerking: de header stdarg.h kan zijn
gebruikt om toegang te krijgen tot argumenten bij het gebruik van een weglatingsteken.

En nogmaals voor de volledigheid. Van C11-specificatie 6:11:6(pagina: 179)

Het gebruik van functiedeclarators met lege haakjes(niet
parametertype declarators in prototype-formaat) is een verouderde
functie
.


Antwoord 2, autoriteit 59%

In C betekent func()dat je een willekeurig aantal argumenten kunt doorgeven. Als je geen argumenten wilt, moet je declareren als func(void). Het type dat u doorgeeft aan uw functie, indien niet gespecificeerd, is standaard int.


Antwoord 3, autoriteit 22%

int func();is een verouderde functiedeclaratie uit de tijd dat er geen C-standaard was, dat wil zeggen de dagen van K&RC(vóór 1989, het jaar de eerste “ANSI C”-standaard werd gepubliceerd).

Onthoud dat er geen prototypes waren in K&R Cen dat het trefwoord voidnog niet was uitgevonden. Het enige wat je kon doen was de compiler vertellen over het retourtypevan een functie. De lege parameterlijst in K&R C betekent “een niet gespecificeerd maar vast” aantal argumenten. Fixed betekent dat je de functie elke keer met hetzelfdeaantal args moet aanroepen (in tegenstelling tot een variadischefunctie zoals printf, waarbij het nummer en type kan per gesprek verschillen).

Veel compilers zullen deze constructie diagnosticeren; in het bijzonder gcc -Wstrict-prototypeszal je vertellen “functiedeclaratie is geen prototype”, wat perfect is, omdat het er uit zietals een prototype (vooral als je vergiftigd door C++!), maar is dat niet. Het is een oude stijl K&R C aangifte type aangifte.

Vuistregel:Laat een lege parameterlijstdeclaratie nooit leeg, gebruik int func(void)om specifiek te zijn.
Dit maakt de K & AMP; R Retourtype-verklaring in een goed C89-prototype. Compilers zijn blij, ontwikkelaars zijn blij, statische dammen zijn blij. Die misleiden door ^ w ^ Wfond of C++ May Circle, omdat ze extra tekens moeten typen wanneer ze hun vaardigheden in vreemde taal proberen uit te oefenen: -)


4, Autoriteit 19%

  • De lege parameterlijst betekent “alle argumenten”, dus de definitie is niet verkeerd.
  • Het ontbrekende type wordt verondersteld intte zijn.

Ik zou een build beschouwen die dit passeert om te ontbreken in geconfigureerde waarschuwing / foutniveau, het heeft geen zin om dit toe te staan ​​voor de daadwerkelijke code.


5, Autoriteit 5%

C wordt verondersteld intAls er geen type wordt gegeven op Function Retourtype en Parameterlijst . Alleen voor deze regel zijn na rare dingen mogelijk.

Een functiedefinitie ziet er als volgt uit.

int func(int param) { /* body */}

Als het een prototype schrijft

int func(int param);

In prototype kunt u alleen het type parameters opgeven. De naam van de parameters is niet verplicht. Dus

int func(int);

Ook als u geen parametertype opgeven, maar de naam intwordt aangenomen als type.

int func(param);

Als u verder gaat, volgende werken.

func();

Compiler veronderstelt int func()wanneer u func()schrijft. Maar plaatst u niet func()IN EEN FUNCTION-instantie. Dat is een functie-oproep


Antwoord 6, autoriteit 2%

Wat het parametertype betreft, er zijn hier al juiste antwoorden, maar als je het van de compiler wilt horen, kun je proberen wat vlaggen toe te voegen (vlaggen zijn sowieso bijna altijd een goed idee).

het compileren van je programma met gcc foo.c -Wextrakrijg ik:

foo.c: In function ‘func’:
foo.c:5:5: warning: type of ‘param’ defaults to ‘int’ [-Wmissing-parameter-type]

vreemd genoeg snapt -Wextradit niet voor clang(het herkent -Wmissing-parameter-typeom de een of andere reden niet, misschien voor de historische hierboven genoemde) maar -pedanticdoet:

foo.c:5:10: warning: parameter 'param' was not declared, 
defaulting to type 'int' [-pedantic]
int func(param)
         ^
1 warning generated.

En voor problemen met het prototype, zoals hierboven al gezegd, verwijst int func()naar willekeurige parameters, tenzij je het expliciet definieert als int func(void), wat je dan de fouten zoals verwacht:

foo.c: In function ‘func’:
foo.c:6:1: error: number of arguments doesn’t match prototype
foo.c:3:5: error: prototype declaration
foo.c: In function ‘main’:
foo.c:12:5: error: too many arguments to function ‘func’
foo.c:5:5: note: declared here

of in clangals:

foo.c:5:5: error: conflicting types for 'func'
int func(param)
    ^
foo.c:3:5: note: previous declaration is here
int func(void);
    ^
foo.c:12:20: error: too many arguments to function call, expected 0, have 1
    int bla = func(10);
              ~~~~ ^~
foo.c:3:1: note: 'func' declared here
int func(void);
^
2 errors generated.

Antwoord 7

Als de functiedeclaratie geen parameters heeft, d.w.z. leeg, dan neemt het een niet-gespecificeerd aantal argumenten. Als je wilt dat er geen argumenten voor nodig zijn, verander het dan in:

int func(void);

Antwoord 8

Dit is de reden waarom ik mensen meestal adviseer om hun code te compileren met:

cc -Wmissing-variable-declarations -Wstrict-variable-declarations -Wold-style-definition

Deze vlaggen dwingen een aantal dingen af:

  • -Wmissing-variabele-declarations: Het is onmogelijk om een ​​niet-statische functie te declareren zonder eerst een prototype te krijgen. Dit maakt het waarschijnlijker dat een prototype in een headerbestand overeenkomt met de daadwerkelijke definitie. Als alternatief dwingt het af dat u het statische trefwoord toevoegt aan functies die niet openbaar zichtbaar hoeven te zijn.
  • -Wstrict-variabele-declarations: Het prototype moet de argumenten correct weergeven.
  • -Wold-style-definition: De functiedefinitie zelf moet ook de argumenten correct weergeven.

Deze vlaggen worden ook standaard gebruikt in veel Open Source-projecten. FreeBSD heeft deze vlaggen bijvoorbeeld ingeschakeld bij het bouwen met WARNS=6 in uw Makefile.


Antwoord 9

In de oude-stijl declarator,

de identificatielijst moet ontbreken, tenzij
de declarator wordt gebruikt in de kop van een functiedefinitie
(Paragraaf A.10.1). Er is geen informatie over de typen parameters:
geleverd door de aangifte. Bijvoorbeeld de verklaring

int f(), *fpi(), (*pfi)();

declareert een functie f die een geheel getal retourneert, een functie fpi die een aanwijzer naar een geheel getal teruggeeft, en een aanwijzer pfi naar een functie die een geheel getal teruggeeft. In geen van deze zijn de parametertypes >gespecificeerd; ze zijn ouderwets.

In de verklaring nieuwe stijl

int strcpy(char *dest, const char *source), rand(void);

strcpy is een
functie retourneert int, met twee argumenten, de eerste een teken
aanwijzer, en de tweede een aanwijzer naar constante tekens

BRON:- K&R-boek

Ik hoop dat het je twijfel heeft weggenomen..

Other episodes