2015-04-10 2 views
0

У меня есть следующий код:указатели, структуры, проходящие аргументы, рекурсия

typedef struct _Statistics { 

    Some code here 

} Statistics; 

void function1(char *string, Statistics *statistic){ 

    Some code here 

    function1(string1, statistic); 
} 
int main(){ 

    Statistics statistic; 
    function1(string, &statistic); 
} 

Это, вероятно, идиотский вопрос, но я не понимаю, указатели полностью: Я понимаю, почему я использую & в основной функции, & отправить адрес переменной статистики, так что в функции1 я могу его изменить. Но почему я не использую & в рекурсивной функции1?

+7

Потому что он уже * есть * указатель. «Статистика» в основном является фактическим объектом. Вызов 'function1 (строка и статистика);' hand a * pointer * to function1. Поэтому, когда функция1 вызывает себя, она может просто использовать указатель, который она указала main(). – wildplasser

+0

Объявите свою функцию как 'void function1 (char * string, Statistics * ptr)', и вы поймете, почему рекурсивный вызов 'function1 (string1, ptr);' – CiaPan

ответ

1

Иногда это помогает написать так:

void function1(char* string, Statistics* statistic){ 

Переменная statistic является указателем на статистике, а не статистики сам. Если вы сделали это в function1:

function1(string1, &statistic); 

Вы бы передаете указатель (из-за &) указатель (из-за * в объявлении) статистики, которая была бы неверна.

Ваше объявление statistic в основном как статистика добавляет к путанице: вы используете одно и то же имя переменной с разными типами в двух областях.

С разными именами переменных это понятнее:

typedef struct _Statistics { 
    Some code here 
} Statistics; 

void function1(char* string, Statistics* ptrstat){ 
    Some code here 
    function1(string1, ptrstat); 
} 

int main(){ 
    Statistics statistic; 
    function1(string, &statistic); 
} 
+0

Итак, в первый раз, когда я вызываю функцию1 (из основного) с & я даю ему адрес, например 444555666, и * статистика - это то, что удержание этого адреса, например, 444555666 имеет 5, но в статистике у меня все еще есть то же место. Я прав? –

+0

Это в основном, да –

4

Потому что &statistic (in function1()) является адресом памяти указателя, а не адресом, содержащимся в указателе.

Тип &statistic: Statistics** в function1().


Несколько слов о указателей

Допустим, мы определим следующие переменные:

char c = 'a'; 
char *p_c = &c; 

Теперь мы будем печатать значения и адреса памяти p_c и c:

printf("%c\n", c); // will print 'a' 
printf("%c\n", *p_c); // will print 'a' 

printf("%p\n", &c); // will print the memory address of c 
printf("%p\n", p_c); // will print the memory address of c 

printf("%p\n", &p_c); // will print the memory address of p_c 

Наконец определим char**, указатель на указатель на char:

char **p_pc = &p_c; 

printf("%c\n", **p_pc); // will print 'a' 
printf("%p\n", *p_c); // will print the memory address of c 
printf("%p\n", p_c); // will print the memory address of p_c 
0

В целом (то есть в большинстве языков), вы можете передать по значению или пройти по ссылке. Это будет зависеть от определения функции и ее «подписи»; то есть способ, которым он и его аргументы объявлены.

Передача по значению - это как назначение, и, если копировать большую структуру, это займет больше времени. Кроме того, функция получает только копию, поэтому вы можете вносить изменения в аргумент в функцию, но это будет влиять только на локальную копию функции (аргумент) и не будет изменять NO исходное значение (в вызывающем), которое было передал вам.

В отличие от этого, передача по ссылке просто передает указатель (адрес в памяти) исходного значения.Это намного быстрее (4 или 8 байт), но это означает, что функция может не только читать, но и записать значение вызывающего абонента. Иногда ты этого хочешь! Иногда вы этого не делаете.

В целом, у вас есть значение статистики. Функция, которую вы вызываете, ожидает адрес (*), поэтому вместо передачи значения (статистики) вам необходимо передать его адрес (статистика).

В функции, вызывающей себя, у вас есть указатель на статистику (Статистика *), и вы должны передать указатель на статистику (Statistics *): следовательно, просто передайте ее, указатель 'statistic'.