Szukaj…


Uwagi

W C powszechne jest używanie wartości zwracanych w celu oznaczenia występujących błędów; oraz do zwracania danych za pomocą przekazanych wskaźników. Można to zrobić z wielu powodów; w tym niepotrzebne przydzielanie pamięci na stercie lub używanie statycznego przydzielania w punkcie, w którym funkcja jest wywoływana.

Używanie parametrów wskaźnika do zwracania wielu wartości

Częstym wzorcem w C, aby łatwo imitować zwracanie wielu wartości z funkcji, jest używanie wskaźników.

#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;
}

Przekazywanie tablic do funkcji

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;
  }
}

Tutaj static wewnątrz [] parametru funkcji, zażądaj, aby tablica argumentów zawierała co najmniej tyle elementów, ile jest określonych (tj. Elementy size ). Aby móc korzystać z tej funkcji, musimy upewnić się, że parametr size znajduje się przed parametrem tablicy na liście.

Użyj getListOfFriends() następujący sposób:

#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;
}

Zobacz też

Przekazywanie tablic wielowymiarowych do funkcji

Parametry są przekazywane według wartości

W C wszystkie parametry funkcji są przekazywane przez wartość, więc modyfikowanie tego, co jest przekazywane w funkcjach odbiorcy, nie wpłynie na lokalne zmienne funkcji wywołującej.

#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;
}

Za pomocą wskaźników możesz pozwolić funkcjom odbierającym modyfikować lokalne zmienne funkcji dzwoniącego. Zauważ, że nie jest to przekazywane przez odniesienie, ale wartości wskaźnika wskazujące na zmienne lokalne są przekazywane.

#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;
}

Jednak zwrócenie adresu zmiennej lokalnej do odbiorcy powoduje niezdefiniowane zachowanie. Zobacz Odsyłanie wskaźnika do zmiennej poza jej okresem użytkowania .

Kolejność wykonywania parametrów funkcji

Kolejność wykonywania parametrów jest niezdefiniowana w programowaniu C. Tutaj może być wykonywany od lewej do prawej lub od prawej do lewej. Kolejność zależy od realizacji.

#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;
}

Przykład funkcji zwracającej strukturę zawierającą wartości z kodami błędów

Większość przykładów funkcji zwracającej wartość wymaga podania wskaźnika jako jednego z argumentów umożliwiających funkcji zmodyfikowanie wskazanej wartości, podobnie jak poniżej. Rzeczywista wartość zwracana przez funkcję jest zwykle pewnego rodzaju, na przykład int wskazująca status wyniku, niezależnie od tego, czy zadziałał, czy nie.

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 */
}

Jednak można również użyć struct jako wartości zwracanej, która pozwala zwrócić zarówno status błędu, jak i inne wartości. Na przykład.

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;
}

Tę funkcję można następnie wykorzystać jak w poniższym przykładzie.

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

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

Lub może być użyty w następujący sposób.

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow