Sök…


Anmärkningar

I C är det vanligt att använda returvärden för att beteckna fel som uppstår; och att returnera data genom användning av vidarebefordrade pekare. Detta kan göras av flera skäl; inklusive att inte behöva tilldela minne på högen eller använda statisk allokering vid den punkt där funktionen anropas.

Använda pekarparametrar för att returnera flera värden

Ett vanligt mönster i C, för att enkelt imitera att returnera flera värden från en funktion, är att använda pekare.

#include <stdio.h>

void Get( int* c , double* d )
{
    *c = 72; 
    *d = 175.0;
}

int main(void)
{
    int a = 0;
    double b = 0.0;

    Get( &a , &b );

    printf("a: %d, b: %f\n", a , b ); 

    return 0;
}

Vidarebefordra i matriser till funktioner

int getListOfFriends(size_t size, int friend_indexes[]) {
  size_t i = 0;
  for (; i < size; i++) {
    friend_indexes[i] = i;
  }
}
C99 C11
/* Type "void" and VLAs ("int friend_indexes[static size]") require C99 at least. 
   In C11 VLAs are optional. */
void getListOfFriends(size_t size, int friend_indexes[static size]) {    
  size_t i = 0;
  for (; i < size; i++) {
    friend_indexes[i] = 1;
  }
}

Här static inuti [] i funktionsparametern, begär att argumentfältet måste ha minst lika många element som anges (dvs size ). För att kunna använda den funktionen måste vi se till att size kommer före matrisparametern i listan.

Använd getListOfFriends() så här:

#define LIST_SIZE (50)

int main(void) {
  size_t size_of_list = LIST_SIZE;
  int friends_indexes[size_of_list];

  getListOfFriends(size_of_list, friend_indexes); /* friend_indexes decays to a pointer to the
                                                     address of its 1st element: 
                                                                      &friend_indexes[0] */

  /* Here friend_indexes carries: {0, 1, 2, ..., 49}; */

  return 0;
}

Se även

Vidarebefordra flerdimensionella matriser till en funktion

Parametrar skickas efter värde

I C passeras alla funktionsparametrar efter värde, så att ändra vad som skickas i callee-funktioner påverkar inte samtalsfunktionernas lokala variabler.

#include <stdio.h>

void modify(int v) {
    printf("modify 1: %d\n", v); /* 0 is printed */
    v = 42;
    printf("modify 2: %d\n", v); /* 42 is printed */
}

int main(void) {
    int v = 0;
    printf("main 1: %d\n", v); /* 0 is printed */
    modify(v);
    printf("main 2: %d\n", v); /* 0 is printed, not 42 */
    return 0;
}

Du kan använda pekare för att låta callee-funktioner ändra anropsfunktionernas lokala variabler. Observera att detta inte är förbi referens men pekarvärden som pekar på de lokala variablerna passerat.

#include <stdio.h>

void modify(int* v) {
    printf("modify 1: %d\n", *v); /* 0 is printed */
    *v = 42;
    printf("modify 2: %d\n", *v); /* 42 is printed */
}

int main(void) {
    int v = 0;
    printf("main 1: %d\n", v); /* 0 is printed */
    modify(&v);
    printf("main 2: %d\n", v); /* 42 is printed */
    return 0;
}

Men att returnera adressen till en lokal variabel till callee resulterar i odefinierat beteende. Se Avsluta en pekare till variabel utanför dess livstid .

Ordning på utförande av funktionsparametrar

Ordern för exekvering av parametrar definieras inte i C-programmering. Här kan det köra från vänster till höger eller från höger till vänster. Beställningen beror på implementeringen.

#include <stdio.h>

void function(int a, int b) 
{
    printf("%d %d\n", a, b);
}

int main(void)
{
    int a = 1;
    function(a++, ++a);
    return 0;
}

Exempel på funktion som returnerar strukt som innehåller värden med felkoder

De flesta exempel på en funktion som returnerar ett värde involverar att tillhandahålla en pekare som ett av argumenten för att låta funktionen ändra det pekade värdet, liknande det följande. Det faktiska avkastningsvärdet för funktionen är vanligtvis någon typ, t.ex. en int att indikera status för resultatet, oavsett om det fungerade eller inte.

int func (int *pIvalue)
{
    int iRetStatus = 0;             /* Default status is no change */

    if (*pIvalue > 10) {
        *pIvalue = *pIvalue * 45;   /* Modify the value pointed to */
        iRetStatus = 1;             /* indicate value was changed */
    }

    return iRetStatus;              /* Return an error code */
}

Men du kan också använda en struct som ett returneringsvärde som gör att du kan returnera både en felstatus tillsammans med andra värden också. Till exempel.

typedef struct {
    int    iStat;      /* Return status */
    int    iValue;     /* Return value */
}  RetValue;

RetValue func (int iValue)
{
    RetValue iRetStatus = {0, iValue};

    if (iValue > 10) {
        iRetStatus.iValue = iValue * 45;
        iRetStatus.iStat = 1;
    }

    return iRetStatus;
}

Denna funktion kan sedan användas som följande exempel.

int usingFunc (int iValue)
{
    RetValue iRet = func (iValue);

    if (iRet.iStat == 1) {
        /* do things with iRet.iValue, the returned value */
    }
    return 0;
}

Eller så kan det användas på följande sätt.

int usingFunc (int iValue)
{
    RetValue iRet;

    if ( (iRet = func (iValue)).iStat == 1 ) {
        /* do things with iRet.iValue, the returned value */
    }
    return 0;
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow