2010-09-28 33 views
8

C++ Nó chỉ xảy ra với tôi rằng tôi không biết làm thế nào để khởi tạo một con trỏ đến con trỏ từ một giá trị con trỏ không có một tuyên bố trong C++:Initialize con trỏ đến con trỏ sử dụng nhiều nhà khai thác địa chỉ trong C hoặc

int a = 1; 
int** ppa = &&a; //Does not compile 
int** ppa = &(&a); //Does not compile 
int* pa = &a; //Works but is a 
int** ppa = &pa; //Two step solution 

Tôi có thiếu thứ gì đó không, đó là câu nói hai và cách duy nhất để làm điều đó?

+3

Tại sao bạn nghĩ rằng bạn cần một con trỏ đến con trỏ, trong trường hợp này? – SingleNegationElimination

+0

có thể trùng lặp của [Làm thế nào để con trỏ đến con trỏ làm việc trong C?] (Http://stackoverflow.com/questions/897366/how-do-pointer-to-pointers-work-in-c) –

+1

@Jens Gustedt, điều này không phải là bản sao. Câu hỏi được liên kết hỏi về con trỏ nói chung. Câu hỏi này là về trường hợp cụ thể. –

Trả lời

12

nếu bạn muốn có một con trỏ đến một con trỏ, con trỏ mà bạn muốn trỏ đến phải nằm đâu đó trong bộ nhớ, vì vậy tôi nghĩ rằng không thể có một "một giải pháp bước" vì bạn cần một biến con trỏ mà bạn có thể trỏ đến.

(Lưu ý: Câu này không có nghĩa là trở thành một thử nghiệm ngôn ngữ để sử dụng "điểm" càng nhiều càng tốt trong một câu :-))

14

Bạn không thể nhận con trỏ tạm thời. &a dẫn đến giá trị r. Nó được phép không có địa chỉ thực.

+1

Điều này là chính xác 100%, nhưng tôi đã chấp nhận câu trả lời của Philip thay vì bởi vì nó đi vào lý do tại sao là, thay vì chỉ ra tiêu chuẩn. –

2

Bạn muốn có một con trỏ (gọi nó là PP) đến một con trỏ (gọi nó là P)?

Sau đó, P phải thực sự tồn tại. Có nghĩa là bạn phải khai báo nó.

Tất nhiên trình biên dịch sẽ không thành công tại &&a - vì bạn không thể lấy địa chỉ của địa chỉ. Bạn có thể lấy địa chỉ của một con trỏ - nhưng trước tiên bạn sẽ phải khai báo con trỏ.

Như vậy:

int a = 1; 
int *P = &a; 
int **PP = &P; 
+1

Trình phân tích cú pháp không thành công tại '&& a' không phải vì bạn không thể lấy địa chỉ của một địa chỉ nhưng vì' && 'là một mã thông báo duy nhất không hợp lệ tại thời điểm này trong khai báo. 'int ** ppa = x &&a;' có thể là khởi tạo hợp lệ cho một 'x' được nhập phù hợp và một quá tải hợp lý' && '(ác!) nhưng nó không phải là địa chỉ của một địa chỉ. –

0

Khi bạn làm như sau:

char a; 
char* b = &a; 
char** c = &b; 

Trước hết, hiện có trên ngăn xếp. Nó rõ ràng có một địa chỉ bộ nhớ (tức là vị trí ngăn xếp của nó) đây là những gì bạn gán cho b. b bây giờ cũng tồn tại trên ngăn xếp và sau đó bạn có thể chuyển địa chỉ bộ nhớ của nó tới c. Tuy nhiên, bạn không thể lấy địa chỉ của địa chỉ của một giá trị không có ngăn xếp trung gian vì nó không tồn tại mà không tạo ra nó một cách rõ ràng trước tiên.

-1

này có thể làm việc:

int ** ppa = & (int *) {& a};

+0

Hmm nope nó không, nó tạo ra một tạm thời – fileoffset

7

Có nhiều thứ khác là đúng: Con trỏ của bạn tới con trỏ phải trỏ đến thứ gì đó. Tuy nhiên, trong C99 bạn có thể gian lận bằng cách sử dụng compound literals:

int a = 1; 
int **ppa = &(int *){ &a }; 

literals Compound chỉ là cơ bản đối tượng giấu tên và có các quy tắc bảo quản giống như các đối tượng bình thường. (Nhưng bạn không thể cung cấp thời gian lưu trữ tĩnh hợp lệ theo phạm vi chức năng với từ khóa static). Bạn thậm chí có thể làm tổ họ, do đó bạn có thể viết lại ví dụ trước để một dòng duy nhất:

int **ppa = &(int *) { &(int) { 1 } }; 
+0

Điều này rất có thể sẽ được undefined hành vi và có thể sụp đổ các ứng dụng trong việc sử dụng đầu tiên của con trỏ. Hợp chất theo nghĩa đen là tạm thời và trình biên dịch có thể tái sử dụng không gian đó, vì vậy '* ppa' trỏ tới' & a' trong khi thực thi dòng thứ hai, nhưng có thể trỏ tới bất kỳ thứ gì khác sau đó. –

+1

@David Rodriguez: Không, bạn đã sai. Hợp chất theo nghĩa đen sẽ có cùng thời lượng lưu trữ là 'a' và' ppa': Tĩnh khi ở bên ngoài một hàm, tự động trong khoảng thời gian của khối đóng khác. Xem C99 6.5.2.5 (6). – schot

+1

Bạn hoàn toàn đúng. Tôi nên đã kiểm tra các tiêu chuẩn trước khi nhảy vào một bình luận ... Nếu tại bất kỳ điểm nào bạn sửa đổi câu trả lời, bình luận và tôi sẽ biến -1 thành +1, nó không cho phép tôi thay đổi nó ngay bây giờ. Ở mức nào, tùy thuộc vào những gì bạn muốn làm với con trỏ, nó là * nguy hiểm * như là giải pháp biến trung gian. –

5

C++ 03 [Section 5.3.1] nói

Kết quả của & hành unary là một con trỏ đến nó toán hạng. Toán hạng phải là lvalue hoặc id đủ điều kiện.Trong trường hợp đầu tiên, nếu loại của biểu thức là “T”, loại kết quả là “con trỏ tới T.”

trong &&a, & điều hành có thể không được áp dụng cho các kết quả của &a bởi vì kết quả không phải là lvalue.

Đồng thời đọc this chủ đề

2

Địa chỉ là số. Nó chỉ có một địa chỉ riêng của nó nếu nó được giữ trong một biến, tức là một con trỏ. Vì vậy,

int *i1 = &a; 

có ý nghĩa, nhưng

int **i2 = &&a; 

làm cho không có ý nghĩa. Tuy nhiên

int **i2 = &i1; 

không có ý nghĩa. Có lý?

+1

Thuật ngữ của bạn sai. Địa chỉ của toán tử * thực hiện * mang một con trỏ, xem [ISO03, 5.3.1 expr.unary.op §2]. Thông thường, hãy gọi con trỏ * giá trị * "địa chỉ" và con trỏ * biến * "con trỏ", nhưng nói đúng, điều đó là sai. – fredoverflow

+0

Thuật ngữ tôi đã sử dụng phổ biến. Giá trị của một con trỏ trong ý nghĩa của Standard là một địa chỉ theo bất kỳ nghĩa nào, mà lần lượt là một con số theo bất kỳ nghĩa nào. Để đặt những gì tôi nói một cách khác, & không mang lại một biến *, * do đó, nó không mang lại bất cứ điều gì có địa chỉ có thể được thực hiện. – EJP

0

Sự cố khi bạn làm điều gì đó như &&a; là bạn đang yêu cầu "địa chỉ của địa chỉ a".

Điều đó không có ý nghĩa. Chúng tôi có thể lấy địa chỉ của a tốt, nhưng điều đó không cung cấp cho chúng tôi biến mà chúng tôi có thể lấy địa chỉ. Nó chỉ cung cấp cho chúng ta một giá trị con trỏ. Cho đến khi giá trị đó được lưu trữ ở đâu đó, chúng ta không thể lấy các addres của nó.

Nếu bạn có mã như 2+2, kết quả không có địa chỉ. Nó chỉ là giá trị 4, nhưng nó chưa được lưu trữ ở bất cứ đâu, vì vậy chúng tôi không thể lấy địa chỉ. Khi chúng tôi lưu trữ nó vào biến số int, chúng tôi có thể lấy địa chỉ của biến đó.

Về cơ bản, vấn đề là sự khác biệt giữa các giá trị và các biến. Giá trị chỉ là một số (hoặc một ký tự hoặc một số dữ liệu khác). Biến là một nơi trong bộ nhớ, nơi một giá trị được lưu trữ. Một biến có một địa chỉ, nhưng một giá trị thì không.

Trong C++ - nói, đó là sự khác biệt giữa giá trị và giá trị. Một rvalue về cơ bản là tạm thời, nó thường là một giá trị được trả về từ một hoạt động khác (chẳng hạn như toán tử & trong trường hợp của bạn), nhưng giá trị đó chưa được lưu trữ ở bất kỳ đâu.

Khi bạn lưu trữ nó vào một biến, bạn sẽ nhận được một giá trị và các giá trị có địa chỉ bạn có thể thực hiện.

Vì vậy, có, bạn cần hai câu lệnh riêng biệt. Trước tiên, bạn lấy địa chỉ, và sau đó bạn lưu trữ địa chỉ đó ở đâu đó. Và sau đó bạn có thể lấy địa chỉ của "một nơi nào đó" này.

+0

Thuật ngữ của bạn sai. Địa chỉ của toán tử * thực hiện * mang một con trỏ, xem [ISO03, 5.3.1 expr.unary.op §2]. Thông thường, hãy gọi con trỏ * giá trị * "địa chỉ" và con trỏ * biến * "con trỏ", nhưng nói đúng, điều đó là sai. – fredoverflow

+0

@Fred: đủ công bằng. Tôi nghi ngờ tôi sẽ gặp rắc rối về điều đó. ;) Điều đó sẽ dạy tôi cố gắng lặp lại ngữ nghĩa C++: p – jalf

+0

Sửa lỗi nó lên một chút. Hy vọng tôi nhận được các bit gây hiểu lầm nhất. – jalf

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