2015-08-11 3 views
7

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

#include <stdio.h> 

void swap(int* a, int* b); 

int main(void) 
{ 
    int x = 1; 
    int y = 2; 

    swap(&x, &y); 
    printf("x is %i\n", x); 
    printf("y is %i\n", y); 
} 

void swap(int* a, int* b) 
{ 
    int tmp = *a; 
    *a = *b; 
    *b = tmp; 
} 

Я поплелся вместе следующее, чтобы увидеть, если это поможет мне лучше понять, что происходит, главным образом, в отношении к необходимости использования & против * (разыменования). В принципе, синтаксис объявления указателя на тип int (int * a) по сравнению с использованием звездочки для «разыменования» (* a = * b) довольно запутанный для меня, и я надеялся, что кто-то сможет просветить меня. Вот еще одна версия выше, чем я думал, что помогло бы уточнить, но на самом деле не:

#include <stdio.h> 

void swap(int* a, int* b); 

int main(void) 
{ 
    int x = 1; 
    int y = 2; 
    int *a = &x; 
    int *b = &y; 

    swap(a, b); 
    printf("x is %i\n", x); 
    printf("y is %i\n", y); 
} 

void swap(int* a, int* b) 
{ 
    int tmp = *a; 
    *a = *b; 
    *b = tmp; 
} 

Короче говоря, мой вопрос, есть ли функциональное различие между тем, что эти две программы делают? В чем разница между разыменованием (*a = *b) по сравнению с использованием & оператора (*a = &x)».

ответ

6

Вы путаете заявление и назначение.

*a = *b называется присвоением. Обратите внимание на его не включают имя типа.

int *a = &x с другой стороны, называется декларация. Обратите внимание на то, что вы инициализацииуказатель с адресом x. Вы не разыменовывая указатель, но являются Объявление это как указатель на int.

Посмотрите на это:

int main() { 
    int a = 5; 
    int b = 2; 
    int *c = &a; // c when dereferenced equals 5; **Declaration** 
    int *d = &b; // d when dereferenced equals 2; **Declaration** 
    int tmp = *c; // tmp equals 5 
    *c = *d; // c when dereferenced now equals 2 **Assignment** 
    *d = tmp; // d when dereferenced now equals 5 **Assignment** 
    return 0; 
} 

Наконец, когда вы объявить и инициализировать указатель в том же заявлении, присвоить указатель на адрес того, что вы хотите иметь точку на него. Если вы хотите изменитьзначение объект указывает на, вы разыгрывающий с использованием *. С другой стороны, если вы хотите изменить , что это указывает на, вы делаете не разыщите его.

+0

Ах, нажмите! Спасибо! –

+1

Если это помогает понять, напишите 'int * x' вместо' int * x' –

1

Если вы установили *a = *b так a и b являются указатель переменных, оператор * будет извлекать значение ячейки в памяти, что b указывает на него и помещает его в клетку, что a указывает на него.

Для *a = &x, оператор & находит адрес ячейки, что выделенной переменной x, и помещает его в клетку о том, что указывает на него.

+0

Вы не можете '* a = & x' без явного приведения. – edmz

+0

Это _will_ be. Если вы его не получите, напишите ошибку своему компилятору. – edmz

+0

Ах, вы правы. –

4

&x возвращает адрес x. x имеет тип integer и a имеет указатель типа на целое число.В этом случае (* a = & x) вы присваиваете адрес x переменной типа «указатель на целое число», которая равна a. (* a = * b) - операция назначения между двумя переменными того же типа, которые являются целыми. Я сказал целое, потому что хотя a и b являются «указателями на целые числа», в этой операции они разыменовываются, и поэтому считывается целочисленное значение, на которое они указываются.

Путаница, я думаю, у вас есть, потому что (* a = & x) имеет смысл только при инициализации указателя.

-1

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

Нет, функциональный эффект точно такой же. В

int *a = &x; 
int *b = &y; 

swap(a, b); 
// swap(&a, &b) 

Тип a такой же как &a, а именно int* (указатель на int). Единственное различие заключается в том, что вы используете другие переменные для хранения, которые на самом деле не нужны логически, но совершенно нормально иметь его, особенно если это поможет вам понять синтаксис.

В чем разница между разыменования (* а = * б) по сравнению с использованием & (* а = & х).

*a = *b присваивает значениеуказывает b (полученного с *b) в тех указаны по a. Чтобы увидеть это более ясно,

int tmp = *b; 
*a = tmp; 

&(*a = &x) не является допустимым выражением, потому что вы не можете сохранить адрес в качестве int (на самом деле вы можете, но это за точку).

+0

Какова причина для downvoting? – edmz

+0

Вы неправильно читаете последнюю часть своего вопроса. Он имел в виду '&' ('* a = & x'). Norice, как я отделил '&' от круглой скобки – Isaiah

+0

@ Isaiah Я действительно это сделал. Выражение недействительно и не может быть скомпилировано. – edmz

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