2015-08-11 13 views
7

Tôi đang cố gắng hiểu rõ hơn về con trỏ và tham chiếu trong C và khóa học của tôi đã cung cấp chương trình sau làm ví dụ.Tìm hiểu con trỏ với chương trình hoán đổi trong 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; 
} 

Tôi lê lại với nhau sau đây để xem nếu nó sẽ giúp tôi hiểu rõ hơn về những gì đang xảy ra, chủ yếu liên quan đến nhu cầu sử dụng & so với * (dereference). Về cơ bản, cú pháp khai báo một con trỏ tới kiểu int (int * a) so với việc sử dụng dấu hoa thị để "dereference" (* a = * b) khá khó hiểu với tôi, và tôi hy vọng ai đó có thể khai sáng cho tôi. Dưới đây là một phiên bản khác của các bên trên mà tôi nghĩ sẽ giúp làm rõ, nhưng thực sự không:

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

Nói tóm lại, câu hỏi của tôi là, liệu có một sự khác biệt về chức năng giữa những gì hai chương trình này đang làm? sự khác biệt giữa một dereference (*a = *b) so với sử dụng & điều hành (*a = &x)"

Trả lời

6

Bạn đang bối rối khai và phân công là gì..

*a = *b được gọi phân. Chú nó không bao gồm một tên loại.

int *a = &x Mặt khác được gọi là khai báo . Lưu ý rằng bạn khởi tạo số con trỏ với địa chỉ của x. Bạn đang không phải là dereferencing con trỏ, nhưng là tuyên bố nó làm con trỏ đến int.

Nhìn này:

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

Cuối cùng, khi bạn tuyên bốkhởi một con trỏ trong cùng tuyên bố, bạn gán con trỏ các địa chỉ về những gì bạn muốn có điểm ở đó. Khi bạn muốn thay đổi giá trị đối tượng trỏ đến, bạn dereference bằng cách sử dụng *. Mặt khác, nếu bạn muốn thay đổi những gì nó trỏ đến, bạn làm không bỏ qua nó.

+0

Ah, nhấp! Cảm ơn bạn! –

+1

Nếu nó giúp hiểu, hãy viết 'int * x' thay vì' int * x' –

1

Nếu bạn đặt *a = *b từ ab là các biến con trỏ, các nhà điều hành * sẽ lấy giá trị của một tế bào trong bộ nhớ mà b điểm cho nó và đặt nó vào tế bào mà a điểm đến nó.

Đối *a = &x, các nhà điều hành & tìm địa chỉ của tế bào đó phân bổ cho các biến x, và đặt nó trong tế bào là một điểm đến nó.

+0

Bạn không thể '* a = & x' mà không có diễn viên rõ ràng. – edmz

+0

Nó _will_. Nếu bạn không nhận được bất kỳ, hãy gửi một lỗi cho trình biên dịch của bạn. – edmz

+0

Ah, bạn nói đúng. –

4

&x trả về địa chỉ của x. x là loại số nguyên và a là loại con trỏ thành số nguyên.Trong trường hợp này, (* a = & x), bạn đang gán địa chỉ x cho biến loại "con trỏ đến số nguyên", là a. (* a = * b) là một phép toán gán giữa hai biến cùng loại là số nguyên. Tôi đã nói số nguyên bởi vì mặc dù ab là "con trỏ đến số nguyên", trong hoạt động đó, chúng bị hủy tham chiếu và do đó giá trị số nguyên mà chúng được trỏ tới được đọc.

Sự nhầm lẫn mà tôi nghĩ bạn có là vì (* a = & x) chỉ có ý nghĩa trong khi khởi tạo con trỏ.

-1

Tóm lại, câu hỏi của tôi là, có sự khác biệt chức năng giữa hai chương trình này đang làm gì?

Không, hiệu ứng chức năng hoàn toàn giống nhau. Trong

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

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

Loại a là như nhau của &a, cụ thể là int* (con trỏ đến int). Sự khác biệt duy nhất là bạn đang sử dụng các biến khác để lưu trữ các biến đó, điều này không thực sự cần thiết một cách hợp lý nhưng nó hoàn toàn tốt để có nó, đặc biệt nếu nó có thể giúp bạn hiểu cú pháp.

sự khác biệt giữa một dereference là gì (* a = b *) so với sử dụng & (* a = & x).

*a = *b giao giá trị trỏ đến bởi b (thu được với *b) trong những người được trỏ đến bởi a. Để nhìn thấy nó rõ ràng hơn,

int tmp = *b; 
*a = tmp; 

&(*a = &x) không phải là một biểu thức hợp lệ bởi vì bạn không thể lưu trữ một địa chỉ vào một int (trên thực tế bạn có thể, nhưng đó là vượt ra ngoài điểm).

+0

Lý do giảm giới hạn là gì? – edmz

+0

Bạn đã đọc sai phần cuối của câu hỏi của mình. Anh ta có nghĩa là '&' ('* a = & x'). Norice làm thế nào tôi tách '&' khỏi dấu ngoặc đơn – Isaiah

+0

@ Isaiah tôi đã làm điều đó. Biểu thức không hợp lệ và không thể biên dịch. – edmz

Các vấn đề liên quan