it-swarm-vi.com

Một lời giải thích tốt đẹp cho con trỏ là gì?

Trong các nghiên cứu của riêng bạn (một mình hoặc cho một lớp học) bạn đã có một khoảnh khắc "ah ha" khi cuối cùng, bạn thực sự hiểu con trỏ? Bạn có một lời giải thích bạn sử dụng cho các lập trình viên mới bắt đầu có vẻ đặc biệt hiệu quả?

Ví dụ: khi người mới bắt đầu lần đầu tiên gặp con trỏ trong C, họ có thể chỉ cần thêm &cát *s cho đến khi nó biên dịch (như bản thân tôi đã từng làm). Có thể đó là một bức tranh, hoặc một ví dụ thực sự có động lực, đã khiến con trỏ "nhấp chuột" cho bạn hoặc học sinh của bạn. Nó là gì và bạn đã thử những gì trước đây dường như không hoạt động? Có bất kỳ chủ đề nào là điều kiện tiên quyết (ví dụ: cấu trúc hoặc mảng) không?

Nói cách khác, những gì cần thiết để hiểu ý nghĩa của &cát *, khi bạn có thể sử dụng chúng với sự tự tin? Học cú pháp và thuật ngữ hoặc các trường hợp sử dụng là không đủ, tại một số điểm, ý tưởng cần phải được tiếp thu.


Cập nhật: Tôi thực sự thích các câu trả lời cho đến nay; hãy giữ cho họ đến Có rất nhiều quan điểm tuyệt vời ở đây, nhưng tôi nghĩ nhiều người là những lời giải thích/khẩu hiệu tốt cho chính chúng ta sau khi chúng ta đã nội tâm hóa khái niệm này. Tôi đang tìm kiếm bối cảnh và hoàn cảnh chi tiết khi nó chợt nhận ra bạn.

Ví dụ :

Tôi chỉ hiểu phần nào về con trỏ cú pháp trong C. Tôi nghe hai người bạn của tôi giải thích về con trỏ cho một người bạn khác, họ hỏi tại sao một struct được truyền bằng một con trỏ. Người bạn đầu tiên nói về việc cần phải tham khảo và sửa đổi như thế nào, nhưng đó chỉ là một nhận xét ngắn từ người bạn khác, nơi nó đánh tôi: "Nó cũng hiệu quả hơn." Vượt qua 4 byte thay vì 16 byte là sự thay đổi khái niệm cuối cùng tôi cần.

72
Macneil

Sơ đồ bộ nhớ dưới dạng lưới

Thông thường những gì tôi làm là biểu diễn bộ nhớ dưới dạng "lưới", để tôi có thể tạo địa chỉ, làm nổi bật các không gian bộ nhớ khác nhau và ghi vào các giá trị ô (hoặc thậm chí xa hơn, biểu diễn nhị phân của chúng) và liên kết các con trỏ trong bộ nhớ với các giá trị chúng chỉ vào. (Và sau đó vẫn đề cập rằng đó là một sự đơn giản hóa).

Thông thường đó là khoảnh khắc "ohhhh" đối với hầu hết các học sinh của tôi.

Biểu tượng tung hứng

Sau đó, khi nói đến việc họ ngừng quên cách sử dụng & và *, điều đó rất đơn giản: trình bày nó giống như cách họ thực hiện các phép tính toán học hoặc vật lý. Nếu bạn chia khoảng cách tính bằng km cho thời gian tính theo giờ, bạn sẽ có được tốc độ tính bằng km/h. Có gì cần phải ra ngoài. Đơn giản.

in ra để giải cứu

Chỉ làm một vài ví dụ cơ bản thể hiện trực quan những gì bạn đã giải thích với những điều này sẽ giúp họ thoải mái trong những gì họ nghĩ họ đã hiểu hoặc cho họ cơ hội để nói "ah, tôi không hiểu điều này".

Mở rộng

Con trỏ che cho các loại đơn giản và đảm bảo rằng chúng hiểu sự khác biệt giữa địa chỉ và kích thước của một loại dữ liệu, sau đó cấu trúc, sau đó là mảng và nhiều cấp độ.

Sau đó bắt đầu số học con trỏ.


Phụ lục: Đệ quy

Tôi thường giải thích đệ quy tương tự, sử dụng một biểu diễn trực quan. Yêu cầu họ in bảng chữ cái bằng cách sử dụng chức năng được tạo sẵn để viết một ký tự đơn, sau đó yêu cầu họ in theo thứ tự ngược lại bằng cách chỉ thay đổi hai dòng.

Thông thường có một "cái gì ...?" Khoảnh khắc và khi bạn chỉ thêm một tham số khác vào printf của mình để in các giá trị số và thụt các bước, nó sẽ trở thành một tiếng thở phào nhẹ nhõm.


Lựa chọn thay thế: Mô hình Play-Doh và Cup nước

Tôi thực sự đã có một số đồng nghiệp trong một trường đại học đã cho sinh viên xem một video giải thích các con trỏ và truy cập bộ nhớ bằng cách sử dụng dán play-doh. Nó cực kỳ thông minh và được thực hiện tốt, mặc dù tôi chưa bao giờ thực sự sử dụng kỹ thuật đó cho mình, ngoại trừ những người học rất trẻ quan tâm đến việc nắm bắt lập trình (nhưng thường thì những người tôi sẽ không hướng họ đến một ngôn ngữ sử dụng con trỏ quá sớm). Về cơ bản, sử dụng các quả bóng play-doh nhỏ mà bạn có thể gắn vào các quả bóng play-doh lớn hơn khác đại diện cho các không gian bộ nhớ và bạn có thể kết hợp với nhau để liên kết chúng (như trong cấu trúc dữ liệu được liên kết) hoặc hợp nhất với nhau (như tiếp giáp nhau không gian bộ nhớ). Sử dụng các màu khác nhau cho các không gian bộ nhớ được trỏ đến và các con trỏ cũng giúp. Nhưng tôi vẫn nghĩ rằng Bộ nhớ dưới dạng lưới hoạt động tốt hơn, vì bạn có thể thấy rõ rằng việc chỉ điểm thực sự là vấn đề "giải quyết", như trên "bản đồ/lưới". Trong khi đó, chế độ Play-doh vẫn khiến họ nhầm lẫn rằng mọi thứ thực sự "chạm" vào nhau trong bộ nhớ.

Thứ Water Cup cũng được sử dụng trực tiếp bởi một đồng nghiệp, nhưng tôi không biết liệu cô ấy có nghĩ ra nó không. Đó là một cách tiếp cận thú vị, nhưng tôi nhận thấy nhiều sinh viên đã bị bối rối bởi lời giải thích. Một cái gì đó tương tự như Kỹ thuật Cup cà phê của DevSolo . Nhưng tôi nghĩ rằng nó thực sự là một sai lầm khi bạn làm cho các sinh viên nhầm lẫn giữa các thùng chứa, cấu trúc dữ liệu, con trỏ và mảng. Nó có thể là một cách tiếp cận thú vị để giải thích các mảng lúc đầu tôi giả sử, nhưng tôi sẽ không gắn bó lâu dài.

25
haylem

Một người khôn ngoan hơn tôi từng nói:

Nữ tu Wu Jincang đã hỏi Ngài Patriach Huineng thứ sáu, "Tôi đã nghiên cứu kinh điển Mahaparinirvana trong nhiều năm, nhưng có nhiều lĩnh vực tôi không hiểu lắm. Xin hãy khai sáng cho tôi."

Người yêu nước trả lời: "Tôi không biết chữ. Xin vui lòng đọc các ký tự cho tôi và có lẽ tôi sẽ có thể giải thích ý nghĩa."

Nữ tu nói, "Bạn thậm chí không thể nhận ra các ký tự. Làm thế nào bạn có thể hiểu ý nghĩa?"

"Sự thật không liên quan gì đến lời nói. Sự thật có thể được ví như mặt trăng sáng trên bầu trời. Từ ngữ, trong trường hợp này, có thể được ví như ngón tay. Ngón tay có thể chỉ vào vị trí của mặt trăng. Tuy nhiên, ngón tay không phải là Mặt trăng. Để nhìn lên mặt trăng, cần phải nhìn ra ngoài ngón tay, phải không? "

80
Frank Shearar

Tôi thấy rằng sơ đồ là rất hữu ích. Thí dụ:

pointer diagram


[.___ Ngoài ra, khi thực hiện bằng bút chì, tôi có thể sử dụng nó để theo dõi chương trình của mình trên giấy hoặc trên bảng/bảng trắng.

46
Michael K

Khi tôi lần đầu tiên "học" về con trỏ, tôi đã bị đẩy vào đó. Trường đại học của tôi đã đưa ra quyết định từ lâu trước khi tôi đăng ký tập trung vào chương trình giảng dạy quanh Java, vì vậy khi giáo sư Cấu trúc dữ liệu của tôi giảng một bài về C và yêu cầu chúng tôi thực hiện Danh sách XOR với các con trỏ tôi cảm thấy như mình đang tham gia vào một cái gì đó cách qua đầu tôi.

Tôi hiểu định nghĩa:

Một con trỏ là một biến chứa địa chỉ của một biến

Nhưng tôi vẫn không hiểu một phần lớn của khái niệm này. Nhìn lại, tôi nghĩ nó tập trung vào ba điều:

  1. Chính xác là gì một vị trí bộ nhớ? (Tại thời điểm đó tôi không tham gia lớp Tổ chức Máy tính)

  2. Cú pháp vụng về (Vậy ừm ... tại sao chính xác nó được định nghĩa như "int * ip" nhưng sau đó tôi gọi biến là "ip"?)

  3. Làm thế nào chính xác là có lợi để lưu trữ địa chỉ của một biến thay vì chỉ sử dụng biến?

Mãi cho đến khi tôi mua cuốn sách K & R và hoàn thành mọi vấn đề mà tôi thực sự nắm bắt được về con trỏ. Bên cạnh thực tế là tôi đã hoàn thành lớp Tổ chức Máy tính (mà tôi nghĩ là cần thiết trước khi học C), một phần của nó phải làm với thực tế là tôi nhận ra rằng con trỏ có thể được sử dụng cho các hàm, mảng, cấu trúc ... để làm những việc hữu ích và không chỉ đơn thuần là lưu trữ cho địa chỉ của các biến thông thường.

Nhưng khoảnh khắc "aha" của tôi cho đến nay là cách K & R giải thích cú pháp khó xử khi xác định một con trỏ đơn giản. Tôi đã ghi chú trong suốt cuốn sách (trong đó tôi viết lại các điểm được tạo ra bởi cuốn sách theo từ của riêng tôi để hiểu thêm) và đây là một trong những điều liên quan đến điều đó:

Một con trỏ là một biến chứa một địa chỉ cho một biến. Một con trỏ vừa được xác định vừa được hủy đăng ký (mang lại giá trị được lưu trữ tại vị trí bộ nhớ mà nó trỏ đến) với toán tử '*'; các biểu hiện là ghi nhớ.

Ex.: 
   int a;      /* Variable 'a' is an integer */

   int *ip;   /* Variable ip is a pointer and dereferencing it gives an integer.
                 In other words, the expression *ip is an int, so ip is a pointer
                 to an int */

Tôi đã luôn cảm thấy rằng tôi không thể hoàn toàn nắm bắt được các khái niệm tiên tiến hơn về con trỏ cho đến khi tôi có một thứ gì đó quá sâu sắc trong đầu. Nó đã làm phiền tôi vô tận sau nhiệm vụ đó (nhân tiện tôi không làm tốt lắm;)) tại sao "* ip" không tồn tại ngay sau khi tôi (nghĩ rằng tôi) định nghĩa "* ip". Nắm vững điều này là điều cần thiết cho các khái niệm nâng cao hơn liên quan đến con trỏ, như con trỏ hàm và các định nghĩa phức tạp hơn như thế này:

char (*(x())[])()

Nói chung, tôi nghĩ rằng khái niệm con trỏ đòi hỏi:

  1. Một sự hiểu biết cơ bản về cách bộ nhớ được đặt ra trong một máy tính (và bộ nhớ là gì).

  2. Kiến thức về cách con trỏ mạnh mẽ có thể (sử dụng trong thế giới thực, không chỉ là một khái niệm trừu tượng khác mà chúng học vì lợi ích của việc học).

  3. Giải mã chữ tượng hình thông thường được gọi là "định nghĩa của một con trỏ"

Vì vậy, tất cả trong tất cả, tôi nghĩ nên có ít nhất 3 khoảnh khắc "aha" khi tìm hiểu về con trỏ. Tôi vẫn còn là một sinh viên nên tôi nghĩ bạn sẽ đánh giá cao quan điểm của một người vẫn còn (tương đối) mới học khái niệm này.

32
Kevin

Con trỏ hơi giống với các phím tắt ứng dụng trên máy tính để bàn của bạn. Xóa các phím tắt và mục tiêu vẫn tồn tại. Bắt đầu các phím tắt và mục tiêu được bắt đầu.

Tôi luôn giải thích công việc này bằng cách đơn giản tạo một tệp txt trên máy tính để bàn của tôi và hai phím tắt cho tệp. Sau khi sao chép và xóa các phím tắt, bạn có thể thấy mọi người hiểu ý tưởng đằng sau 'tài liệu tham khảo'.

Khi nhóm hiểu được cơ bản đằng sau các phím tắt, bạn có thể bắt đầu giải thích các con trỏ bằng mọi cách bạn muốn. Họ có thể sẽ hiểu nó khá dễ dàng.

19
Barfieldmv

8-10 năm trước, tôi đã dạy một khóa học giới thiệu "C" tại một trường cao đẳng cộng đồng. Đây luôn luôn là một chủ đề thú vị để khám phá. Điều có vẻ hoạt động tốt nhất, và điều này là sau khi thảo luận với đồng nghiệp một vài lần là sử dụng cốc cà phê và bàn tay của bạn.

Tôi đã sử dụng sự tương tự của một tách cà phê (hoặc hàng của chúng cho các mảng) như là một biến (nó có thể chứa một cái gì đó). Sau đó, tôi đã sử dụng bàn tay của mình, cũng có thể giữ một cái gì đó hoặc, bằng cách mở rộng ngón trỏ của mình để "chỉ vào" một tách cà phê.

Một bàn tay gần gũi là vô giá trị, một ngón tay chỉ vào đầu tôi (giống như một khẩu súng giả) là một con trỏ lơ lửng.

Sau đó, với một vài cuộc biểu tình và các chuyến đi thông qua trình gỡ lỗi, nó đã nhấp vào hầu hết.

14
DevSolo

Tôi thực sự khá lo lắng khi nghe câu hỏi "làm thế nào bạn nắm bắt được con trỏ". Tôi luôn nghĩ rằng khái niệm này cực kỳ đơn giản và một sự phát triển logic của các ngôn ngữ cung cấp sức mạnh lớn cho các lập trình viên.

Điều làm tôi lo lắng là tôi không bao giờ thấy khó hiểu về khái niệm con trỏ. Vì vậy, khi bạn ở đây "khi nào bạn cuối cùng đã nhận được nó" nhiều lần, bạn bắt đầu suy nghĩ:

Tôi thực sự có được nó? Có lẽ tôi chưa bao giờ làm?

Có lẽ lý do tại sao khái niệm này có vẻ khó hiểu, là bởi vì chúng tôi tiếp tục nói với tất cả những người chưa gặp họ rằng con trỏ rất khó, và đây là một trăm cách bạn có thể học?

Chỉ cần ném ý tưởng đó ra, tất nhiên cá nhân tôi thích một sơ đồ tốt và Steve Gibson luôn làm tốt công việc giải thích mọi thứ !

10
Marcus Whybrow

Tôi chưa bao giờ gặp vấn đề với con trỏ trong C, nhưng điều đó có thể là do tôi phải học trình biên dịch trước. Thật là nhẹ nhõm khi không phải tự mình quản lý địa chỉ nữa. Vì vậy, có lẽ câu trả lời (giả sử đây là điều bạn đang dạy) là cung cấp cho sinh viên một ngôn ngữ hội được mô phỏng để làm việc. Họ sẽ tìm ra nó trong quá trình viết bất cứ điều gì tinh vi hơn "Xin chào, thế giới."

7
Larry Coleman

Một con trỏ là một biến có giá trị là địa chỉ bộ nhớ của một biến khác.

7
kirk.burleson

Làm thế nào tôi thực sự học về con trỏ? Bằng cách viết một trình biên dịch sinh viên năm nhất đại học.

Làm thế nào để giải thích con trỏ trong các điều khoản của giáo dân? Tôi thích sự tương tự (ngày?) Của một danh mục thư viện được lưu trữ trên thẻ chỉ mục. Mỗi thẻ ("con trỏ") chứa thông tin về vị trí của một số sách ("dữ liệu"), nhưng thực tế không chứa chính cuốn sách đó. Nếu bạn sửa đổi thẻ ("số học con trỏ"), tất cả những gì nó làm là thay đổi cuốn sách mà nó trỏ đến và không có tác động đến chính cuốn sách - chỉ cần cẩn thận không làm hỏng địa chỉ hoặc bạn có thể trỏ đến một cuốn sách không tồn tại hoặc thậm chí là thư viện sai. Tuy nhiên, nếu bạn theo dõi "địa chỉ" trên thẻ và đi đến phần thích hợp của thư viện ("lấy con trỏ"), bạn có thể xem/sửa đổi chính cuốn sách.

6
Yevgeniy Brikman

Được chỉnh sửa để hỗ trợ cho yêu cầu sửa đổi của câu hỏi

Con đường của tôi để hiểu "con trỏ bài" (nếu tôi nhớ chính xác) đã đi như thế này. Tôi đã có một số kinh nghiệm đơn giản về lập trình hội từ khi tôi còn mucking xung quanh với BBC Micro vì vậy tôi có khái niệm về bộ nhớ như một bó hộp (xem bên dưới để biết điều này). Điều này đã được củng cố bằng cách sử dụng các mảng. Tuy nhiên, tôi đã đi vào thế giới của C và phải đối phó với các chuỗi và điều đó có nghĩa là con trỏ. Trong BASIC, điều này là không quan trọng, trong trình biên dịch chương trình, tôi không bao giờ phải làm việc với họ, và bây giờ trong C cổ điển, tất cả đều là con trỏ và công cụ. À, nhưng tôi có thể quay lại các mảng với các chuỗi (null đã kết thúc) như thế này:

char s[] = "Hello, world!";
printf("%s",s);

Tất cả đều tốt và tốt, đó chỉ là một mảng ký tự (8 bit cho mỗi ký tự trong thế giới nhỏ bé của tôi) với ký tự 0 ở cuối để hiển thị nơi kết thúc. Printf chỉ cần lấy mảng đó và chạy qua nó in nó. Nhưng nếu tôi muốn truyền chuỗi này vào một hàm thì sao?

void print_str(char* p) {
  printf("%s",p);
}

Là những gì hướng dẫn nói, nhưng những gì * tất cả về? Hmm, char * có nghĩa là "con trỏ tới char". OK ... mất tôi. Sau đó, tôi nhận ra rằng char * làm cho p tương đương với s [0]. OK, tôi có thể sử dụng nó, nhưng tôi vẫn chưa hiểu được con trỏ là gì. Ý tôi là, làm thế nào để tôi thiết lập một số dữ liệu với một trong những điều này? Tắt hướng dẫn sử dụng một lần nữa ...

char* p = "Hello World!";

Khi tôi viết ở trên, tôi tự nói với bản thân mình "khai báo một con trỏ tới char và đặt nó bằng với mảng ký tự này". Bằng cách nào đó con trỏ không cần đến một mảng. Đoán đó là trình biên dịch làm một số thứ cho tôi để thay đổi. Vậy làm thế nào tôi có thể thay đổi mảng với con trỏ này? Tôi biết rằng tôi có thể sử dụng phiên bản mảng

 s[2] = 'L'; 

nhưng những gì tương đương trong "con trỏ nói"? Tắt hướng dẫn đó một lần nữa ...

*(p+2) = 'L';

Tôi cho rằng * đơn giản có nghĩa là "nội dung của địa chỉ bộ nhớ" và (p+2)s[2]. Điều đó có nghĩa là con trỏ p chỉ ... một ... địa chỉ ... bong!

Đó là âm thanh của Khai sáng. Tôi đột nhiên vặn con trỏ (đó là một thời gian dài trước đây, bộ tính giờ cũ của chúng tôi đã không "mò mẫm" cho đến sau này). Đó chỉ là sự thiếu quyết đoán.


Nguyên:

OK, giá trị 2c của tôi:

Hãy tưởng tượng bộ nhớ là một loạt các hộp. Mỗi hộp có một số ở bên cạnh (địa chỉ). Mỗi hộp chứa một số (nội dung). Bạn có thể làm việc với các hộp này theo 2 cách: biến (tôi muốn nội dung của hộp N), con trỏ (tôi muốn nội dung của hộp bất cứ thứ gì có trong hộp N ). Con trỏ chỉ đơn giản là vô cảm.

Và đối với câu trả lời lớn bao gồm mọi thứ bạn cần biết - đọc cái này .

5
Gary Rowe

Tôi sẽ giả sử ai đó sẽ học con trỏ biết các biến thông thường là gì và cách chúng hoạt động trong C. Bây giờ, hãy thử xác định các con trỏ với một số thuộc tính của nó-

  • Chúng cũng là các biến, nhưng có bản chất khác nhau. Giả sử có hai lớp trong không gian biến. Các biến thông thường của các loại khác nhau nằm ở lớp trên và con trỏ ở lớp dưới. Giống như con số này-

    alt text

  • Như tên 'Con trỏ' gợi ý, con trỏ có thể ĐIỂM một cái gì đó. Giống như ngón tay của chúng ta có thể chỉ vào một số đối tượng. Những điều họ chỉ đến là gì? Đây là các biến bình thường. Nói tóm lại, "Con trỏ trỏ đến các biến thông thường".

  • Giống như các biến thông thường, con trỏ cũng có cùng số loại như int, char hoặc float. Và một con trỏ của một loại cụ thể có thể chỉ đến cùng một loại biến.
  • Một con trỏ có thể trỏ đến một biến và sau đó cùng một con trỏ có thể trỏ đến một biến khác. Chỉ là loại nên giống nhau. Vì vậy, liên kết của một con trỏ với một số biến không phải là vĩnh viễn và có thể thay đổi.
  • Vì vậy, làm thế nào một con trỏ được khai báo? Gần giống như các biến thông thường. Bạn phải đặt trước tên bằng dấu hoa thị (*). Giống-

    int *pointer;
    
  • Sau đó, làm thế nào một con trỏ được liên kết với một biến? Sử dụng & toán tử trước biến như câu lệnh này-

    pointer = &variable;
    
  • Làm thế nào một con trỏ được sử dụng bằng cách chỉ vào một biến? Điều này cũng được thực hiện bằng cách đặt trước tên bằng dấu hoa thị (*). Sau đó, nó có thể được sử dụng ở vị trí của biến mà nó đang chỉ bây giờ-

    *pointer = var1 + var2;
    

    thay vì

    variable = var1 + var2;
    
  • Bây giờ, chơi với con trỏ với một số mã. Bây giờ chỉ cần làm quen với đặc điểm này của con trỏ. Cho đến thời điểm này, chúng ta đang nói về những gì con trỏ làm. Khi bạn đã ổn với nó, sau đó bắt đầu nghiên cứu cách con trỏ trỏ đến một số biến và cách chúng phản ứng nếu các phép toán số học thông thường được áp dụng trên chúng. Sau đó, đi cho mối quan hệ giữa con trỏ và mảng và con trỏ đến con trỏ.

Đó là tất cả tôi sẽ đề nghị về con trỏ học tập.

5
Gulshan

Lấy một số khối gỗ nhỏ.

thêm móc kim loại vào một đầu và mắt kim loại ở đầu kia.

bây giờ bạn có thể thực hiện một danh sách được liên kết trong những thứ bạn có thể chơi với.

Hãy thử giải thích với chỗ dựa vật lý này. Tôi thường ước mình có được điều này khi dạy con trỏ cho sinh viên năm thứ nhất (sinh viên năm nhất).

Cái móc kim loại nhỏ là con trỏ, khối gỗ thứ được chỉ vào.

Tôi DEFY bất cứ ai để không nhận được nó sau khi chơi với các khối.

4
Tim Williscroft

Tôi đã làm cho cuộc sống của mình dễ dàng hơn khi tôi loại bỏ tất cả lông tơ và bắt đầu coi con trỏ như bất kỳ biến nào khác thay vì một thực thể ma thuật nào đó (từ lâu ở lớp 11) .. chỉ cần biết 3 điều:

  1. Con trỏ là một biến lưu trữ địa chỉ của một biến khác (hoặc chỉ bất kỳ địa chỉ nào).
  2. * được sử dụng để lấy giá trị tại vị trí bộ nhớ được lưu trong biến con trỏ.
  3. & toán tử cung cấp địa chỉ của một vị trí bộ nhớ.

Phần còn lại là cú pháp và ý nghĩa thông thường .. Chỉ cần viết một số chương trình C đơn giản (như triển khai thư viện danh sách được liên kết) bằng cách sử dụng con trỏ để hiểu rõ hơn.

4
Sridhar Iyer

Lời giải thích mà tôi thực sự đã đưa ra là:

Hãy xem xét một mạng lưới thành phố với những ngôi nhà khác nhau được xây dựng trên những mảnh đất. Trong tay bạn cầm một tờ giấy. Trên giấy bạn đã viết:


Nhà của David,

112 Vì vậy, đường phố.


Mảnh giấy (biến con trỏ) chứa một địa chỉ điểm đến nhà của David. Khi bạn muốn nói với một người bạn hãy nhìn vào ngôi nhà mát mẻ của David, việc sử dụng tờ giấy làm tài liệu tham khảo cho ngôi nhà sẽ dễ dàng hơn nhiều so với việc gửi tòa nhà hai tầng thực sự trong thư.

Như với con trỏ thực, bạn có thể gặp một số rắc rối khi bạn theo dõi địa chỉ trên mảnh giấy của bạn. David có thể đã di chuyển và khi bạn đến đó, bạn chỉ cần tìm thấy một lỗ hổng lớn trên mặt đất. Trong trường hợp này, tốt hơn hết là xóa địa chỉ trên tờ giấy khi David di chuyển hoặc ít nhất là thay đổi nó thành địa chỉ mới. Bạn cũng có thể thấy rằng bạn đến địa chỉ và nhập những gì bạn nghĩ là phòng khách của bạn David nhưng lần này bạn kết thúc ở một bể bơi hoàn toàn xa lạ. Một số người khác đã sử dụng không gian tại địa chỉ mà bạn có cho một cái gì đó hoàn toàn khác.

2
Per Wiklander
  1. Con trỏ có thể được coi là một khái quát của một chỉ mục thành một mảng. [.__.]
    • Hãy xem xét rằng một mảng lớn có thể được cắt nhỏ thành một số mảng nhỏ hơn, không chồng chéo, có kích thước thay đổi. Bây giờ, các mảng nhỏ hơn là những gì chúng ta thường nghĩ là mảng. Cái lớn hơn là toàn bộ không gian bộ nhớ của máy tính. Quá trình cắt bỏ các mảng nhỏ hơn được gọi là cấp phát bộ nhớ.
  2. Một tập hợp các cấu trúc được liên kết với nhau bởi một số con trỏ có thể được coi là một đồ thị có hướng . [.__.]
    • Mỗi đỉnh là một biến có thể giữ một số giá trị.
    • Một số biến là con trỏ và mỗi con trỏ có thể có chính xác một Edge đi vào một thứ khác.
    • Các biến không phải là con trỏ sẽ không có Edge nào. Họ có thể có bất kỳ số lượng Edge đến.
2
rwong

Nếu bạn muốn giải thích con trỏ, bạn phải giải thích bộ nhớ trước. Tôi thường làm điều đó bằng cách sử dụng biểu đồ giấy/bình phương với các hàng và cột. Nếu "học sinh" hiểu bộ nhớ, cô ấy có thể hiểu địa chỉ là gì. Nếu bạn có địa chỉ, bạn có con trỏ.

Bạn có thể chơi với sự trừu tượng này. Ví dụ. ghi địa chỉ (số) của một hình vuông vào một hình vuông khác. Bây giờ vẽ một mũi tên từ hình vuông con trỏ đến hình vuông đích. Bây giờ ghi đè con trỏ (ví dụ: tăng nó) và điều chỉnh mũi tên. Viết một địa chỉ vào một hình vuông khác và để học sinh vẽ mũi tên ...

Bước tiếp theo: Đặt tên cho một số hình vuông (như con trỏ). Bây giờ bạn có thể giải thích hội nghị. Đó là nó.

2
EricSchaefer

Tôi không thể nhớ được hoàn cảnh xung quanh con trỏ của mình, nhưng tôi đã hồi phục lại bộ nhớ xung quanh sự hiểu biết của tôi về một mảng kiểu c. (tức là arr[3] giống như *(arr+3))

Vì một số lý do, tôi thấy rất hữu ích khi xem con trỏ dưới dạng mảng bất cứ khi nào tôi gặp tình huống con trỏ.

2
Zaz

Về cơ bản @Gary Rowe đã giới thiệu đúng mô hình. Bộ nhớ như một tập hợp các hộp có địa chỉ (số) trên đó. Mỗi hộp lưu trữ một giá trị (số).

Ý tưởng của một con trỏ là diễn giải giá trị trong một hộp là địa chỉ của một hộp khác. Giá trị này được sử dụng để tham chiế vào một hộp cụ thể, đó là lý do tại sao nó được gọi là tham chiế. Do đó dereferences là quá trình mở hộp được giới thiệu.

if v là một biến (hộp), thì câu lệnh

  • v có nghĩa là giá trị của v, tức là cho tôi những gì trong hộp
  • *v có nghĩa là hủy bỏ giá trị của v, tức là cho tôi những gì trong hộp được giới thiệu bằng giá trị của v
  • &v có nghĩa là tham chiếu v, tức là cho tôi địa chỉ trên hộp

Tôi nghĩ nó không phục vụ mục đích giới thiệu con trỏ như một thứ hoàn toàn khác. Đó là một khái niệm khó nắm bắt đối với tôi khi tôi còn là một đứa trẻ. Nó luôn có vẻ như là một phép thuật đen tối mà tôi chưa bao giờ thực sự hiểu, cần rất nhiều nhân vật đặc biệt. Lần đầu tiên tôi hiểu là khi tôi viết một trò chơi nhỏ bằng cách sử dụng hai lần trong một ngôn ngữ không có mỹ phẩm con trỏ. Điều đó đã khai sáng cho tôi.

Con trỏ là một vấn đề giải thích. Tôi nghĩ rằng giải thích điều đó làm cho mọi thứ dễ dàng hơn nhiều. Và con trỏ mỹ phẩm là các hoạt động cực kỳ đơn giản và trực quan nếu hiển thị một ví dụ đơn giản với bộ nhớ gồm 10 biến.

2
back2dos

Có lẽ đó chỉ là tôi, nhưng tôi làm việc tốt với các chất tương tự. Vì vậy, giả sử bạn có một người bạn (chức năng/lớp) "Foo", người muốn có người khác (chức năng/lớp khác), "Bar", liên hệ với bạn vì một số lý do. "Foo" có thể đưa bạn đi xem "Bar", nhưng điều đó không thuận tiện, di chuyển tất cả những sinh vật đó (ví dụ) xung quanh. Tuy nhiên, "Foo" có thể gửi "Bar" số điện thoại của bạn (con trỏ). Bằng cách đó, bất kể bạn ở đâu, "Foo" biết cách liên lạc với bạn mà không phải tìm bạn.

Và, giả sử "Bar" có một người quen, "Baz", người cũng muốn liên lạc với bạn. Nhưng bạn bảo vệ số điện thoại của mình và bạn không muốn mọi người có, "Baz" có thể gọi "Bar" (điện thoại là con trỏ), người sau đó có thể chuyển tiếp cuộc gọi cho bạn (một con trỏ khác). Và cứ thế lặp đi lặp lại chuỗi bạn bè của "Baz" và bạn của bạn bè.

2
Hugo

Con trỏ làm cho cách có ý nghĩa hơn nếu bạn đã học ngôn ngữ hội và/hoặc kiến ​​trúc máy tính. Tôi nghĩ rằng nếu tôi dạy một lớp C, tôi sẽ bắt đầu với một vài tuần kiến ​​trúc để giải thích mô hình bộ nhớ và các loại hướng dẫn mà bộ xử lý thực sự thực thi.

2
Barry Brown

"Aha!" Của tôi thời điểm đến trong hướng dẫn này:

Hướng dẫn về Con trỏ và Mảng trong C

Nói chính xác, nó đã đến trong chương này: Chương 3: Con trỏ và Chuỗi

Nói chính xác hơn, nó đi kèm với câu này:

Tham số được truyền cho put () là một con trỏ, là giá trị của một con trỏ (vì tất cả các tham số trong C được truyền theo giá trị) và giá trị của một con trỏ là địa chỉ mà nó trỏ tới, hoặc, đơn giản là một địa chỉ .

Khi tôi đọc điều đó, những đám mây tách ra và những thiên thần thổi kèn.

Đối với, bạn thấy, mọi hướng dẫn hoặc cuốn sách C tôi đã đọc trước đó đã khẳng định rằng C có thể vượt qua giá trị hoặc bằng cách tham chiếu, một lời nói dối bất chính. Sự thật là C luôn vượt qua giá trị, nhưng đôi khi giá trị được chuyển xảy ra là một địa chỉ. Trong phương thức, một bản sao được tạo từ địa chỉ đó, giống như một bản sao sẽ được tạo từ một int được truyền vào. Một bản sao là không được tạo từ giá trị mà con trỏ trỏ tới. Do đó, bằng cách sử dụng con trỏ trong phương thức, bạn có thể truy cập giá trị ban đầu và thay đổi nó.

Tôi chưa bao giờ trở thành lập trình viên C, nhưng tôi đã trở thành lập trình viên .NET và các đối tượng và tham chiếu đối tượng hoạt động theo cùng một cách; tham chiếu đến đối tượng được truyền theo giá trị (và do đó được sao chép), nhưng bản thân đối tượng không được sao chép. Tôi đã làm việc xung quanh nhiều lập trình viên không hiểu điều này bởi vì họ không bao giờ học được con trỏ.

2
Kyralessa

Một con trỏ là một ghi chú dán cho bạn biết nơi nào đó hữu ích. Nó chứa vị trí của sự vật và cho bạn biết nó lớn đến mức nào (bằng C, dù sao đi nữa). Vì vậy, một con trỏ đôi giống như một tờ giấy ghi chú "Có sáu gói trong tủ lạnh". Bạn phải thực sự đi lấy sáu gói để tìm hiểu xem đó là Coke hay Budweiser.

1
philosodad

http: //csl Library.stanford.edu/

Trang web này có các hướng dẫn tuyệt vời để học con trỏ và quản lý bộ nhớ.

Tôi sẽ đề nghị bạn đi qua những điều cơ bản về con trỏ, con trỏ và bộ nhớ được đưa ra trên trang web. Bạn cũng có thể xem xét các vấn đề danh sách được liên kết đưa ra trên liên kết để tăng cường hơn nữa các khái niệm con trỏ.

1
deovrat singh

Cho mã :

int v=42; // khai báo và khởi tạo một biến đơn giản

int *p = &v; // tạo một điểm p cho biến v

Có thể nói sau đây về đoạn mã trên :

int * p // "int con trỏ p" ... đây là cách bạn khai báo một con trỏ tới biến kiểu int

*p // "được trỏ bởi p" ... đó là dữ liệu mà p trỏ đến, giống như v.

&v // "địa chỉ của biến v" ... điều này thể hiện giá trị bằng chữ cho p

1
zener

Chìa khóa để giải thích con trỏ là đảm bảo rằng những người bạn đang giải thích, đã có sự hiểu biết về khái niệm bộ nhớ. Mặc dù thật tuyệt nếu họ thực sự hiểu nó ở mức độ thấp, tin rằng bộ nhớ tồn tại như một mảng lớn và hiểu rằng bạn có thể truy cập bất kỳ vị trí nào trong mảng bởi vị trí chỉ mục của nó là đủ.

Bước tiếp theo, có khái niệm chuyển vị trí chỉ mục thay vì sao chép toàn bộ bộ nhớ có ý nghĩa với hầu hết mọi người. Và điều đó là đủ để cho phép hầu hết mọi người hiểu tại sao con trỏ là hữu ích.

bước cuối cùng để hiểu con trỏ là giải thích làm thế nào bạn có thể truyền vào như một tham số một vị trí chỉ mục bộ nhớ cho phương thức để lưu trữ vị trí chỉ mục cho nơi lưu trữ tất cả dữ liệu. Tôi đã thấy rằng điều này có thể là quá xa đối với một số người để đối phó.

Khi ai đó đã nắm được các bước cơ bản này, họ sẽ hiểu rõ rằng bạn có thể xâu chuỗi con trỏ vô thời hạn, miễn là bạn theo dõi số lần bạn cần xem địa chỉ để tìm đối tượng dữ liệu thực tế.

Khi ai đó đã nắm được các con trỏ, điều tiếp theo mà họ phải nắm bắt nhanh chóng là sự khác biệt giữa bộ nhớ heap và bộ nhớ stack và tại sao các con trỏ để ngăn xếp bộ nhớ lại nguy hiểm khi được truyền ra ngoài phương thức.

1
Michael Shaw

Bí quyết là giải thích rằng vị trí của một vật và bản thân vật đó không giống nhau, giống như hình ảnh của một đường ống không phải là một đường ống . Khi bạn di chuyển một vật, vị trí của nó thay đổi. Vị trí vẫn còn và một số điều khác có thể được đặt ở đó.

1
sal

Giả sử bạn đã hiểu các mảng ít nhất ở mức độ hời hợt, lời giải thích tốt nhất của tôi cho con trỏ sẽ là:

Tưởng tượng tất cả bộ nhớ trong máy tính của bạn (hoặc không gian địa chỉ trong tiến trình của bạn nếu bạn muốn chính xác hơn) như một mảng byte khổng lồ. Một con trỏ chỉ là một chỉ mục vào mảng đó. Con trỏ do đó chỉ là một loại số nguyên đặc biệt.

Tìm hiểu về tất cả các thủ thuật mà các lập trình viên C và hội có thể làm bằng cách coi con trỏ là số nguyên và cách phân biệt hoàn toàn là quy ước ở cấp độ ngôn ngữ hội, đã giúp tôi củng cố sự hiểu biết này.

0
dsimcha

Khi tôi ở trường đại học, giáo sư của tôi có một số slide PowerPoint thực sự gọn gàng mô tả một điểm là một biến riêng biệt với một mũi tên đến một vị trí bộ nhớ (đại diện như một mảng) và khi chúng tôi đang thực hiện Danh sách liên kết, anh ấy sẽ thực hiện bước đó -bước bước, hiển thị khi mũi tên thay đổi, khi con trỏ bị hủy đăng ký, v.v ..., không có cách nào người ta không thể hiểu nó trong vài phút. Bản thân khái niệm này thực sự dễ dàng, nhưng thực hiện đúng hoặc áp dụng nó trong các chương trình thực tế đòi hỏi phải thực hành nhiều hơn.

0
chiurox

Trước khi tôi làm điều đó, tôi giải thích rằng trong lập trình "mọi thứ đều sử dụng bộ nhớ" và phân bổ biến (tĩnh) trong bộ nhớ. Tôi cũng sẽ giải thích địa chỉ bộ nhớ là gì và mối quan hệ giữa không gian bộ nhớ, địa chỉ bộ nhớ và các biến.

Cuối cùng, tôi giải thích rằng có các kiểu dữ liệu và biến số nguyên, kiểu dữ liệu chuỗi và biến ... và cứ thế, cho đến khi giải thích rằng có một kiểu dữ liệu đặc biệt lưu trữ địa chỉ bộ nhớ, có giá trị trống như 0 o "", được gọi là null.

Và cuối cùng, các biến được phân bổ động thông qua việc sử dụng các con trỏ.

0
umlcat

Tôi nhớ một cuốn sách "Câu đố C" hoặc tương tự, mà tôi đọc hoàn toàn bởi vì đó là một trong số ít những cuốn sách liên quan đến lập trình/máy tính có sẵn trong thư viện, sự hiểu biết của tôi về C còn thô sơ. Nó ném một expresison C vào bạn, và yêu cầu khám phá nó, ngày càng phức tạp hơn.

0
peterchen