You are on page 1of 22

Enkel stilguide fr C++

Tommy Olsson, <tao@ida.liu.se>


Linkpings universitet och Tekniska hgskola
Institutionen fr datavetenskap
Programvara och system
581 83 Linkping

Innehll
Inledning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Kllkodsfiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Uppdelning av kllkod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Filnamn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Inkluderingsfiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Kommentarer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Namngivning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Kodningsstil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Tomrum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Satsblock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Styrsatser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Funktioner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Pekare och referenser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Meddelanden och ledtexter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Utmatning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Variabler och konstanter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Variabler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Konstanter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Uttryck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Styrsatser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
If-satsen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
switch-satsen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
for-satsen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
while-satsen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
do-while-satsen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
vrigt rrande styrsatser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Funktioner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Funktionsparametrar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Funktionsverlagring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Returtyper och returvrden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Inline-funktioner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Temporra objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Allmnt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Pekare och dynamisk minneshantering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Pekare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Dynamisk minneshantering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Klasser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
tkomstrttighet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Inline-funktioner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
const-medlemsfunktioner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Konstruktorer och destruktorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Tilldelningsoperatorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Operatorverlagring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Returtyper fr medlemsfunktioner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Arv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Undantag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Kodmallar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Inkluderingsfiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Inline-definitionsfiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Implementeringsfiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Klassbeskrivningar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Funktionsbeskrivningar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

ii

Inledning
Stil r en ofta frbisedd men mycket viktig aspekt d man skriver. Sttet att skriva en text har en direkt
inverkan p lsbarhet och frstelse. Programmeringsstil, i meningen hur man skriver kllkod, r ocks
ngot som ofta frbises. Program mste vara lsbara och frsteliga fr mnskliga lsare och inte bara
fr maskiner. Detta r viktigt fr att skapa programvara av god kvalitet, som inte enbart uppfyller
anvndarens krav utan ocks kan utvecklas inom givna tids- och kostnadsramar.
Ett program vars innebrd r klar och tydlig har en strre sannolikhet att ocks vara korrekt och
plitligt. D man ska modifiera ett program krvs en ingende frstelse av programkoden, vilket i hg
grad stds av klarhet. Underhll av programvara (ofta en frga om utveckling) r kostsamt och pgr
under ett systems hela livstid. Klarhet spelar drmed en viktig roll i att hlla underhllskostnader nere.
Vad utmrker en klar, lsbar och begriplig text? Det kan vara allt frn smtt till stort. En del kan man
relatera till hur vi skriver vanlig text, fr att gra den lsbar och begriplig. Vi bygger upp text med
lmpligt och korrekt ordval, delar upp texten i satser, som sammanstlls i stycken, osv. ven insttning
av mellanrum och tomma rader, liksom interpunktering r viktigt. Uppdelning av en text i stycken,
avsnitt och kapitel kan man i program jmfra med t.ex. anvndning av sammansatta satser, underprogram, moduler och liknande. Sedan finns naturligtvis en hel del som r specifikt fr programkod.
God lsbarhet uppnr man bl.a. genom enhetlighet, enkelhet (krngla inte till koden i ondan), uppdelning av strre problem i mindre delproblem (sndra och hrska) och genom att undvika underfrstdda
eller svrbegripliga egenskaper hos programsprket. Bra program skapas vanligtvis genom ett gediget
ingenjrsarbete.
Mnga programvarufretag har programmerarhandbcker med regler och rekommendationer fr hur
fretagets programvara ska skrivas. Syftet r att programvara som produceras inom olika projekt och av
olika programmerare ska vara ltt att lsa, frst och underhlla och ven vara enhetlig.
Denna stilguide r framtagen fr att anvndas i kurser. Ett syfte r att frska visa p god programmeringsstil (detaljer kan alltid diskuteras!) i allmnhet och speciellt fr C++-programmering. Ett annat
syfte r att dessa regler och rekommendationer ska kunna anvndas fr bedmning av laborationsuppgifter och projekt.
Fljande beteckningar anvnds i denna stilguide (vad som ska vara regel resp. rekommendation kan
naturligtvis ocks diskuteras):
Regler markeras med indragna stycken med ett i vnstermarginalen. Regler r normalt tvingande,
men det kan finnas enstaka tillfllen d det kan vara motiverat att frng en regel.
! Rekommendationer anges med indragna stycken med ett utropstecken i vnstermarginalen.
Rekommendationer r lmpliga att flja, svida det ej finns goda skl att gra annat.
Stil kan anses vara en frga om personlig smak. S lnge man skriver enbart fr sig sjlv fr man naturligtvis vlja den stil man sjlv fredrar. Ska man arbeta i ett projekt eller i ngot annat sammanhang
med flera inblandade, fr man vara beredd p att gemensamma stilregler kan finnas och ska fljas.

Kllkodsfiler
Uppdelning av kllkod
Moduluppdelning kan gras genom att programkod frdelas mellan olika kllkodsfiler.
deklarationer som utgr det externa grnssnittet fr en modul skrivs i en inkluderingsfil.
kod som implementerar en modul, t.ex. funktionsdefinitioner, skrivs i en implementeringsfil.
inline-deklarerade funktioner skrivs med frdel i en inline-deklarationsfil.
Filnamn
Deklarationer av intresse fr en anvndare, t.ex. funktionsdeklarationer, klassdefinitioner, etc., skrivs i
inkluderingsfiler. Definitioner av funktionerna respektive klassers medlemsfunktioner skrivs i motsvarande implementeringsfiler.

Om det finns inline-deklarerade funktioner (kan ej skrivas i en implementeringsfil) r det lmpligt


att placera dess p en separat inline-definitionsfil, vilken inkluderas sist i inkluderingsfilen ifrga.
Fr kod som utgr klass- eller funktionsmallar finns lite olika modeller fr hur sdan kod ska gras tillgnglig fr anvndande program. I vissa system finns namngivningsregler fr filer innehllande mallar.
Syftet med fljande regler r att ge filnamn en enhetlig tolkning utifrn filnamnens suffix.
Inkluderingsfiler i C++ ska ha filtypen .h, eller om man uttryckligen vill ange att det r en fil med
C++-specifik kod, .hh. Inkluderingsfiler som innehller kod som ven accepteras av C-kompilatorer br ha filtypen .h.
Implementeringsfiler i C++ ska ha filtypen .cc. Om den kompilator som anvnds ej accepterar
filtypen .cc, ska .C, .cpp , eller .cxx anvndas i stllet.
Definitionsfiler med inline-deklarerade funktioner ska ha filtypen .icc.
Vissa avlusare kan ej hantera inline-funktioner. Om sdana funktioner skrivs i en separat inline-definitionsfil, kan man lsa detta med preprocessorn. Vid normal kompilering inkluderas .icc-filen i .hh-filen.
Vid kompilering fr avlusning, inkluderas i stllet .icc-filen i .cc-filen varvid nyckelordet inline tas bort
av preprocessorn, se fljande exempel.
// Fil: Stack.hh
class Stack {

};
#ifndef DEBUG
#include Stack.icc
#endif

// Fil: Stack.cc
#include STACK.hh
#ifdef DEBUG
#define inline
#include Stack.icc
#undef inline
#endif

Fljande rekommendationer avser att ge vgledning fr hur kllkod br delas upp mellan olika filer.
! En inkluderingsfil br ej innehlla mer n en klassdefinition. Det r ofta enklare att underhlla
program om denna rekommendation fljs.
! En inkluderingsfil som innehller en klassdefinition br ha ett namn p formen klassnamn.hh.
! Placera maskinberoende kod i speciella filer, s att sdan kod blir ltt att lokalisera d koden ska
anpassas till en annan maskintyp.
Inkluderingsfiler
Varje inkluderingsfil ska innehlla en mekanism fr att frhindra upprepad inkludering av filen, en
gard. Garder konstrueras med fljande preprocessorteknik:
#ifndef STACK_HH
#define STACK_HH
...
#endif

D fljande slags definitioner anvnds mste de inkluderas som separata inkluderingsfiler.


Klasser som anvnds som basklasser eller medlemsvariabler.
Klasser som frekommer som parametertyper eller returtyper i funktionsprototyper eller
medlemsfunktionsprototyper.
Prototyper fr funktioner eller medlemsfunktioner, vilka anvnds i inline-deklarerade medlemsfunktioner som definieras i filen.
Antalet filer som inkluderas i en viss fil br minimeras.

Klassdefinitioner fr klasser som enbart refereras via pekare (*) eller referenser (&) ska ej infogas
via inkluderingsfiler. Det r i dessa fall tillrckligt med en deklaration, t.ex.:
class A;

// pekare och referenser till A kan deklareras

Alternativt kan varje deklaration av en pekare eller referens till klassen ange nyckelordet class, t.ex.:
class B
{
class A*
};

a_ptr;

Anvnd aldrig relativa filnamn i inkluderingsdirektiv (#include). Ange i kompileringskommandot


eventuella tillgg d det gller inkluderingsskvgen med preprocessorflaggan -I.
Varje implementeringsfil ska inkludera filer som innehller fljande slags deklarationer, om de
anvnds i de funktioner som definieras i filen:
typ- och funktionsdeklarationer
variabel- och medlemsfunktionsdeklarationer
! Inkludera aldrig andra filer i en .icc-fil.

Kommentarer
Att skriva bra kommentarer r svrt! Man ska kommentera lagom mycket och rtt saker. Ett viktigt
syfte med kommentarer r att den som lser programkoden ska kunna stta sig in i hur programmet
fungerar, fr att t.ex. rtta fel eller modifiera programmet. En grundfrutsttning man ska anta r att
lsaren r datorkunnig och har (grundlggande) kunskaper om programsprket. Kommentera drfr
inte sdant som r uppenbart av sjlva koden och inte heller detaljer.
Utg dremot frn att lsaren vet nstan inget om vad programmet ska gra. Tnk p att ett kodavsnitt
som frefaller intuitivt fr dig, d du skriver det, kanske inte r det fr en annan lsare eller ens fr dig
sjlv senare. Kommentarer i program br i hg grad beskriva vad som hnder.
Ibland kan det ocks vara ndvndigt att frklara hur saker grs, t.ex. att ett komplicerat kodavsnitt kan
vara en implementering av en knd algoritm (men att det kanske inte r uppenbart av koden och dessutom kan det vara vrdefullt att f den upplysningen serverad) eller, om s inte r fallet, man i stllet
beskriver hur det gr till.
Annat som r viktigt att beskriva r begrnsningar, t.ex. att en datastruktur har en begrnsad storlek.
Kommentering ska gras p ett kompakt och ltt lokaliserbart stt. En strategisk kommentar skrivs fre
en klass eller ett funktion och beskriver klassens resp. funktionens syfte och egenskaper. En taktisk
kommentar beskriver vad en enskild rad eller ett kortare satsavsnitt i koden gr. Om en taktisk kommentar avser en enskild rad br den, om mjligt, placeras sist p raden.
Med en systematisk och vl genomtnkt namngivning och genom vlstrukturerad kod blir behovet av
taktiska kommentarer i koden mindre.
Varje kllkodsfil ska dokumenteras inledningsvis, dr dess namn och innehll framgr.
Varje klass och funktion ska ha en strategisk kommentar som beskriver dess roll.
! Kommentera efter hand som olika programdelar frdigstlls.
! Se till att kommentarer r korrekta. Var kortfattad men fullstndig.
! Uppdatera kommentarer samtidigt som ndringar grs i koden.

Namngivning
Namngivning r centralt fr lsbarhet och frstelse av program. Genom att tillmpa en systematiska
namngivning underlttas identifieringen av olika namngivna storheter och frstelsen av koden kar,
samtidigt som behovet av kommentering minskar.
Anvnd alltid meningsfulla och rttvisande namn p variabler, konstanter, funktioner, datatyper,
klasser, programlgen, etc.
Undvik frkortningar eftersom andra kan gra en helt annan uttydning av en frkortning n den man
sjlv tycker r helt intuitiv.

Anvnd meningsfulla namn.


Anvnd normalt inte enbokstavsnamn. I vissa fall kan slingvariabler (t.ex. i en for-satser) undantas
frn denna regel, om det bara r frga om att stega igenom ett antal heltalsvrden. Sdana skrivs av
tradition ofta med enbokstavsnamn, i, j, .
Frsk begrnsa namn till en rimlig lngd, men efterstrva hela ord.
Namn p konstanter skrivs med genomgende stora bokstver, t ex MAX.
Namn p variabler och funktioner skrivs med genomgende sm bokstver, t ex print.
Namn p abstrakta datatyper, poster (struct), typdefinitioner (typedef) och upprkningstyper
(enum) ska inledas med stor bokstav och fr vrigt skrivas med sm bokstver, t ex Stack.
I namn sammansatta av flera ord ska orden skrivas med understrykningstecken emellan, fr att gra
namnen enkla att lsa. Hur frsta bokstaven i respektive ord ska skrivas bestms av namngivningsreglerna ovan, t ex print_line, Tree_Node, MAX_SIZE.
Inled ej identifierare med enkelt eller dubbelt understrykningstecken, eller understrykningstecken
fljt av en stor bokstav, fr att undvika namnkollisioner med biblioteksnamn.
! Eftersom reserverade ord och namn i standardomgivningen r p engelska, ger det mest enhetligt
intryck om man vljer engelska ven fr egna namn.
Anm. I en del ldre system kan t.ex. externa namn vara begrnsade till endast 6 tecken och lngre namn
blir avhuggna med risk fr att avhuggning ger namnkollisioner d namn r lika i de 6 frsta tecknen.

Kodningsstil
Regler och rekommendationer som rr kodningsstil kan ven finnas under andra avsnitt. Fr klasser
hnvisas helt till avsnittet om klasser.
Format
! Skriv en deklaration per rad, t.ex. en variabeldeklaration eller en enkel sats per rad.
! Indrag av rader frn vnstermarginalen ska systematiskt avspegla det logiska nstlingsdjupet och ska
vara 2, 3 eller 4 positioner (ej blandat).
! Olika kodstycken (t ex delbearbetningar) avgrnsas med en tomrad eller med en kommentar.
Tomrum
Tomrum spelar en viktig roll fr lsbarheten. Grundregeln r att anvnda tomrum i enlighet med hur
mellanrum stts in och styckesuppdelning grs i vanlig text. Anvnd omsorgsfullt tomrum fr att dela
upp och dra uppmrksamhet till olika delar av program.
Stt in ett mellanrumstecken efter varje komma i en parameterlista, men ej fre.
Stt in ett mellanrumstecken fre och efter varje tvstllig operator. Operatorerna -> och . ska dock
ej ska ha ngot mellanrum fre eller efter sig. I sammansatta uttryck, d det gller deluttryck p den
innersta nivn, kan man ibland utelmna mellanrum och t.ex. skriva x = a*b + c*d - e/f.
Stt ej in mellanrumstecken omedelbart efter en vnsterparentes eller fre en hgerparentes.
Stt ej in mellanrumstecken fre semikolon.
Stt in ett mellanrumstecken fre en vnsterparentes, utom fre en parameterlista.
Stt in en tom rad fr att separera deklarationer frn satser, fr att separera satsavsnitt som motsvarar
olika delmoment i en berkning, fr att separera funktionsdefinitioner frn varandra, etc. Var
systematisk med antalet tomma rader i olika situationer. Stt inte in fr mnga tomma rader i fljd,
en eller tv kan ofta vara lagom.
! Stt ej in tomma rader som delar upp kod som hr intimt samman. T.ex. en tom rad fre while i en
do-while-sats ger ju ltt intrycket av att det i stllet r frga om en while-sats som pbrjas.

Satsblock
I C++ behver satsblocket, till fljd av de sammansatta satserna syntax, ofta komma till anvndning fr
att gruppera sammanhrande satser. Satsblockets patenteser r dock svrplacerade, om man vill ha en
snygg och enhetlig kod. Hur parenteserna ska placeras har debatterats en hel del och det har utvecklats
olika stilar, med sina fr- och nackdelar. En variant r att placera blockparenteserna p egna rader och i
samma kolumn direkt fre och efter blocket. Parenteserna placeras med samma indrag som den styrsats
de tillhr. Denna stil anses av mnga vara att fredra ur lsbarhetssynpunkt. Exempel:
if (...)
{
...
}
else
{
...
}

while (...)
{
...
}

do
{
...
}
while (...);

En liten variation p ovanstende r att dra in blockparenteserna motsvarande ett indragssteg och
satserna i blocket ytterligare ett steg. Det har flera nackdelen, dels fr koden ett mer oroligt intryck
och dessutom motsvarar inte indraget frn vnstermarginalen lngre det logiska nstlingsdjupet.
Ett alternativ till ovanstende r att flytta upp inledande blockparenteser till sist p raden innan. Detta
ger ngot kompaktare kod och ytterligare fokusering p det vsentliga, nmligen nyckelorden i styrsatsen ifrga (den enda intressanta parentesen r egentligen den allra sista). Exempel:
if (...) {

}
else {

while (...) {

do {

}
while (...);

Man se ibland kod enligt exemplen ovan dr else i if-atsen respektive while i do-while-satsen placerats
efter spetsparentesen p raden innan. Det har den eventuella frdelen att eliminera en tom rad men
nackdelen att matchande nyckelord (if-else respektive do-while) inte fr samma indrag, vilket ger en
viss obalans.
Styrsatser
! I styrsatser, (if, else, for, while och do-while) br alltid satsdelen utgras av ett satsblock, ven om
enbart en sats ingr. Detta medfr enhetlighet, klarhet och ndringsbarhet.
! Styrsatser br vara korta.
Funktioner
Program, som inte r mycket enkla, ska delas upp i funktioner. Varje funktion ska helst bara gra en sak.
En sak kan naturligtvis vara ngot komplext, men i sdana fr man dela upp arbetet p flera funktioner, som var och en gr sin del.
Funktionsdeklarationer ska skrivas p prototypformat, dvs. med datatyperna fr argumenten
angivna, drfr att detta ger kompilatorn mjlighet att gra typkontroll.
! I en funktionsdeklaration br den inledande parentesen och frsta argumentet, om sdant finns,
skrivas p samma rad som funktionsnamnet. Om utrymme finns br ven vriga argument och den
avslutande parentesen skrivas p samma rad., t.ex.:
double fun(int, double);
I annat fall ska varje ytterligare parameter skrivas p en egen rad och med den avslutande parentesen direkt
efter det sista parametern.

! I en funktionsdefinition kan funktionens returtyp skrivas p en egen rad ovanfr funktionsnamnet.


Detta gr funktionsnamnet lttare att se (det finns betydligt mer komplicerade fall n nedanstende,
dr frdelen med detta skrivstt blir mer uppenbar, t.ex. i samband med mallklasser):
double
fun(int i, double d)
{

! Funktioner br vara korta.


Pekare och referenser
! Operatorerna * och & br vara skrivna i direkt anslutning till typnamnen i deklarationer och definitioner, eftersom de r en del av typdefinitionen och fljaktligen st ihop med dess vriga delar. Ex:
Node*

next;

! Datatypbeskrivningar som innehller operatorerna * och & br typdefinieras, t.ex.:


typedef

Node*

Node_Pointer;

Meddelanden och ledtexter.


Var inte nedltande.
Frsk inte vara humoristisk.
! Var informativ men kortfattad.
! Ange specifika inmatningsval i ledtexter, i frekommande fall.
! Ange i ledtexter om ett frvald vrden kommer att anvndas om inget vrde ges.
Utmatning
Rubricera all utmatning tydligt.
Presentera all information fr anvndaren p ett enhetligt stt.

Variabler och konstanter


Variabler och konstanter (symboliska konstanter) har mycket gemensamt. Det som egentligen skiljer r
att en variabels vrde kan ndras under programkrningen, vilket inte en konstants vrde kan nr den
vl initierats.
Variabler
Variabler ska deklareras med minsta mjliga rckvidd. Anvnd inte globala variabler i ondan.
Varje variabel ska deklareras i en egen deklarationssats (anvnd ej multipeldeklaration).
Varje deklarerad variabel ska ges ett vrde innan den anvnds, om mjligt redan i deklarationen.
Anvnd, om mjligt, initiering i stllet fr tilldelning, fr datamedlemmar i klassobjekt.
! teranvnd inte variabler fr olika syften, utan deklarera en variabel fr varje syfte. Kompilatorn
optimerar minnesanvndningen t dig.
Konstanter
Namngivna konstanter (symboliska konstanter) fyller flera viktiga syften. En viktig aspekt r att ge
namn t vrden, t.ex. PI i stllet fr 3.1415926535897932384. Kod dr sdana namn anvnds blir
klarare r om det litterala vrdet (magiskt vrde) anvnds.
En annan frdel men symboliska konstanter r att konstanta vrden som kan komma att ndras, t.ex. i
samband med modifiering av program, ndras p ett enda stlle (i konstantdefinitionen).

Namngivning av vrden kan ocks stadkommas med variabler, men dr kommer en annan viktig egenskap hos konstanter in, nmligen att de r just konstanta. Konstanters vrden fr ej ndras och den
egenskapen kontrolleras av kompilatorn.
Ngra av reglerna fr variabler ovan, kan ven tillmpas fr konstanter.
Konstanter ska definieras genom anvndning av const eller enum, aldrig med #define (det r
gammal C-stil).
Undvik numeriska vrden i koden. Anvnd symboliska konstanter i stllet.

Uttryck
Det finns ett antal vanliga fallgropar i samband med berkning av sammansatta uttryck. C++ har mnga
operatorer och mnga prioritetsniver att hlla reda p, vilket bidrar till att det kan vara svrt att uttolka
sammansatta uttryck korrekt, om inte uttrycken skrivs p ett stt som stdjer uttolkningen.
Fr sammansatta uttryck dr ingende operatorer har samma prioritet, gller dessutom associativitetsregler. Dessa bestmmer om uttryck ska berknas frn vnster till hger eller frn hger till vnster.
Vnsterassociativitet gller fr de flesta prioritetsniverna, hgerassociativitet endast p ngra.
! Anvnd inte kommaoperatorn, av lsbarhetsskl.
! Den tilldelningsoperator som normalt br anvndas r =. vriga tilldelningsoperatorer (+=, -=, *=,
/=, %=, <<=, >>=, &=, |=, ^=) frsmrar ofta lsbarheten.
! Villkorsoperatorn ? : br normalt undvikas, av lsbarhetsskl.
! Anvnd parenteser fr att frtydliga berkningsordningen fr operatorer och deluttryck i komplicerade sammansatta uttryck.

Styrsatser
I C++ finns tv styrsatser fr selektion (if och switch) och tre fr repetition (for, while och do-while).
Vilken sats br man anvnda i en viss situation, eller kvittar det? Ibland ger det sig sjlvt, drfr att en
viss sats inte (enkelt) kan anvndas i en viss situationer. Det gller t.ex. switch-satsen, vars styruttryck
mste vara ett int-kompatibelt uttryck och dessutom mste vrdena i case-lgena vara konstanter. Detta
gr switch-satsen mer begrnsad n if-satsen, men dremot passar den mycket bra i vissa fall och ger
d enklare kod n motsvarande if-satsen.
Repetitionssatserna kan vara svrare att vlja bland, ven om det finns ngra grundregler man kan g
efter fr att frska anvnda rtt sats fr en viss typ av repetition, se rekommendationerna fr respektive sats nedan. Tnk noga igenom valet av repetitionssats, ditt val kan vara vsentligt fr att ge lsaren
rtt signal om vad fr slags repetition det r frga om (utan att behva luslsa koden).
Av utrymmesskl anvnds den s.k. javastilen fr att visa rekommenderad syntax nedan.
If-satsen
If-satsen br i princip skrivas enligt fljande syntax:
if (uttryck) {
satser
}
else if (uttryck) {
satser
}
else {
satser
}

Styruttrycket i if-satsen ska vara ett villkorsuttryck eller en boolsk variabel eller boolsk funktion.
! Om samtliga uttryck beror av samma variabel br en switch-sats anvndas i stllet fr en if-sats.
! if-satser br ha maximal 7 grenar och ett maximalt nstlingsdjup av 3.
7

switch-satsen
switch-satsen br i princip skrivas enligt fljande syntax:
switch (uttryck) {
case vrde:
satser
break;
case vrde:
case vrde:
satser
break;
default:
satser
break;
}

En switch-sats ska alltid innehlla ett avslutande default-alternativ, i vilket ovntade fall hanteras.
Koden i ett case-alternativ i en switch-sats ska avslutas med break, eller return. D flera casealternativ delar p samma kodblock anvnds break endast fr det sista av alternativen. Sdana fall
br kommenteras.
for-satsen
for-satsen br i princip skrivas enligt fljande syntax:
for (initieringssats uttryck2; uttryck3) {
satser
}

for-satsen ska endast anvndas fr repetitioner dr antalet varv kan bestmas d satsen brjar, dvs.
d uttryck2 r ett konstant uttryck under exekveringen av for-satsen, och d slingvariabeln stegas
med ett konstant steg i varje varv. I annat fall anvnds while (frtestade slingor) eller do-while
(eftertestade slingor).
for (int index = 0; i < number_of_elements; ++index) {
cout << vector[index];
}

while-satsen
while-satsen br i princip skrivas enligt fljande syntax:
while (styruttryck) {
satser
}

! while-satsen br endast vljas d styruttrycket p ett naturligt stt kan frtestas. Genom detta undviker man ologiska initieringar av variabler som ingr i uttrycket (ofta r ett tecken p att do-while
br vljas i stllet). Det kan vara aktuellt att avbryta slingan utan att utfra den ngon enda gng.
p = list;
while (p != 0) {
cout << p->name << endl;
p = p->next;
}

do-while-satsen
do-while-satsen br i princip skrivas enligt fljande syntax:
do {
satser
}
while (styruttryck);

! do-while anvnds d satserna i slingan alltid ska utfras minst en gng. I annat fall anvnds while.
cout << Ange vre grns (heltal strre n 0): ;
do {
cin >> upper_limit;
if (upper_limit < 1)
cout << vre grns ska vara strre n 0, ge ett nytt vrde: ;
}
while (upper_limit < 1);

vrigt rrande styrsatser


Anvnd aldrig goto fr normal programstyning.
I tidskritiska tillmpningar eller fr hantering av felsituationer kan goto tilltas. Sdana fall skall ingende
motiveras. goto bryter den sekventiella exekveringen p ett stt som ofta gr koden svr att frst. Dessutom
finns begrnsningar fr nr goto kan anvndas; det r t.ex. ej tilltet att hoppa frbi en sats som initierar ett
lokalt objekt som har en konstruktor.

! Anvnd unsigned fr variabler som rimligtvis ej kan anta negativa vrden. Variabler som representerar storlek eller lngd r lmpliga att deklarera som unsigned. Genom detta kan en del otrevliga
fel undvikas.
Det finns tillfllen d unsigned kan ge upphov till problem. Fljande for-sats kommer aldrig att avslutas,
till fljd av moduloaritmetiken som anvnds fr heltalstyper utan frtecken. P en Sun SPARC kommer variabeln i att cykliskt genomlpa 9, 8, , 0, 4294967295, 4294967294, :
for (unsigned int i = 9; i >= 0; i--)

! Anvnd alltid inklusiva undre grnser och exklusiva vre grnser, t.ex. 0 <= i och i < 10. Genom
att vara konsekvent i detta avseende kan svra fel undvikas.
! Anvnd ej continue om ej ptaglig lsbarhetsvinst eller frenkling kan erhllas med. Det r ofta mer
lsbart att anvnda else-gren i stllet; continue anvnds ju alltid tillsammans med en if-sats.
! Anvnd normalt break endast fr att avsluta case-alternativ i switch-satser. break kan tilltas fr
att g ur en slinga, om detta innebr att anvndning av flaggor undviks.
! Skriv ej logiska uttryck p formen if (ptr), if (!ptr) eller if (!!ptr), om ptr r en pekare. Mnga finner
dessa former svra att lsa. Skriv if (ptr != 0) eller if (ptr == 0).
! Efterstrva en return-sats i en funktion, p sista raden i funktionen. Om ptaglig frenkling kan erhllas genom flera return-satser, kan det tilltas. Endast en return-sats stdjer regeln att varje konstruktion ska ha endast en utgng (och endast en ingng). Fr en funktion som returnerar void kan
return helt utelmnas.

Funktioner
Funktionsparametrar
Anvnd inte ospecificerade funktionsargument (ellips, );
! Undvik funktioner med mnga argument.
! Om en funktion lagrar en pekare till ett objekt som tkoms via en parameter, ska parametern vara av
typen pekare. I annat fall ska referensparameter anvndas.
! Anvnd konstanta referenser (const &) fr vrdeanrop, svida ej parametertypen r av frdefinierad
typ eller r en pekare. (Undvika kopiering och eventuellt aktivering av en destruktor fr kopian).
Funktionsverlagring
! Alla variationer av ett verlagrat funktionsnamn br ha samma innebrd (semantik).
Returtyper och returvrden
Ange alltid en returtyp fr en funktion, eller void om inget vrde ska returneras.
En funktion ska aldrig returnera en referens eller pekare till en lokal variabel.
Inline-funktioner
Anvnd ej preprocessordirektivet #define fr att generera effektivare kod; anvnd i stllet inlinedeklarerade funktioner.
! Anvnd inline-deklaration endast d detta verkligen r pkallat.
Temporra objekt
! Minimera antalet temporra objekt som skapas fr funktionsparametrar och som returvrden.
Allmnt
! Undvik lnga och invecklade funktioner. Frsk att dela upp komplicerade funktioner i flera sm.

Pekare och dynamisk minneshantering


Anvndning av pekare och dynamisk minneshantering krver noggrannhet. En viktig aspekt r terlmning av dynamisk minne. Grs inte det korrekt uppstr s.k. minneslckor (minne som inte lngre
anvnds av programmet kan inte teranvndas, drfr att det fortfarande r bokfrt som upptaget),
vilket kan medfra att minnet tar slut.
Pekare
Anvnd ej C-makrot NULL fr test och tilldelning av pekare, anvnd hellre 0. Om man vill anvnda
NULL ska man sjlv definiera NULL enligt fljande.
const int NULL = 0;

! Undvik om mjligt pekare till pekare, **. Ofta kan referens till pekare anvndas i stllet, *&, t.ex. i
samband med funktionsparametrar.
! Anvnd typedef fr att frenkla programsyntaxen vid deklaration av lnkade strukturer och
funktionspekare.
Dynamisk minneshantering
Anvnd ej malloc, calloc eller free, fr att tilldela och terlmna dynamiskt minne, utan new
och delete. Om, av ngon anledning, de frra anvnds, blanda aldrig med new och delete!
! Skapa ej dynamiskt minne och frvnta att ngon annan ska terlmna det.
! Tilldela alltid en pekare som pekar till terlmnat minne ett nytt vrde (0 om ej annat). Om pekarens
deklarationsblock r p vg att lmnas, r detta naturligtvis ej ndvndigt.

10

Klasser
Klasser br i princip definieras enlighet fljande syntax, javastil t.h.:
class Derived : public Base
{
public:

protected:

private:

};

class Derived : public Base {


public:

protected:

private:

};

Man kan diskutera om tkomstskyddsdeklarerarna, public:, protected: och private:, ska dras in ett
steg, som ovan, eller ej.
public-, protected- och private-avdelningarna ska deklareras i den ordningen.
Genom denna deklarationsordning kommer det som r av intresse fr anvndaren, public, frst i klassdefinitionen. Drefter fljer protected-delen med sdant som r av intresse om man avser att hrleda frn klassen.
Sist private-delen som r av minst intresse allmnt.

Inga medlemsfunktioner ska definieras i klassdefinitionen.


Medlemsfunktioner som definieras i klassdefinitionen blir automatiskt inline-funktioner, vilket ibland kan
vara nskvrt. Att specificera medlemsfunktioner i klassdefinitionen gr dock att klassdefinitionen blir omfattande och svrare att lsa. Dessutom strider det mot principen att dlja information. Det r drfr att fredra att
skriva separata inline-deklarerade specifikationer fr medlemsfunktionerna, vilket ocks har vissa frdelar,
t.ex. kan en inline-funktion d ltt gras om till en vanlig funktion.

tkomstrttighet
Specificera ej datamedlemmar i en klass som public eller protected.
I grnssnitt mot andra sprk kan det vara ndvndigt att definiera public-specificerade datakomponenter.
Att specificera en datamedlem som public innebr att anvndare av klassen fritt kan operera p en sdan datamedlem. Detta strider mot den grundlggande principen i objektorienterad programmering att data ska vara
inkapslade och enbart ska kunna manipuleras p ett kontrollerat stt, dvs. via klassens medlemsfunktioner. Om
public-data undviks kan dess interna representation ndras utan att detta pverkar anvndarens kod.
Anvndning av protected-variabler i en klass rekommenderas ej, eftersom sdana variabler blir synliga i hrledda klasser. Namnen p sdana variabler kan d ej ndras, eftersom hrledda klasser kan vara beroende av
namnen. Om en hrledd klass mste komma t data i frldraklassen, kan detta lsas genom att gra ett speciellt l protected-grnssnitt i basklassen med funktioner som returnerar private-data. Detta behver ej pverka
effektiviteten om funktionerna definieras som inline-funktioner.

Inline-funktioner
! tkomstfunktioner br vara inline-funktioner.
const-medlemsfunktioner
En medlemsfunktion som ej ndrar ett objekt tillstnd ska vara const-deklarerad.
Medlemsfunktioner som r const-deklarerade r de enda funktioner som kan anropas fr const-objekt. Frutom att const-deklaration kar mjligheterna fr kompliatorn att utfra kontroller, kar den fljaktligen ven
funktionens anvndbarhet. Ibland verlagrar man en viss funktion, eller operator, fr att ha olika versioner fr
const- och icke-const-objekt.

Konstruktorer och destruktorer


En klass som anvnder new fr att skapa minne som hanteras av klassen, ska normalt ha en
kopieringskonstruktor och en destruktor.
Klasser som r basklasser och som har virtuella funktioner, mste ha en virtuell destruktor.

11

Tilldelningsoperatorer
En klass som anvnder new fr att skapa minne som hanteras av klassen ska normalt definiera en
tilldelningsoperator (operator=).
Operatorverlagring
! Anvnd operatorverlagring sparsamt och p ett enhetligt stt. Tolkningen ska vara intuitiv.
! Nr tv operatorer r varandras motsats (t ex == och !=) r det lmpligt att definiera bda.
Returtyper fr medlemsfunktioner
En public medlemsfunktion ska aldrig returnera icke-konstant referens/pekare till medlemsdata.
En public medlemsfunktion ska aldrig returnera en icke-const referens eller pekare till data utanfr
objektet, svida inte objektet delar data med andra objekt.
Arv
! Undvik arv fr del-av-relationer.
! Ge hrledda klasser tkomst till medlemsdata via skyddade tkomstfunktioner.

Undantag
Anvnd undantag (exceptions) enbart fr verkligt exceptionella hndelser, hantering av fel eller
ptagligt ovanliga eller viktiga situationer.
Hantera varje undantag p lmplig designniv.

Kodmallar
Dokumentation r en viktig del i framstllning av programvara. Hr behandlas den form av dokumentation som utgrs av kommentarer i kllkoden. Kllkodskommentarer kan delas in i strategiska och
taktiska kommentarer:
en strategisk kommentar placeras fre ett kodavsnitt, t.ex. fre en moduldeklaration eller en
funktionsdefinition, och beskriver vad det beskrivna kodavsnittet fyller fr funktion.
en taktisk kommentar rr vanligtvis en enskild rad kod, eller ngra rader. Om kommentaren rr en
enskild rad placeras den med frdel sist p raden om detta r mjligt, i annat fall fre raden ifrga.
En taktisk kommentar som rr flera rader placeras fre raderna, som en rubrik.
Strategiska kommentarer vnder sig i frsta hand till anvndare av en modul eller en funktion, medan
taktiska kommentarer vnder sig till den som ska underhlla koden. Fr mycket taktiska kommentarer
gr ltt koden olslig och br drfr undvikas. Taktisk kommentering kan ocks ofta undvikas genom
den strategiska kommenteringen, vl valda namn och vlskriven kod fr vrigt. Endast komplicerad
kod br kommenteras taktiskt.
Nedan visas mallar fr olika slags filer, inkluderingsfiler, inline-definitionsfiler och implementeringsfiler, samt fr strategiska kommentarer fr funktioner. Att standardisera sttet att kommentera kan gra
det mjligt att med lmpliga verktyg automatiskt generera annan dokumentation, t.ex. manualsidor.

12

Inkluderingsfiler
/*
* IDA Programvaruproduktion AB (u.p.a.)
*
* IDENTIFIERING
*
* Filnamn:
Stack.hh
* Enhetsnamn:
Stack
* Typ:
Moduldeklaration
* Revision:
2.1
* Skriven av:
H. Acker
*
*
* BESKRIVNING
*
* Denna modul ...
*
* REVISIONSBERTTELSE
*
* Revision Datum
Frndringar
*
* 1
970319 Ursprungsversion
* 1.1
970407 ...
* ...
* 2.0
970821 ...
*
*/
#ifndef STACK_HH
#define STACK_HH
/*
* REFERERADE BIBLIOTEK OCH MODULER
*/
#include <*.hh>
#include *.hh
...
/*
* VILLKORLIG INKLUDERING AV INLINE-DEFINITIONSFILEN
*
* Vid normal kompilering inkluderas inline-definitionsfilen
* Stack.icc hr. Vid kompilering fr avlusning inkluderas filen
* i stllet i Stack.cc. Detta styrs i kompileringskommandot med
* preprocessorflaggan -D och DEBUG som argument, dvs. -DDEBUG.
*/
#ifndef DEBUG
#include Stack.icc
#endif
/*
* SLUT P FILEN Stack.hh
*/
#endif

13

Inline-definitionsfiler
/*
* IDA Programvaruproduktion AB (u.p.a.)
*
* IDENTIFIERING
*
* Filnamn:
Stack.icc
* Enhetsnamn: Stack
* Typ:
Inline-definitioner hrande till modul Stack
* Revision:
2.1
* Skriven av: H. Acker
*
*
* BESKRIVNING
*
* Denna definitionsfil...
*
* REVISIONSBERTTELSE
*
* Revision Datum
Frndringar
*
* 1
970319 Ursprungsversion
* 1.1
970407 ...
* ...
* 2.0
970821 ...
*
*/
/*
* FUNKTION is_empty()
* ...
*/
template <class T>
inline
int
Stack<T>::
is_empty()
{
...
}
/*
* FUNKTION ...
* ...
*/
template <class T>
inline
...
/*
* SLUT P FILEN Stack.icc
*/

14

Implementeringsfiler
/*
* IDA Programvaruproduktion AB (u.p.a.)
*
* IDENTIFIERING
*
* Filnamn:
Stack.cc
* Enhetsnamn: Stack
* Typ:
Definitioner hrande till modul Stack, ej inline
* Revision:
2.1
* Skriven av: H. Acker
*
*
* BESKRIVNING
*
* Denna implementeringsfil...
*
* REVISIONSBERTTELSE
*
* Revision Datum
Frndringar
*
* 1
970319
Ursprungsversion
* 1.1
970407
...
* ...
* 2.0
970821
...
*
*/
/*
* REFERERADE BIBLIOTEK OCH MODULER
*/
#include Stack.hh
/*
* VILLKORLIG INKLUDERING AV INLINE-DEFINITIONSFILEN
*
* Vid kompilering fr avlusning inkluderas inline-definitionsfilen
* Stack.icc hr, samtidigt som inline-deklarationerna avlgsnas.
* Vid normal kompilering inkluderas filen i stllet i Stack.hh.
* Detta styrs i kompileringskommandot med preprocessorflaggan -D
* och DEBUG som argument, dvs. -DDEBUG.
*/
#ifdef DEBUG
#define inline
#include Stack.icc
#undef inline
#endif

15

/*
* LOKALA DEFINITIONER
*/
/*
* BESKRIVNING
* ...
*/
static ...

// ...

...
/*
* LOKALA FUNKTIONER (DEKLARATIONER)
*/
void f(...);

// ...

...
/*
* KONSTRUKTOR Stack()
* ...
*/
template <class T>
Stack<T>::
Stack()
{
...
}
/*
* LOKALA FUNKTIONER (DEFINITIONER)
*/
/*
* FUNKTION push(const T& item)
* ...
*/
void
push(const T& item)
{
...
}
/*
* SLUT P FILEN Stack.cc
*/

16

Klassbeskrivningar
Nedan visas hur klasser kan dokumenteras i inkluderingsfilen.
/*
* KLASS X
*
* BASKLASSER
*
* ...
*
* BESKRIVNING
*
* ...
*
* TILLSTND
*
* ...
*
* KONSTRUKTORER
*
* ...
*
* OPERATIONER
*
* ...
*
* DATAMEDLEMMAR
*
* ...
*
* REVISIONSBERTTELSE
*
* Revision Datum
Frndringar
*
* 1
970319 Ursprungsversion
* ...
*/
class X
{
friend ...
...
public:
...
protected:
...
private:
...
};

17

Funktionsbeskrivningar
I filmallarna ovan har strategiska kommentarer fr funktioner markerats med t.ex.:
/*
* FUNKTION funktionsnamn
* ...
*/

I realiteten ska en fullstndig funktionsbeskrivning finnas, vilken kan se ut enligt fljande.


/*
* FUNKTION f(int i, ...)
*
* BESKRIVNING
*
* Denna funktion...
*
* INDATA
*
* ...
*
* UTDATA
*
* ...
*
* SIDOEFFEKTER
*
* ... (helst inga)
*
* UTNYTTJAR
*
* Modul:
iostream
* Modul:
...
* Funktion: g
* Funktion: ...
*
* REVISIONSBERTTELSE
*
* Revision
Datum
Frndringar
*
* 1
970319 Ursprungsversion
* ...
*/
void
f(int i, ...)
{
...
}

18

You might also like