Поиск…


замечания

В C обычно используется возвращаемое значение для обозначения ошибок, которые происходят; и возвращать данные через использование переданных в указателях. Это можно сделать по нескольким причинам; в том числе не нужно выделять память в куче или использовать статическое распределение в точке, где вызывается функция.

Использование параметров указателя для возврата нескольких значений

Общий шаблон на C, чтобы легко имитировать возврат нескольких значений из функции, заключается в использовании указателей.

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

Передача массивов в функции

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

Здесь static внутри [] параметра функции, запросите, чтобы массив аргументов должен иметь как минимум столько элементов, сколько указано (т. size Элементы size ). Чтобы иметь возможность использовать эту функцию, мы должны убедиться, что параметр size находится перед параметром массива в списке.

Используйте getListOfFriends() следующим образом:

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

Смотрите также

Передача многомерных массивов в функцию

Параметры передаются по значению

В C все параметры функции передаются по значению, поэтому изменение того, что передается в вызываемых функциях, не влияет на локальные переменные функций вызывающего абонента.

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

Вы можете использовать указатели, чтобы функции вызываемого абонента изменяли локальные переменные функций вызывающего абонента. Обратите внимание, что это не пропуск по ссылке, но значения указателя, указывающие на локальные переменные, передаются.

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

Однако возврат адреса локальной переменной к вызываемому приводит к неопределенному поведению. См. Разделение указателя на переменную за пределами ее срока службы .

Порядок выполнения функции

Порядок выполнения параметров не определен в программировании на С. Здесь он может выполняться слева направо или справа налево. Порядок зависит от реализации.

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

Пример функции, возвращающей структуру, содержащую значения с кодами ошибок

Большинство примеров функции, возвращающей значение, включают предоставление указателя в качестве одного из аргументов, позволяющих функции изменять указанное значение, похожее на следующее. Фактическое возвращаемое значение функции обычно представляет собой некоторый тип, такой как int чтобы указывать статус результата, независимо от того, работает он или нет.

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

Однако вы также можете использовать struct как возвращаемое значение, которое позволяет вам возвращать как статус ошибки вместе с другими значениями. Например.

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

Затем эту функцию можно использовать, как в следующем примере.

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

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

Или он может быть использован следующим образом.

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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow