English

Att returnera data

Att returnera något i ett program betyder att man skickar något värde till den som anropade koden. Är det en funktion som returnerar ett värde så hamnar det hos den som anropade funktionen. Är det ett program som returnerar ett värde så hamnar värdet hos den som startade programmet.

Funktioner måste i många språk deklareras med en returtyp som talar om vilken sorts data som ska returneras. Om inget data ska returneras från funktionen kan man i språk som till exempel C och Java ge den returtypen void. I andra språk, som till exempel Ada och Pascal, måste funktioner alltid returnera ett värde. Funktioner som inte returnerar något heter nämligen procedurer i dessa språk. Strikt sett så är det Ada och Pascal som har rätt. Det är skillnad på funktioner och procedurer, och funktioner ska alltid ha ett returvärde.

När programkörningen når en retursats så hoppar den ur funktionen den befinner sig i. Programkörningen fortsätter på instruktionen direkt efter funktionsanropet i den anropande koden. Eventuell kod som ligger efter retursatsen kommer aldrig att kunna köras. Man brukar kalla sådan kod för död kod.

Kodexempel i C

    char printable(char ch)
    {
       if (ch < 32)
          return ' ';
       if (ch > 126 && ch < 161)
          return ' ';
       return ch;
    }
  

Här ser vi att det finns flera retursatser i en funktion. Beroende på hur de olika villkoren faller ut kommer olika värden att returneras. När man har retursatser i villkorliga satser så är det viktigt att komma ihåg att ha en retursats som fångar upp de fall som inte matchar något av villkoren. Om man har deklarerat att funktionen ska returnera någon typ så måste den göra det i alla lägen. Programkörningen får aldrig nå slutet av funktionen utan att nå fram till en retursats.

Det är också viktigt att alla retursatser returnerar data av rätt typ. Returtypen återkommer på tre ställen i samband med en funktion och det är viktigt att alla tre platser hanterar samma typ. Dels är det själva funktionsdeklarationen som har en returtyp. Denna returtyp deklareras ofta innan funktionsnamnet. Funktionen printable ovan har returtypen char. Det andra stället som ska matcha returtypen är där funktionen tar slut. Där finns kommandot return som kommer att utföra själva tillbakaskickandet av returvärdet. Om funktionen säger att den ska skicka tillbaka en char så får man se till att return faktiskt gör det. Det tredje stället där det måste stämma är i den anropande koden. Om en funktion returnerar ett värde ska man ta hand om det och då måste man förstås behandla det som den typ som funktionen säger att den returnerar.

Returvärden

De flesta språk har någon form av huvudfunktion där man anser att programmet startar. I C och Java brukar den heta main medan till exempel Basic-dialekter och Pascal har en huvudfunktion som rent visuellt ligger ytterst i koden. Returvärdet från denna huvudfunktion är lite speciellt. Detta värde ska ju skickas tillbaka till den som anropade programmet och det måste därför följa de anropskonventioner som det aktuella operativsystemet har. Unix och C har satt standarden för detta och de flesta följer den i stora drag. Ett programs returvärde i Unix representerar en statusflagga som talar om ifall programmet lyckades med sin uppgift eller ej. Om ett program returnerar 0 betyder det att allt gick bra, ett returvärde skilt från 0 betyder att något gick fel.

I ANSI C representeras dessa felkoder med två konstanter: EXIT_SUCCESS och EXIT_FAILURE. När man jobbar i C bör man alltid använda dessa konstanter som returvärde från main (både då man avslutar med return och exit) för att hålla koden så plattformsoberoende som möjligt. Andra plattformar än Unix kan betrakta ett returvärde på andra sätt och anpassar då definitionen av felkoderna därefter. I till exempel Sony NEWS-OS version 4.0C har man av misstag definierat EXIT_SUCCESS till 1 och EXIT_FAILURE till 0. VMS definierar EXIT_SUCCESS till 1 och EXIT_FAILURE till 0x10000002 (eller 3, eller 0...). En annan ganska vanlig implementation av EXIT_FAILURE är -1. AmigaOS har en bredare skala av felkoder som vi kan se i tabellen nedan. Man kan även tänka sig inbyggda system som tolkar felkoderna helt annorlunda beroende på minnesbesparingar eller begränsade datatyper. Det enda man kan lita på när man programmerar för inbyggda system är att ingenting fungerar som man är van vid.

ReturvärdeKommentar
0Allt är bra.
5Mindre fel uppstod. Inget som påverkar kommande programs funktion.
10Fel uppstod. Programmets utdata kan vara felaktig.
20Allvarligt fel. Eventuella kringliggande script bör avbrytas.