Sự khác biệt giữa một biến và một vị trí bộ nhớ là gì? [đóng cửa]


38

Gần đây tôi đã cố gắng giải thích các con trỏ theo một cách trực quan, như flashcards.

Câu 001: Đây là bản vẽ của một vị trí trong bộ nhớ máy tính. Có đúng là địa chỉ của nó là 0x23452? Tại sao?

nhập mô tả hình ảnh ở đây

Trả lời: Có, vì 0x23452mô tả nơi máy tính có thể tìm thấy vị trí này.


Câu 002: Có đúng là ký tự bđược lưu trữ bên trong vị trí bộ nhớ 0x23452không? Tại sao?

nhập mô tả hình ảnh ở đây

Trả lời: Không, bởi vì nhân vật athực sự được lưu trữ bên trong nó.


Câu hỏi 003: Có đúng là một con trỏ được lưu trữ bên trong vị trí bộ nhớ 0x23452? Tại sao?

nhập mô tả hình ảnh ở đây

Trả lời: Có, vì địa chỉ của vị trí bộ nhớ 0x34501được lưu trữ bên trong nó.


Câu hỏi 004: Có đúng là một con trỏ được lưu trữ bên trong vị trí bộ nhớ 0x23452không? Tại sao?

nhập mô tả hình ảnh ở đây

Trả lời: Có, vì địa chỉ của một vị trí bộ nhớ khác được lưu trữ bên trong nó.


Bây giờ là phần khiến tôi lo lắng. Một kỹ sư phần mềm giải thích về con trỏ với tôi như thế này:

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.

Dựa trên bốn thẻ ghi chú tôi đã chỉ cho tất cả các bạn, tôi sẽ xác định các con trỏ theo một cách hơi khác:

Con trỏ là một vị trí bộ nhớ có giá trị là địa chỉ bộ nhớ của một vị trí bộ nhớ khác.

Có an toàn để nói rằng một biến là giống như một vị trí bộ nhớ?

Nếu không thì ai đúng? Sự khác biệt giữa một biến và một vị trí bộ nhớ là gì?


37
Có một giả định ngầm ở đây rằng mọi người đọc những bức ảnh đó sẽ biết ý định của bạn rằng số thập lục phân trong hộp là một địa chỉ bộ nhớ và a, 0x23453. nilvv những thứ bên trong chúng là các giá trị. Điều đó có vẻ rõ ràng đối với bạn, nhưng tôi sẽ không thoải mái đưa ra câu trả lời quyết định cho những câu hỏi đó mà không cần xem các trường đó được định nghĩa như thế nào. Thực sự không có cách nào để biết nếu atrong hình ảnh thứ hai là một ký tự, một chuỗi (nếu chúng khác nhau) hoặc tên của một biến. Nếu nó là một chuỗi, thì đó nilcũng là một chuỗi? Hoặc một giá trị "null"?
ilkkachu

39
Câu hỏi 1 là một câu hỏi tồi. Đó là điều mà bạn cần nói với độc giả trước khi họ có thể trả lời các câu hỏi khác. Thay vì một câu hỏi, nó nên là thông tin được cung cấp cho người đọc: "Trong các câu hỏi sau, các hộp là vị trí bộ nhớ và các số hex bên dưới là địa chỉ của chúng".
17 của 26 tháng

15
Câu hỏi 3 là không thể trả lời cho bối cảnh. Không có cách nào để nói ở mức byte như thế nào giá trị được lưu trữ trong bộ nhớ đang được diễn giải / sử dụng ở cấp ứng dụng.
17 của 26 tháng

6
Đáng lưu ý: mọi thứ bạn viết ở đây đều đúng với C hoặc C ++ nhưng sai về cơ bản bất kỳ ngôn ngữ nào không có tham chiếu / tham chiếu con trỏ rõ ràng. Toàn bộ ẩn dụ của các biến là các vị trí mà các giá trị bị phá vỡ đối với một ngôn ngữ (như Python, hoặc Java, hoặc C #, hoặc Ruby, hoặc nhiều thứ khác) trong đó phép gán chỉ tạo một điểm biến cho một đối tượng mà không sao chép nó và các đột biến đối tượng được hiển thị thông qua tất cả các biến trỏ đến nó. Tài liệu của Python sử dụng phép ẩn dụ thay thế của các biến như các bảng tên treo trên các đối tượng vì lý do này.
Đánh dấu Amery

19
BTW, và tha thứ cho tôi nếu bạn đã hiểu điều này, nhưng có vẻ như đây có thể là một điểm gây nhầm lẫn - ký hiệu "0x23452" này chỉ là một cách để biểu thị một số ở định dạng thập lục phân, và nó chỉ được thực hiện cho thuận tiện. Nhưng đó chỉ là một con số - không có nghĩa là tiền tố 0x biểu thị rằng đó là một con trỏ, những gì được lưu trữ trong bộ nhớ thực sự chỉ là một số vô nghĩa (bạn có thể gắn nhãn các vị trí bộ nhớ bằng số nguyên thập phân đơn giản). Ý nghĩa (nghĩa là cách số nên được giải thích) xuất phát từ ngôn ngữ - loại biến & cách sử dụng.
Filip Milovanović

Câu trả lời:


69

Biến là một cấu trúc logic đi theo mục đích của thuật toán, trong khi vị trí bộ nhớ là cấu trúc vật lý mô tả hoạt động của máy tính. Nói chung, để thực hiện một chương trình, có ánh xạ (trình biên dịch được tạo) giữa khái niệm logic của một biến và lưu trữ của máy tính.

(Ngay cả trong ngôn ngữ lắp ráp, chúng ta có một khái niệm về các biến (logic) sẽ chuyển sang thuật toán và mục đích và các vị trí bộ nhớ (vật lý), mặc dù chúng được tập hợp nhiều hơn trong quá trình lắp ráp.)

Một biến là một khái niệm cấp cao (er). Một biến đại diện cho một ẩn số (như trong toán học, hoặc gán lập trình) hoặc một trình giữ chỗ có thể được thay thế bằng một giá trị (như trong lập trình: tham số).

Một vị trí bộ nhớ là một khái niệm cấp thấp (er). Một vị trí bộ nhớ có thể được sử dụng để lưu trữ một giá trị, đôi khi, để lưu trữ giá trị của một biến. Tuy nhiên, một thanh ghi CPU là một cách khác để lưu trữ giá trị của một số biến. Các thanh ghi CPU cũng là các vị trí lưu trữ ở mức thấp (er), nhưng chúng không phải là các vị trí bộ nhớ vì chúng không có địa chỉ, chỉ có tên.

Theo một nghĩa nào đó, một biến là một cơ chế trừu tượng để thể hiện ý định của chương trình, trong khi vị trí bộ nhớ là một thực thể vật lý của môi trường xử lý cung cấp lưu trữ và truy xuất.

Câu 003: Có đúng là một con trỏ được lưu trữ bên trong vị trí bộ nhớ 0x23452? Tại sao?

Chúng tôi không thể nói chắc chắn. Chỉ vì có một giá trị ở đó sẽ hoạt động như một địa chỉ, không có nghĩa đó là địa chỉ đó, thay vào đó, nó có thể là số nguyên (thập phân) 144466. Chúng ta không thể đưa ra các giả định về việc giải thích các giá trị chỉ dựa trên cách chúng xuất hiện dưới dạng số.

Câu hỏi 004: Có đúng là một con trỏ được lưu trữ bên trong vị trí bộ nhớ 0x23452? Tại sao?

Đây thực sự là một câu hỏi kỳ lạ. Họ mong đợi một số giả định dựa trên các hộp, tuy nhiên, hãy lưu ý rằng các địa chỉ tăng thêm 1 cho mỗi hộp. Trong bất kỳ máy tính hiện đại nào, điều đó có nghĩa là mỗi hộp có thể chứa một địa chỉ byte - byte là tiêu chuẩn trong nhiều thập kỷ nay. Tuy nhiên, một byte chỉ có 8 bit và có thể nằm trong khoảng từ 0 đến 255 (đối với các giá trị không dấu); Tuy nhiên, chúng cho thấy một giá trị lớn hơn nhiều được lưu trữ trong một trong những địa chỉ này, vì vậy rất đáng ngờ. (Điều này có thể hoạt động nếu đây là một máy có địa chỉ từ, nhưng nó không nói lên điều đó, và, ngày nay có rất ít máy móc, mặc dù một số máy giáo dục là như vậy.)

Dựa trên bốn thẻ ghi chú tôi đã chỉ cho tất cả các bạn, tôi sẽ xác định các con trỏ theo một cách hơi khác:

Con trỏ là một vị trí bộ nhớ có giá trị là địa chỉ bộ nhớ của một vị trí bộ nhớ khác.

Trong khi có những tình huống mà suy nghĩ này là chính xác, bạn đang trộn lẫn các ẩn dụ ở đây. Khái niệm về một biến đi đến thuật toán và mục đích của nó - không cần phải giả sử tất cả các biến có vị trí bộ nhớ. Một số biến (đặc biệt là mảng) có vị trí bộ nhớ vì vị trí bộ nhớ hỗ trợ địa chỉ (trong khi các thanh ghi CPU chỉ có thể được đặt tên không được lập chỉ mục).

Để thực thi, có một ánh xạ logic giữa các biến & câu lệnh và vị trí bộ nhớ của bộ xử lý & các chuỗi lệnh của bộ xử lý. Một biến có giá trị không bao giờ thay đổi (ví dụ: hằng số) thậm chí không nhất thiết yêu cầu vị trí bộ nhớ, vì giá trị có thể được sao chép theo ý muốn (ví dụ như cần thiết cho các chuỗi mã do trình biên dịch tạo ra).


4
Và thậm chí byte 8 bit vẫn không phổ biến.
Ded repeatator

14
@JimmyJames Hãy xem xét trường hợp của một forchỉ mục vòng lặp khi trình biên dịch quyết định hủy hoàn toàn vòng lặp. Không ở đâu trong mã đầu ra được sản xuất (có thể là mã lắp ráp hoặc mã máy hoặc mã byte) có vị trí bộ nhớ trong đó bộ đếm vòng lặp được lưu trữ. Nhưng nó vẫn là một biến.
dmckee

4
@JimmyJames, Trong trường hợp con trỏ vòng lặp không được kiểm soát, thì có, nếu mã của bạn thực sự sử dụng giá trị của bộ đếm, thì nó phải được tải ở đâu đó , nhưng (a) nơi đó có thể là một thanh ghi và (b) về nguyên tắc không có lý do tại sao nó phải ở cùng một vị trí trên mỗi lần lặp của vòng lặp không được kiểm soát.
Solomon chậm

3
Nếu vòng lặp đang làm một cái gì đó như sao chép mảng có độ dài cố định sourcethành mảng có độ dài bằng nhau thì destvòng lặp được mã hóa cũng for (int i=0; i<8; ++i) dest[i] = source[i];có thể biên dịch thành một thứ tương đương với sự lặp lại dest++ = source++;số lần xuất hiện. Với bộ đếm vòng lặp, không có bằng chứng nào (thậm chí không có trong thanh ghi) và chỉ có số lần lặp lại cho bạn biết về điều kiện vòng lặp.
dmckee

2
Sự khác biệt bị nhầm lẫn phần nào bởi các ngôn ngữ như C có ngữ nghĩa dựa trên sự trừu tượng của một cỗ máy có bộ nhớ bao gồm các vị trí được đánh số.
Michael Kay

20

Có an toàn để nói rằng một biến là giống như một vị trí bộ nhớ?

Không. Vị trí biến và bộ nhớ là hai trừu tượng ở hai mức trừu tượng khác nhau. Biến và con trỏ là khái niệm cấp cao hơn ở cấp mã / ngôn ngữ, vị trí bộ nhớ là khái niệm cấp thấp hơn ở cấp độ máy. Khi một mã đã được biên dịch thành một tệp thực thi, sẽ không còn bất kỳ biến nào. Cố gắng nói về vị trí bộ nhớ và các biến theo cách này là một lỗi phân loại.

Một biến có thể được thực hiện bằng cách sử dụng bộ nhớ, nhưng không phải lúc nào trình biên dịch cũng có thể tối ưu hóa một phép tính và thực hiện tất cả các phép tính liên quan đến một biến hoàn toàn trong các thanh ghi hoặc nó có thể đặt một biến duy nhất cho nhiều vị trí bộ nhớ hoặc nó có thể sử dụng một bộ nhớ vị trí cho nhiều biến.

Con trỏ là một vị trí bộ nhớ có giá trị là địa chỉ bộ nhớ của một vị trí bộ nhớ khác.

Loạt flashcard này rất bối rối, chúng không chỉ không đúng mà còn không sai.


1
Once a code had been compiled into an executable, there's no longer any variables.Đó là điều mà tôi cho là không đồng ý. Điều đó đúng rằng biến của bạn như bạn biết (nghĩa là tên đó) không còn tồn tại, nhưng cụm từ của bạn dường như gợi ý rằng tệp thực thi được biên dịch chỉ sử dụng địa chỉ bộ nhớ. Điều đó không đúng. Bộ thực thi được biên dịch nhưng không thực thi của bạn không biết bộ nhớ sẽ sử dụng địa chỉ nào khi thực thi. Khái niệm về một biến (tức là một tham chiếu có thể sử dụng lại cho bất kỳ địa chỉ bộ nhớ nào sẽ được gán trong thời gian chạy) vẫn tồn tại bên trong tệp thực thi được biên dịch.
Flater

2
Hoặc trình biên dịch có thể tối ưu hóa biến hoàn toàn đi, theo nhiều cách khác nhau. Điện toán trước một cái gì đó, cắt tỉa các biến không cần thiết. Nếu biến là một hằng số, thì trình biên dịch có thể kết thúc bằng cách sử dụng các lệnh CPU sử dụng các hằng số, và tôi lập luận rằng điều đó không còn được tính là biến ở bất cứ đâu.
kutschkem

16

Biến là cấu trúc ngôn ngữ . Chúng có tên, nằm trong một phạm vi, có thể được tham chiếu bởi các phần khác của mã, v.v ... Chúng là một thực thể logic . Trình biên dịch có thể tự do thực hiện cấu trúc ngôn ngữ này theo bất kỳ cách nào nó làm hài lòng, miễn là hành vi có thể quan sát được được quy định bởi tiêu chuẩn ngôn ngữ. Như vậy, biến thậm chí không cần được lưu trữ ở bất cứ đâu nếu trình biên dịch có thể chứng minh rằng điều đó không cần thiết.

Vị trí bộ nhớ là một khái niệm phần cứng . Chúng biểu thị một vị trí trong bộ nhớ ảo / vật lý. Mỗi vị trí bộ nhớ có chính xác một địa chỉ vật lý và bất kỳ số lượng địa chỉ ảo nào có thể được sử dụng để thao tác. Nhưng luôn có chính xác một byte được lưu trữ tại mỗi vị trí bộ nhớ.

Con trỏ là một loại giá trị đặc biệt . Nói một cái gì đó là một con trỏ giống như nói một cái gì đó là loại double. Nó biểu thị có bao nhiêu bit được sử dụng cho giá trị và cách các bit đó được diễn giải, nhưng điều đó không có nghĩa là giá trị này được lưu trữ trong một biến, cũng không có nghĩa là giá trị này được lưu trữ trong bộ nhớ.


Để đưa ra một ví dụ trong C: Khi tôi có một mảng 2D int foo[6][7];và tôi truy cập một phần tử của nó với foo[1][2], thì đó foolà một biến chứa một mảng. Khi foođược sử dụng trong ngữ cảnh này, nó được biến thành một con trỏ tới phần tử đầu tiên của mảng. Con trỏ này không được lưu trữ trong bất kỳ biến nào, cũng không được lưu trong bộ nhớ, giá trị của nó chỉ được tạo trong một thanh ghi của CPU, được sử dụng và sau đó bị lãng quên. Tương tự, biểu thức foo[1]được biến thành một con trỏ khác trong ngữ cảnh này, một lần nữa, không nằm trong một biến, không được lưu trong bộ nhớ, nhưng được tính trong CPU, được sử dụng và bị lãng quên. Ba khái niệm biến , vị trí bộ nhớcon trỏ thực sự là ba khái niệm khác nhau.


Btw, tôi thực sự có nghĩa là "luôn có chính xác một byte được lưu trữ tại mỗi vị trí bộ nhớ". Đây không phải là trường hợp trong thời kỳ đồ đá của năm mươi năm trước, nhưng nó đúng với hầu hết tất cả các phần cứng được sử dụng ngày nay. Bất cứ khi nào bạn lưu trữ một giá trị trong bộ nhớ lớn hơn một byte, bạn thực sự đang sử dụng một số vị trí bộ nhớ liên tiếp. Tức là (giả sử thứ tự byte cuối lớn), số 0x01234567 được lưu trong bộ nhớ dưới dạng

+------+------+------+------+
| 0x01 | 0x23 | 0x45 | 0x67 |
+------+------+------+------+
    ^      ^      ^      ^
    |      |      |      |
 0x4242 0x4243 0x4244 0x4245

(Các máy endian nhỏ như kiến ​​trúc X86 lưu trữ các byte theo thứ tự ngược lại.) Điều này cũng đúng với các con trỏ: Một con trỏ trên máy 64 bit được lưu trữ trong tám byte liên tiếp, mỗi byte có địa chỉ bộ nhớ riêng. Bạn không thể nhìn vào một ô nhớ và nói: "Ồ, đây là một con trỏ!" Bạn luôn chỉ thấy byte khi bạn nhìn vào bộ nhớ .


Làm thế nào để máy tính biết khi một nhóm các vị trí bộ nhớ liên tiếp bắt đầu và kết thúc?
progner

6
@progner Không. Nó diễn giải các byte trong bộ nhớ theo các hướng dẫn mà nó nhận được. Các hướng dẫn đó cũng được lưu trữ trong không có gì ngoài một chuỗi các byte. Đối với CPU, sự khác biệt duy nhất giữa một byte chứa một lệnh, một byte chứa một ký tự và một byte chứa một số bit dấu phẩy động, là cách nó được hướng dẫn sử dụng byte này. Nếu byte được tìm nạp vì bộ đếm chương trình trỏ tới nó, nó được sử dụng như một lệnh. Nếu nó được tìm nạp bởi vì một lệnh nói tải nó vào một thanh ghi float, thì nó được sử dụng làm dữ liệu dấu phẩy động.
cmaster

7
@progner Đó thực sự là sự đổi mới quan trọng của kiến ​​trúc von-Neuman: Để lưu trữ cả hướng dẫn và dữ liệu trong cùng một bộ nhớ, cho phép các hướng dẫn thay đổi dữ liệu được thực hiện sau đó như nhiều hướng dẫn hơn. Điều này cho phép tự sửa đổi mã, nhưng nó cũng cho phép hạt nhân của hệ thống tải một số chương trình vào bộ nhớ và sau đó báo cho CPU thực hiện chương trình đó. Trước von-Neuman, các máy tính như máy Zuse sẽ nhận được hướng dẫn của chúng thông qua kênh hoàn toàn độc lập với dữ liệu mà chúng vận hành.
cmaster

5

Hãy để tôi tập trung vào câu hỏi thực tế của bạn - "ai đúng?" khi so sánh hai tuyên bố này:

  • 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
  • Con trỏ là một vị trí bộ nhớ có giá trị là địa chỉ bộ nhớ của một vị trí bộ nhớ khác.

Câu trả lời cho điều này là không có . Người đầu tiên nói về "địa chỉ bộ nhớ của một biến khác", nhưng các biến không nhất thiết phải có địa chỉ bộ nhớ, như các câu trả lời khác đã được giải thích. Người thứ hai nói "con trỏ là vị trí bộ nhớ", nhưng con trỏ thực sự chỉ là một con số, có thể được lưu trữ trong một biến, nhưng như trước đây, một biến không nhất thiết phải có địa chỉ bộ nhớ.

Một số ví dụ cho các tuyên bố chính xác hơn:

  • "Con trỏ là số biểu thị địa chỉ bộ nhớ của vị trí bộ nhớ" hoặc

  • "Biến con trỏ là biến có giá trị là địa chỉ bộ nhớ của vị trí bộ nhớ."

  • "Một địa chỉ bộ nhớ có thể giữ một con trỏ biểu thị địa chỉ bộ nhớ của một vị trí bộ nhớ."

Lưu ý đôi khi thuật ngữ "con trỏ" được sử dụng làm lối tắt cho "biến con trỏ", điều này cũng được miễn là nó không dẫn đến nhầm lẫn.


Bạn có thể thay đổi "khác" thành "a" vì một con trỏ có thể trỏ đến chính nó.
Pieter B

@PieterB: nitty, nitty ;-) không chắc điều này có thực sự làm cho nó rõ ràng hơn không, vì tôi chỉ muốn thay đổi từ ngữ ban đầu thành mức độ thực sự cần thiết để làm cho chúng hợp lý. Nhưng than ôi, tôi đã thực hiện chỉnh sửa.
Doc Brown

Công bằng mà nói, nếu bạn hiểu điều đó "nhưng một con trỏ chỉ là một con số" thì cũng không đúng, thực ra một con trỏ là một định danh giới thiệu một số;) Hoặc ít nhất chúng ta phải biết các đặc điểm ngôn ngữ để vào chi tiết.
Zaibis

2
Một con trỏ là một giá trị (số đã quá cụ thể đối với một số triển khai) có khả năng đề cập đến một số đối tượng. Có khả năng cũng có con trỏ null, con trỏ hoang dã và con trỏ lơ lửng, mặc dù một số (hoặc thậm chí tất cả!) Trong số đó có thể bị loại trừ bởi ngôn ngữ được sử dụng.
Ded repeatator

2
@Ded repeatator: bạn nói đúng, nhưng tôi nghĩ mô hình tinh thần của một con trỏ là một con số đủ tốt cho mục đích của câu hỏi này. Vì vậy, hãy giữ mọi thứ đơn giản.
Doc Brown

5

Tôi chắc chắn sẽ không nói rằng một con trỏ là một vị trí bộ nhớ có chứa một địa chỉ. Đối với một người, tôi không biết về một kiến ​​trúc 0x23453có thể vừa với một byte. :) Ngay cả khi bạn xóa bỏ phân biệt byte / từ, bạn vẫn gặp vấn đề là mọi vị trí bộ nhớ đều chứa một địa chỉ. Địa chỉ chỉ là số và nội dung của bộ nhớ chỉ là số.

Tôi nghĩ mẹo ở đây là "con trỏ" mô tả ý định của con người , không phải bất kỳ tính năng cụ thể nào của kiến ​​trúc. Nó tương tự như cách "ký tự" hoặc "chuỗi" không phải là một thứ cụ thể mà bạn có thể thấy trong bộ nhớ - đó cũng chỉ là những con số, nhưng chúng hoạt động như một chuỗi vì đó là cách chúng được xử lý. "Con trỏ" chỉ có nghĩa là một giá trị dự định sẽ được sử dụng làm địa chỉ.

Thành thật mà nói, nếu mục tiêu của bạn là dạy một ngôn ngữ cụ thể (Mục tiêu C?), Tôi không chắc việc rút ra băng nhớ cổ điển thậm chí còn hữu ích. Bạn đã nói dối trắng bằng cách hiển thị các giá trị được nhập và giá trị quá lớn cho một byte. Ngữ nghĩa dạy, chứ không phải cơ khí - cái nhìn sâu sắc quan trọng về con trỏ là họ cung cấp gián tiếp , mà là một công cụ hữu ích để hiểu ồ ạt.

Tôi nghĩ rằng một so sánh tốt có thể là một URL, cho bạn biết nơi tìm một số dữ liệu, nhưng bản thân nó không phải là dữ liệu. Hãy nghe tôi nói:

  • Bạn hiếm khi quan tâm URL thực sự là gì ; phần lớn trong số họ bị vắt kiệt trong các liên kết với tên. Rất nhiều người sử dụng internet mà không biết chính xác làm thế nào một URL dẫn đến một trang; một số người không biết gì về URL hoàn toàn.

  • Không phải mọi chuỗi là một URL, hoặc dự định sẽ được sử dụng làm URL.

  • Nếu bạn cố truy cập URL không có thật hoặc một trang đã từng tồn tại nhưng đã bị xóa, bạn sẽ gặp lỗi.

  • Một URL có thể trỏ đến một hình ảnh, một số văn bản, một số nhạc hoặc bất kỳ số lượng các mục riêng lẻ nào khác - hoặc nó có thể trỏ đến một trang có nhiều thứ chứa trong đó. Rất phổ biến khi có cả đống trang có bố cục tương tự nhưng dữ liệu khác nhau.

  • Nếu bạn tạo một trang web và bạn muốn tham khảo dữ liệu trên một số trang web khác, bạn không cần phải sao chép và dán tất cả vào đó; bạn chỉ có thể tạo một liên kết đến nó.

  • Bất kỳ số lượng các trang khác có thể liên kết đến cùng một URL.

  • Nếu bạn có một tập hợp các trang tương tự, bạn có thể tạo một trang chỉ mục liệt kê các liên kết đến tất cả chúng hoặc bạn có thể có một liên kết "tiếp theo" ở cuối trang 1 đưa bạn đến trang 2, v.v. Những ưu điểm và nhược điểm của cả hai phương pháp đều rõ ràng ngay lập tức, đặc biệt nếu bạn xem xét những gì quản trị trang web cần làm để thêm hoặc xóa các trang ở nhiều nơi khác nhau.

Sự tương tự này cho thấy rất rõ con trỏ dùng để làm gì , điều rất quan trọng để hiểu chúng - nếu không chúng chỉ có vẻ độc đoán, phức tạp và vô nghĩa. Hiểu cách thức một cái gì đó hoạt động dễ dàng hơn nhiều nếu bạn đã hiểu những gì nó làm và tại sao nó hữu ích. Nếu bạn đã nội tâm hóa rằng một con trỏ là một hộp đen cho bạn biết nơi nào khác, và sau đó bạn tìm hiểu về sự phức tạp của mô hình bộ nhớ, thì việc biểu thị con trỏ là địa chỉ là khá rõ ràng. Thêm vào đó, ngữ nghĩa giảng dạy sẽ đưa sinh viên của bạn đến một nơi tốt hơn để hiểu và phát minh ra các hình thức khác của sự quyết định - điều này tốt khi hầu hết các ngôn ngữ chính không có con trỏ nào cả!


every memory location contains an address- Mỗi vị trí bộ nhớ một địa chỉ. Nó không được chứa ở bất cứ đâu, ngoại trừ có thể trong một biến con trỏ.
Robert Harvey

@RobertHarvey mỗi vị trí bộ nhớ (ít nhất là từ) có chứa một số, có thể được hiểu một cách tầm thường một địa chỉ. vấn đề là không có gì trong phần cứng thực sự phân biệt địa chỉ với địa chỉ không phải địa chỉ
Eevee

2

Tôi biết bạn đã chấp nhận một câu trả lời và câu hỏi này đã có năm câu trả lời rồi, nhưng có một điểm họ không đề cập đến, một câu mà tôi nghĩ đã làm bạn vấp ngã. Sách giáo khoa CS thường cố gắng không biết gì về sự lựa chọn ngôn ngữ lập trình, điều này dẫn đến giả định ngầm định rằng thuật ngữ được sử dụng để mô tả mọi thứ là phổ biến. Không phải vậy.

Trong C, toán tử ampersand đơn nguyên được gọi là toán tử "address-of". Các lập trình viên C sẽ không ngần ngại nói rằng biểu thức &xước lượng đến địa chỉ của biến x. Tất nhiên, chúng có nghĩa là "địa chỉ bộ nhớ trong đó giá trị của biến x được lưu trữ" nhưng không ai là người phạm tội trong cuộc trò chuyện thông thường. Trong C, từ "con trỏ" thường dùng để chỉ loại dữ liệu của một biến dự định có địa chỉ bộ nhớ làm giá trị của nó. Hoặc tương đương kiểu dữ liệu của giá trị. Nhưng một số người sẽ sử dụng "con trỏ" làm giá trị.

Trong Java, tất cả các biến của đối tượng hoặc kiểu mảng hoạt động rất giống con trỏ C (ngoại trừ số học con trỏ), nhưng các lập trình viên Java gọi chúng là tham chiếu, không phải con trỏ.

C ++ coi các tài liệu tham khảo và con trỏ là các khái niệm khác nhau. Chúng có liên quan, nhưng không hoàn toàn giống nhau, vì vậy các lập trình viên C ++ phải tạo ra sự khác biệt trong cuộc trò chuyện. Dấu và được đọc là "địa chỉ của" trong một số ngữ cảnh và "tham chiếu đến" trong các ngữ cảnh khác.

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.

Đó là cách một lập trình viên C có thể mô tả nó, sử dụng "một con trỏ" theo nghĩa tương tự như "một int." (Như trong, "một con trỏ giữ một địa chỉ bộ nhớ trong khi một int giữ một số nguyên trong một phạm vi nhất định.")

Con trỏ là một vị trí bộ nhớ có giá trị là địa chỉ bộ nhớ của một vị trí bộ nhớ khác.

Đó là một cách kỳ lạ để nói, bởi vì nó đòi hỏi một định nghĩa rất lỏng lẻo và không chính thức về "là".

Có an toàn để nói rằng một biến là giống như một vị trí bộ nhớ?

Sẽ rõ ràng hơn khi nói một địa chỉ bộ nhớ là vị trí trong bộ nhớ nơi lưu trữ giá trị của một biến. (Cấp, không phải tất cả các biến được lưu trữ trong bộ nhớ, do tối ưu hóa trình biên dịch, nhưng bất kỳ biến nào có địa chỉ được lấy &xsẽ có.)


Như chúng ta đang là pedantic: Địa chỉ mà tại đó một cái gì đó được lưu trữ. Ngoài một địa chỉ không thể lưu trữ bất cứ thứ gì, thường thì mọi thứ được lưu trữ ở nhiều vị trí liền kề, chỉ có một địa chỉ (thường được chọn theo quy tắc nhất quán) được sử dụng (và chỉ sử dụng một trong nhiều địa chỉ có khả năng).
Ded repeatator

@Ded repeatator Tôi cho một người không cố gắng trở thành nhà mô phạm.
gatkin

Tiêu chuẩn C thậm chí còn phân biệt, chính thức, giữa các biến phải tuân thủ nghiêm ngặt các bước của máy trừu tượng tại mỗi điểm chuỗi thứ tự Điên vì mục đích an toàn của luồng và một số thao tác cấp thấp trên phần cứng được ánh xạ bộ nhớ và những biến không được ' t, miễn phí để được chuyển vào một đăng ký hoặc tối ưu hóa hoàn toàn.
Davislor

@Davislor: Tiêu chuẩn C sử dụng thuật ngữ "đối tượng" ở những nơi mà các đặc tả ngôn ngữ khác sử dụng "biến", cũng như để mô tả những thứ khác không có biến. Một số cuộc thảo luận có thể sử dụng thuật ngữ "biến" không biết ngôn ngữ, nhưng vì bất kỳ lý do gì, Tiêu chuẩn thiếu một thuật ngữ để phân biệt giữa các phân bổ (biến) được đặt tên từ các loại đối tượng khác như phân bổ lồng nhau (cấu trúc / thành viên liên kết) hoặc các đối tượng không tên bởi con trỏ hội nghị. Một cách không chính thức, "biến" là một thuật ngữ tuyệt vời, nhưng Tiêu chuẩn không sử dụng nó.
supercat

@supercat Điều đó không đúng. Việc sử dụng tiêu chuẩn C11 thuật ngữ “biến” hơn một trăm lần, trong đó có vài chục được danh từ, ví dụ, “truy cập đồng thời vào biến được khởi tạo, thậm chí thông qua một hoạt động nguyên tử, tạo thành một cuộc chạy đua dữ liệu.”
Davislor

1

Câu lệnh 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 được quá mức. Nhưng vào lúc người đọc hiểu chính xác vị trí bộ nhớ là gì và nó khác với biến như thế nào, họ sẽ hiểu chính xác con trỏ là gì và do đó không cần phải dựa vào lời giải thích không chính xác này.

Câu lệnh Một con trỏ là một vị trí bộ nhớ có giá trị là địa chỉ bộ nhớ của một vị trí bộ nhớ khác là sai. Giá trị của một con trỏ không cần phải được lưu trữ trong một vị trí bộ nhớ và sẽ gây tranh cãi nếu một con trỏ cần trỏ đến một vị trí bộ nhớ, tùy thuộc vào định nghĩa dự định của "bộ nhớ".

Sự khác biệt giữa một biến và một vị trí bộ nhớ

Một vị trí bộ nhớ là một trong nhiều nơi có thể lưu trữ dữ liệu. Dữ liệu đó có thể là một biến hoặc một phần của biến. Biến là một cách ghi nhãn dữ liệu.


0

Câu trả lời này tập trung vào C và C ++; điều đó có vẻ phù hợp vì câu hỏi của bạn liên quan đến các con trỏ là một phần không thể thiếu của C / C ++ so với các ngôn ngữ khác. Hầu hết bài đăng này sẽ áp dụng cho hầu hết các ngôn ngữ được biên dịch mà không có thời gian chạy phức tạp (như Pascal hoặc Ada, nhưng không giống như Java hoặc C #).

Các câu trả lời tốt đã được đưa ra nhấn mạnh rằng một biến là một ngôn ngữ được xây dựng ở mức độ trừu tượng hơn so với bộ nhớ vật lý. Tôi muốn nhấn mạnh mặc dù sự trừu tượng này có một lý do và hệ thống nhất định với nó:

Sự trừu tượng chủ yếu bao gồm việc sử dụng tên thay vì địa chỉ bằng chữ.

Ý tưởng nguyên tắc là một biến là một tay cầm có tên cho một đối tượng được gõ; các đối tượng trong C / C ++ thường nằm trong bộ nhớ. Các ngôn ngữ sau đó thêm một số chi tiết liên quan đến quản lý trọn đời và sắp xếp dữ liệu cho chuyển đổi loại. Khái niệm về các biến trừu tượng hơn các địa chỉ vật lý vì chúng ta thực sự không quan tâm đến giá trị số của các địa chỉ hoặc vị trí chính xác của các hàm trong bộ nhớ. Chúng tôi chỉ cần đặt tên cho chúng và sau đó giải quyết chúng theo tên, và trình biên dịch, trình liên kết và hệ thống thời gian chạy sẽ chăm sóc các chi tiết nghiệt ngã.

Và đừng giả vờ rằng C / C ++ là bất khả tri về bộ nhớ: Rốt cuộc, có toán tử địa chỉ áp dụng chung. Đúng, đúng, bạn không thể lấy địa chỉ của biến C trong lớp lưu trữ đăng ký; Nhưng lần cuối bạn sử dụng nó là khi nào? Đó là một ngoại lệ đặc biệt đối với khái niệm chung, không phải là sự bác bỏ đối số. Ngược lại, quy tắc chung là việc lấy địa chỉ của một biến thực sự buộc trình biên dịch thực sự tạo ra một đối tượng trong bộ nhớ, ngay cả khi nó không làm như vậy (ví dụ với các hằng số). Khái niệm "xử lý có tên" cũng là một mô hình tốt cho các tham chiếu C ++: Tham chiếu chỉ là một tên khác cho cùng một đối tượng.

Khi tôi viết trình biên dịch nội tuyến với giá 68 nghìn, thật tuyệt khi thấy cách bạn có thể sử dụng tên biến làm điểm bù cho các thanh ghi địa chỉ (và bạn có thể sử dụng tên của các biến được khai báo registerthay vì tên thanh ghi kim loại trần!). Đối với trình biên dịch, một biến là một địa chỉ bù không đổi. Để nhắc lại: Các biến được đặt tên là các thẻ điều khiển, thường dành cho các đối tượng trong bộ nhớ.


Con trỏ là một phần rất cơ bản của C #, Java, JS và các ngôn ngữ khác. Gọi họ khác nhau không thay đổi điều đó, mặc dù đó là PR tốt.
Ded repeatator

@Ded repeatator :-) Good ol 'Tony ...
Peter - Tái lập lại

0

Nghe có vẻ như câu hỏi nhắm vào một ngôn ngữ phổ biến được hình thành bằng cách tăng Tiêu chuẩn C với bảo đảm bổ sung "Trong trường hợp một số phần của Tiêu chuẩn hoặc tài liệu triển khai mô tả hành vi của một số hành động và một số phần khác phân loại nó là không xác định , phần trước chiếm ưu thế. ", cũng như định nghĩa về" biến "phù hợp với cách sử dụng thuật ngữ của các ngôn ngữ khác.

Trong ngôn ngữ đó, mỗi vị trí bộ nhớ có thể được xem như một hộp thư được đánh số luôn chứa một số (thường là tám) bit, mỗi bit có thể độc lập bằng 0 hoặc một. Các vị trí bộ nhớ thường được sắp xếp theo hàng hai, bốn hoặc tám. và một số thao tác xử lý trên nhiều vị trí bộ nhớ liên tiếp cùng một lúc. Tùy thuộc vào máy, một số thao tác hoạt động trên các nhóm gồm hai, bốn hoặc tám vị trí bộ nhớ có thể bị giới hạn hoạt động trên các vị trí trong một hàng. Hơn nữa, trong khi một số máy có thể có một phòng hộp thư được đánh số liên tiếp, thì một số máy khác có thể có nhiều nhóm hộp thư được đánh số khác nhau.

Một biến xác định một phạm vi các vị trí bộ nhớ được liên kết riêng với nó và một loại mà các vị trí bộ nhớ đó sẽ được diễn giải. Đọc một biến sẽ làm cho các bit trong các vị trí lưu trữ được liên kết của nó được hiểu theo cách phù hợp với loại của biến và việc viết một biến sẽ khiến các bit liên quan được đặt theo cách phù hợp với loại và giá trị của nó.

Một địa chỉ gói gọn bất cứ thông tin nào là cần thiết để xác định hộp thư. Điều này có thể được lưu trữ dưới dạng một số đơn giản, hoặc như một loại chỉ định nhóm cùng với số lượng hộp thư trong nhóm đó.

Áp dụng &toán tử cho một biến sẽ mang lại một con trỏ đóng gói địa chỉ và gõ chúng. Áp dụng unary *hoặc []toán tử cho một con trỏ sẽ làm cho các bit của hộp thư bắt đầu tại địa chỉ được đóng gói được diễn giải hoặc được đặt theo cách phù hợp với loại được đóng gói.


Có vẻ như bạn đang lật lại câu hỏi.
Robert Harvey

0

Tôi đến muộn bữa tiệc này nhưng tôi không thể cưỡng lại việc đưa 2 xu của mình vào.

Tại những thời điểm này, sự khác biệt giữa các giá trị được lưu trữ trong các vị trí bộ nhớ này là gì?

Lần 1

nhập mô tả hình ảnh ở đây

Lần 2

nhập mô tả hình ảnh ở đây

Câu trả lời đúng: không có gì. Chúng là tất cả các giá trị giống hệt nhau được trình bày với các cách hiểu khác nhau về ý nghĩa của chúng.

Làm thế nào để tôi biết điều đó? Bởi vì tôi là người đã tạo nên điều này. Bạn chưa thực sự biết điều đó.

Bạn đang gặp phải điều gì đó mà tôi gọi là vấn đề ngoài ban nhạc . Làm thế nào để giải thích chính xác ý nghĩa của các giá trị này không được lưu trữ ở đây. Kiến thức đó được lưu trữ ở nơi khác. Tuy nhiên, khi bạn trình bày những giá trị này trên giấy, bạn đưa vào giải thích đó. Điều đó có nghĩa là bạn đã thêm thông tin đơn giản là không tồn tại ở những vị trí bộ nhớ này.

Ví dụ: các giá trị ở đây là giống hệt nhau, nhưng bạn chỉ biết điều đó là đúng nếu bạn đúng khi bạn giả sử mã hóa ký tự ASCII / UTF-8 là cách tôi nhận được ký tự đầu tiên, thay vì nói EBCDIC . Và bạn cũng phải giả sử rằng cái thứ hai là biểu thức thập lục phân của các giá trị số được lưu trữ tại các vị trí bộ nhớ đó, tất cả có thể là con trỏ tới các địa chỉ khác, thay vì nói các tham chiếu đến các chuỗi bắt đầu bằng "0x". : P

Không có gì được lưu trữ trong các vị trí bộ nhớ này cho bạn biết bất kỳ giả định nào là đúng. Thông tin đó có thể được lưu trữ. Nhưng nó sẽ được lưu trữ ở nơi khác.

Đây là vấn đề trình bày . Bạn không thể thể hiện bất kỳ số nào mà không đồng ý trước về cách trình bày nó. Bạn có thể dựa vào các giả định, quy ước và bối cảnh nhưng nếu bạn nghiên cứu sâu về nó, khi bài thuyết trình không được xác định rõ ràng, câu trả lời thực sự chính xác duy nhất là "không đủ thông tin".


Thậm chí còn vui hơn khi cùng một bộ nhớ được sử dụng cho những thứ không đổi khác nhau cùng một lúc.
Ded repeatator

@Ded repeatator Đúng. Điều đó luôn khiến tôi nghĩ về dàn diễn viên tái diễn của c ++ . Cùng một bit nhìn thấy một cách khác nhau.
candied_orange

@Ded repeatator hoặc, hãy nghĩ về nó, liên minh trong c
candied_orange
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.