2009-12-17 56 views
14

Tôi đang cố gắng sử dụng chuyển bằng tham chiếu trong C để hàm có thể sửa đổi các giá trị của các thông số được truyền cho nó. Đây là chức năng chữ ký:Vượt qua tham chiếu trong C

int locate(char *name, int &s, int &i) 

Tuy nhiên khi tôi cố gắng để biên dịch nó tôi nhận được lỗi này mà đề cập cụ thể đến dòng trên:

error: expected ‘;’, ‘,’ or ‘)’ before '&' token

Nếu tôi loại bỏ các '&' chương trình sẽ biên dịch , nhưng nó sẽ không hoạt động chính xác, rõ ràng. Có gì sai ở đây? Làm thế nào tôi có thể thực hiện cuộc gọi bằng công việc tham chiếu?

+7

Tại sao bạn nghĩ rằng đi qua tham chiếu nên làm việc trong C?C không có tham chiếu. –

+2

Chắc chắn rồi. Nó chỉ gọi tham chiếu của nó là "con trỏ". – Crashworks

+7

"con trỏ" không được "chuyển bằng tham chiếu". Bất cứ điều gì bạn chuyển đến một hàm trong C, nó được truyền theo giá trị. Nó có thể xảy ra rằng thứ được truyền qua là con trỏ, trong trường hợp này, hàm nhận được * bản sao của con trỏ * và có thể sử dụng bản sao đó để thay đổi giá trị được trỏ tới bởi con trỏ, nhưng chính con trỏ được truyền theo giá trị . –

Trả lời

34

C không có tham chiếu. Bạn cần chuyển con trỏ đến biến mà bạn muốn sửa đổi:

int locate(char *name, int *s, int *i) 
{ 
    /* ... */ 

    *s = 123; 
    *i = 456; 
} 

int s = 0; 
int i = 0; 
locate("GMan", &s, &i); 

/* s & i have been modified */ 
7

C không hỗ trợ tham chiếu. Bạn sẽ cần C++ để thực hiện theo cách được viết hoặc sửa đổi thành

int locate(char *name, int *s, int *i) 

và chuyển con trỏ đến biến tham số thứ hai và thứ ba.

20

C không có biến tài liệu tham khảo nhưng bạn có thể xem xét tham chiếu như con trỏ const để dữ liệu như vậy,

Hãy trỏ const số liệu như thế này để điểm con trỏ không thể để các dữ liệu khác nhưng dữ liệu được trỏ bởi nó có thể được đã thay đổi.

int locate (char *name, int * const s, int * const i) 
+0

+1 cho đề xuất con trỏ const – Qberticus

1

Bạn không thể thực hiện việc này trong c. c không có tham chiếu, bạn có thể sử dụng con trỏ để thay thế.

1

Nếu bạn muốn sử dụng truyền theo phương pháp tham chiếu để sửa đổi tham số được sử dụng trong cuộc gọi hàm, luôn sử dụng con trỏ làm đối số chính thức của hàm.

Do đó thay vì sử dụng sử dụng

int locate(char *name, int &s, int &i) 

này,

int locate(char *name, int *s, int *i) 

Khi nào bạn sẽ gọi hàm này, bạn có thể sử dụng

.........

int a=5; 
int d=10; 
char c='A'; 
int result; 

result=locate(&c, &a, &d); 

Tôi hy vọng tất cả sẽ là cle ar bây giờ,

Đối với ý tưởng thêm về đi ngang qua giá trị hoặc đi ngang qua tham khảo và cái nào là tốt hơn, nguồn này là tốt cho người mới bắt đầu

http://www.learnc.net/call-by-reference.php

Hãy vui vẻ.

+0

Tôi chắc chắn 'name' không phải là một con trỏ trỏ tới một' char' đơn lẻ. – Downvoter

1

Các câu trả lời sớm hơn có vẻ thiếu ngữ cảnh và không giải quyết thuộc tính mà con trỏ C bị quá tải. Hoàn toàn công bằng khi tuyên bố rằng C "đi qua tham chiếu". Con trỏ cũng là một tham chiếu. Tuy nhiên, chính thức hơn, một tham chiếu C là cơ chế biểu diễn địa chỉ bộ nhớ của ký hiệu.

  • Con trỏ chỉ đơn giản là biến trong bộ nhớ có giá trị được coi là địa chỉ .
  • Tham chiếu chỉ đơn giản là giá trị theo nghĩa đen cho địa chỉ bộ nhớ.
  • Ngôn ngữ C cho phép truyền qua tham chiếu - nhưng chỉ trong ngữ cảnh phù hợp!

Tách ngữ cảnh là định nghĩa chữ ký và lời gọi chữ ký.

Hãy xem xét nguyên thủy int a = 0x22e8; và một nơi khác mà chúng tôi khai báo int* b = &a; (Tôi sẽ nhận được chức năng sau một phút).

Chúng ta có thể hình dung việc này mà nhớ (giả định endianness không quan trọng ví dụ này):

... 
0x00000200:  22e8  ; this is the variable for int a's literal value: 
           ; a == 0x000022e8 
           ; &a == 0x00000200 
0x00000???:  9090  ; ... more code ... 
0x00000400:  0200  ; this is pointer b pointing to a's address: 
           ; b == 0x00000200 
           ; *b == 0x000022e8 
           ; &b == 0x00000400 
... 

Thật dễ dàng để thấy rằng chúng ta có thể gán một con trỏ đến bất kỳ địa chỉ mà không cần bất kỳ thủ thuật đặc biệt. Một con trỏ chỉ là một biến, nhưng C cho phép chúng ta tham chiếu đến địa chỉ mà nó trỏ đến; chúng ta có thể "dereference" con trỏ từ địa chỉ giá trị của nó để thay thế coi con trỏ là giá trị cơ bản của con trỏ trong một ngữ cảnh yêu cầu: while (*b == a) .... Chúng ta có thể dễ dàng gọi b == &a.

Khi áp dụng tính năng này để thực hiện cuộc gọi, bạn phải tách biệt ngữ cảnh của hàm (chữ ký) định nghĩa so với yêu cầu để phân biệt đường truyền theo tham chiếu.

int* foo(int* blah, int nah) { .. }  // signature definition context: 
             // These are parameters 
... vs ... 

b = foo(&a, 4);      // invocation context: 
             // These are arguments 

Trong việc xác định một chữ ký chức năng, chúng tôi không nói với trình biên dịch mà giải quyết một cuộc tranh cãi được truy cập từ — thời gian chạy thậm chí chưa biết! Nó chỉ là vô nghĩa để xác định void bar(int &blah) {...}. Thay vào đó, chúng tôi sử dụng cú pháp con trỏ bị bỏ qua — "bất kỳ đối số nào được truyền vào sẽ được tải tại địa chỉ được trỏ tới" — để tham chiếu giá trị đối số mong muốn khi thời gian chạy xảy ra. Như vậy C có thể truyền tham số bằng tham chiếu.

Ngữ cảnh của cả hai định nghĩa chữ ký hàm và các cuộc gọi hàm thay đổi cách trình biên dịch xem xét quá tải con trỏ so với tham chiếu và cách thời gian chạy thực sự có thể giải quyết chúng.

+0

Để rõ ràng hơn, cú pháp C "tham chiếu" thực tế là cú pháp và: "& a'. Và cũng" đi qua tham chiếu ",' b = foo (& a, 4) ', xảy ra khi chạy trong khi thực hiện cuộc gọi hàm; và định nghĩa chữ ký, 'int * foo (int * a, int nah) {..}' là thiết lập để cho phép tham chiếu đi qua. – ToFue

0

(Tôi đã sử dụng C trong một thời gian nhưng tôi vẫn còn khá mới đối với vài khái niệm trong C. Tôi đang cố gắng trả lời điều này theo hiểu biết tốt nhất của tôi, cảm thấy tự do để sửa tôi Nếu tôi sai)

Khi bạn nói chuyển bằng tham chiếu, bạn chuyển địa chỉ và làm như vậy, bạn sẽ sử dụng con trỏ trỏ đến địa chỉ. Vì vậy, bạn cần phải chuyển các con trỏ đến nguyên mẫu hàm của bạn nhưng những gì bạn đang làm là truyền địa chỉ trực tiếp.

Chức năng của bạn cố gắng là không tham chiếu (sử dụng &) con trỏ của bạn, nhưng bạn không bao giờ có con trỏ đến tham số 'và' i 'để không tham chiếu đến nó.

Cách đúng để làm cho các nguyên mẫu hàm/định nghĩa là

int locate(char *name, int *s, int *i) 

và khi bạn phải gọi chức năng này bạn sử dụng việc kê khai dưới đây trong chức năng chính hoặc gọi

int locate(char *name, &s, &i) 
Các vấn đề liên quan