Làm thế nào để một máy tính phân biệt '\ 0' (ký tự null) với không dấu int = 0?


29

Nếu trong một tình huống nhất định, bạn có một mảng ký tự (tất nhiên là kết thúc bằng ký tự null) và ngay sau đó, ở vị trí tiếp theo ngay trong bộ nhớ, bạn muốn lưu trữ 0dưới dạng int unsign, máy tính sẽ phân biệt như thế nào giữa các ký tự này hai?


18
Bạn đang hỏi về các máy tính điển hình về câu trả lời hoàn toàn đúng. Tuy nhiên, đã từng có một số kiến trúc sử dụng bộ nhớ được gắn thẻ để phân biệt giữa các loại dữ liệu.
grawity

12
Giống như cách máy tính không thể phân biệt float 4 byte với số nguyên 4 byte (lặp lại một số rất khác nhau).
Hagen von Eitzen

6
Mặc dù kết thúc một chuỗi bằng 0x00 là phổ biến, có những ngôn ngữ sử dụng các chuỗi có tiền tố dài. Một hoặc hai byte đầu tiên sẽ chứa số byte trong chuỗi. Theo cách này, 0x00 ở cuối là không cần thiết. Tôi dường như nhớ lại Pascal và BASIC làm điều đó. Có lẽ COBOL là tốt.
sáng

@lit cũng định dạng tiêu đề trong nhiều giao thức truyền thông. "Xin chào tôi là loại tin nhắn này và tôi dài nhiều byte". Thông thường bởi vì bạn cần lưu trữ các loại dữ liệu phức tạp bên trong, sau đó việc chấm dứt null trở nên rắc rối hơn nhiều khi phân tích cú pháp.
mathreadler

1
@lit: Hầu hết các biến thể của Pascal và BASIC đều có, và PL / I và Ada - và trong Java do việc chia sẻ chuỗi con đã bị loại bỏ trong 7u6 sử dụng hiệu quả tiền tố chiều dài mảng - nhưng chỉ loại COBOL: bạn có thể đọc dữ liệu từ pic X occurs m to n depending on v( và số lượng có thể ở bất cứ đâu, không chỉ ngay trước đó), nhưng việc lưu trữ nó phức tạp hơn.
dave_thndry_085

Câu trả lời:


86

Nó không.

Bộ kết thúc chuỗi là một byte chứa tất cả 0 bit.

Số nguyên không dấu là hai hoặc bốn byte (tùy thuộc vào môi trường của bạn) mỗi byte chứa tất cả 0 bit.

Hai mục được lưu trữ tại các địa chỉ khác nhau. Mã được biên dịch của bạn thực hiện các hoạt động phù hợp với các chuỗi trên vị trí cũ và các hoạt động phù hợp với các số nhị phân không dấu ở sau. (Trừ khi bạn có lỗi trong mã của mình hoặc một số mã thông minh nguy hiểm!)

Nhưng tất cả các byte này trông giống với CPU. Dữ liệu trong bộ nhớ (trong hầu hết các kiến ​​trúc tập lệnh phổ biến hiện nay) không có bất kỳ loại nào được liên kết với nó. Đó là một sự trừu tượng chỉ tồn tại trong mã nguồn và có nghĩa là một cái gì đó chỉ dành cho trình biên dịch.

Chỉnh sửa thêm: Như một ví dụ: Hoàn toàn có thể, thậm chí phổ biến, để thực hiện số học trên các byte tạo thành một chuỗi. Nếu bạn có một chuỗi các ký tự ASCII 8 bit, bạn có thể chuyển đổi các chữ cái trong chuỗi giữa chữ hoa và chữ thường bằng cách thêm hoặc trừ 32 (số thập phân). Hoặc nếu bạn đang dịch sang mã ký tự khác, bạn có thể sử dụng các giá trị của chúng làm chỉ mục thành một mảng có các phần tử cung cấp mã hóa bit tương đương trong mã khác.

Đối với CPU, các ký tự thực sự là các số nguyên cực ngắn. (tám bit mỗi bit thay vì 16, 32 hoặc 64.) Đối với con người chúng ta, giá trị của chúng tình cờ được liên kết với các ký tự có thể đọc được, nhưng CPU không biết điều đó. Nó cũng không biết gì về quy ước "C" của "null byte kết thúc một chuỗi", (như nhiều người đã lưu ý trong các câu trả lời và nhận xét khác, có những môi trường lập trình trong đó quy ước đó không được sử dụng) .

Để chắc chắn, có một số hướng dẫn trong x86 / x64 có xu hướng được sử dụng rất nhiều với các chuỗi - ví dụ tiền tố REP - nhưng bạn cũng có thể sử dụng chúng trên một mảng số nguyên, nếu chúng đạt được kết quả mong muốn.


14
Đó là lý do tại sao các nhà phát triển phải cẩn thận với các chuỗi. Nếu bạn có 100 byte liên tiếp, bạn có thể chứa tối đa 99 ký tự 1 byte trong đó cộng với dấu kết thúc ở byte cuối cùng. Nếu bạn viết một chuỗi 100 byte ở đó, chương trình sẽ không thể tìm ra rằng chuỗi kết thúc ở đó và sẽ tiếp tục đọc các byte liên tiếp cho đến khi một byte không trùng hợp. Nếu chuỗi dài hơn 100 byte, nó sẽ ghi đè lên một số dữ liệu liền kề. Các ngôn ngữ lập trình cấp cao (Java, C #, JS, v.v.) tự xử lý vấn đề này, nhưng trong các ngôn ngữ cấp thấp như C, C ++, lắp ráp nó có khả năng đáp ứng.
gronostaj

18
@gronostaj Nhận xét của bạn hơi khó hiểu: Không giống như trong C, chuỗi C ++ cũng tự động xử lý việc này. C ++ thường không được phân loại là ngôn ngữ cấp thấp (và thậm chí C đôi khi không).
Konrad Rudolph

5
Có các kiến ​​trúc CPU (cũ) có các điểm đánh dấu kiểu trên các giá trị dữ liệu, do đó, việc hủy bỏ một số nguyên dưới dạng một con trỏ sẽ đưa ra một ngoại lệ.
Simon Richter

8
@JamieHanrahan Bộ xử lý IA64 có một chút gọi là NaT (hoặc "Không phải là một thứ") có thể ném ngoại lệ nếu một giá trị được đặt.
ErikF

4
@KonradRudolph "tự động" không có nghĩa là "hoàn hảo", chắc chắn không có trong C ++
rackandboneman

5

Nói tóm lại, không có sự khác biệt (ngoại trừ một int có chiều rộng 2 hoặc 4 byte và char chỉ 1).

Vấn đề là tất cả các libaries hiện đại đều sử dụng kỹ thuật terminator null hoặc lưu trữ độ dài của chuỗi. Và trong cả hai trường hợp, chương trình / máy tính đều biết nó đã kết thúc chuỗi khi nó đọc ký tự null hoặc nó đã đọc nhiều ký tự như kích thước cho biết.

Các vấn đề với sự khởi đầu này khi bộ kết thúc null bị thiếu hoặc độ dài bị sai khi chương trình bắt đầu đọc từ bộ nhớ mà nó không được phép.


3
Ồ, có một sự khác biệt trong ngắn - thực ra, ngắn là loại khét tiếng vì là loại dữ liệu phụ thuộc rất máy :)
rackandboneman

2

Không có sự khác biệt. Mã máy (trình biên dịch mã) không có các loại biến, thay vào đó, loại dữ liệu được xác định theo hướng dẫn.

Một ví dụ tốt hơn sẽ là intfloat, nếu bạn có 4 byte trong bộ nhớ, sẽ không có thông tin nào về việc đó là một inthoặc một float(hoặc một cái gì đó hoàn toàn khác), tuy nhiên, có 2 hướng dẫn khác nhau để thêm số nguyên và bổ sung số nguyên, vì vậy nếu bổ sung số nguyên hướng dẫn được sử dụng trên dữ liệu, sau đó là số nguyên và ngược lại.

Tương tự với các chuỗi, nếu bạn có mã, giả sử, nhìn vào một địa chỉ và đếm byte cho đến khi nó đạt đến một \0byte, bạn có thể coi đó là độ dài của chuỗi tính toán của hàm.

Tất nhiên lập trình như thế này sẽ hoàn toàn điên rồ, vì vậy đó là lý do tại sao chúng tôi có các ngôn ngữ cấp cao hơn biên dịch thành mã máy và hầu như không có chương trình nào trong trình biên dịch trực tiếp.


2

Câu trả lời từ khoa học sẽ là: siêu dữ liệu.

Siêu dữ liệu cho máy tính biết liệu một số dữ liệu tại một vị trí nhất định là int, chuỗi, mã chương trình hay bất cứ thứ gì. Siêu dữ liệu này có thể là một phần của Mã chương trình (như Jamie Hanrahan đã đề cập) hoặc nó có thể được lưu trữ rõ ràng ở đâu đó.

Các CPU hiện đại thường có thể phân biệt giữa các vùng bộ nhớ được gán cho mã chương trình và vùng dữ liệu (ví dụ: NX Bit https://en.wikipedia.org/wiki/NX_bit ). Một số phần cứng kỳ lạ cũng có thể phân biệt giữa chuỗi và số, vâng. Nhưng trường hợp thông thường là Phần mềm xử lý vấn đề này, mặc dù siêu dữ liệu ngầm định (trong mã) hoặc siêu dữ liệu rõ ràng (VM hướng đối tượng thường lưu trữ siêu dữ liệu (thông tin loại / lớp) như một phần của dữ liệu (đối tượng)) .

Một lợi thế của việc không phân biệt giữa các loại dữ liệu khác nhau là một số thao tác trở nên rất đơn giản. Hệ thống con I / O không nhất thiết phải biết liệu dữ liệu mà nó chỉ đọc từ hoặc ghi vào đĩa có thực sự là mã chương trình, văn bản hoặc số có thể đọc được của con người hay không. Tất cả chỉ là các bit được vận chuyển qua máy. Hãy để mã chương trình xử lý các vấn đề gõ ưa thích.


0

Nó không. Bạn làm nó!

Hoặc trình biên dịch / phiên dịch của bạn.

Nếu hướng dẫn yêu cầu máy tính thêm số 0dưới dạng, nó sẽ thực hiện. Nếu họ bảo máy tính dừng in dữ liệu sau khi đạt được 0, dưới dạng ' \0'char, nó sẽ làm điều đó.

Ngôn ngữ có cơ chế để đảm bảo làm thế nào để xử lý dữ liệu. Trong các biến C có các kiểu, như int, floatchar, và trình biên dịch tạo ra các hướng dẫn đúng cho từng loại dữ liệu. Nhưng C cho phép bạn truyền dữ liệu từ một biến sang một biến khác có loại khác, thậm chí một con trỏ có thể được sử dụng làm số. Đối với máy tính, tất cả các bit như mọi thứ khác.


0

Một ký tự null là một byte và int không dấu là hai byte.

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.