2014-01-28 4 views
1

При использовании прохода по ссылке в C, иногда адрес передается вызываемым изменение функции:С - Pass по значению и передачи по ссылке несогласованность

void mainFunction() 
{ 
    BYTE aAddress[10]; 
    readFunction(aAddress); // Address of aAddress: 0x111111 
} 

void readFunction(BYTE *pAddress) // Address of pAddress: 0x222222 
{ 
    ... 
} 

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

void mainFunction() 
{ 
    readFunction(0x20); // Passed value: 0x20 
} 

void readFunction(BYTE uValue) // Received value: 0x00 
{ 
    ... 
} 
+0

Вы * do * объявляете функции перед их вызовом? То есть у вас есть прототип 'readFunction', прежде чем вызывать его в' mainFunction'? –

+0

У вас есть прототипы для функции, определенной до того места, где вызывается функция? Если не попытаться переместить определение функции над местом, где оно вызывается.Если это исправляет, то причина, по которой он не работает, заключается в том, что компилятор принимает что-то о функции - и принимает это неправильно. –

+4

Строго говоря, это не 'pass-by-reference' в C. Как вы выводите адреса? 'pAddress' - это указатель, который должен указывать на то же место, что и' aAddress', когда 'readFunction' вызывается с помощью' aAddress'. – Axel

ответ

2

Все зависит от того, как вы печатали адреса? Если вы получите адрес переменной, то , конечно, они будут отличаться. Значение указатели указывают, однако, будет то же самое ::

int main (void) 
{ 
    char some_array[100]; 
    printf("array holds: %p\n", (void*) some_array);//same 
    printf("Address in main: %p\n", (void*) &some_array[0]);//same 
    pass_arr(some_array); 
    return 0; 
} 
void pass_arr(char *arr) 
{ 
    printf("Address of pointer VAR: %p\n", (void *) &arr);//PRINTS DIFFERENT ADDRESS 
    printf("Pointer address: %p\n", (void *) arr);//same 
    printf("points to: %p\n", (void *) &(*arr));//same 
} 

check this codepad
Вы, вероятно, не удалось правильно напечатать адрес переменной, только правильный путь заключается в использовании %p заполнитель, и до с указанием адреса void *. Это связано с тем, что адреса, адреса которых печатаются, зависят от реализации.


Тем не менее, вы упоминаете "проходят по ссылке". C не проходит по ссылке, он не имеет ссылок в смысле C++. Но для того, чтобы функция, чтобы изменить значение чего-то другого, вы должны передать указатель на указатель:

struct some_str 
{ 
    int mem1; 
    size_t mem2; 
}; 
int main (void) 
{ 
    struct some_str *foo = malloc(sizeof *foo); 
    set_value(&foo); 
    free(foo); 
    return 0; 
} 
void set_value(struct some_str **change) 
{//pointer to pointer 
    static int change_count = 0; 
    (*change)->mem1 = 123; 
    (*change)->mem2 = ++change_count;//for example 
} 

C всегда проходит по значению, в случае указателя, что значение является память адрес, в случае примитивного типа (int, char, long ...), это не переменная но значение вы передаете, если передать указатель на переменную (&my_int), вы не передавая переменную, а ее адрес в памяти. Это единственные 2 варианта, которые вам нужно выбрать.

Более подробную информацию по этой теме (массивы против указателей, и почему массивы распадаются на указатели в большинстве случаев you may find this link useful)

+0

Отличный ответ. – George

+0

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

+0

@JimBalter: Добавил это к моему ответу тоже. PS: возможно, изменить свой комментарий к _ «99% раз это ваша вина, и единственный инструмент в операции вы» _ :) –

1

При использовании проход по ссылке в C, иногда адрес передается вызываемой функции изменения

-> NO. Посмотрите на этот код

#include <stdio.h> 

void readFunction (int *pAddress) 
{ 
    printf("Address of pAddress: %p\n", &pAddress); 
    printf("Content of pAddress: %p\n", pAddress); 
} 

void main() 
{ 
    int a[10]; 
    printf("Address of a: %p\n", &a); 
    readFunction(a); 
} 

когда выполнить его, вы получите что-то как:

Address of a: 0xbfb94948 
Address of pAddress: 0xbfb94930 
Content of pAddress: 0xbfb94948 

pAddress находится в другом месте, но он по-прежнему указывает на адрес a. И это примитив прохода по ссылке

+0

В ролях указатели, и объяснить _ „это примитивная проход по ссылке“ _ –

+0

Язык C не поддерживает „пройти по ссылке“. Вообще. Самое близкое, что вы можете получить, это передача _pointer_ _value_. Есть люди, которые настаивают на том, что это «проходит по ссылке», но это неверно. –

+0

При передаче указателя на 'printf()', который должен быть напечатан с использованием преобразования '% p', указатель всегда должен быть переведен в' (void *) '. –

Смежные вопросы