Đúc có nghĩa là gì?


18

Khi mã hóa bằng các ngôn ngữ cấp thấp như CI thấy rằng việc truyền đôi khi có nghĩa là 'diễn giải lại các byte này như thể nó luôn thuộc loại khác' và đôi khi là 'chuyển đổi giá trị này một cách thông minh sang loại khác'.

Nghĩa gốc của từ này là gì và có sự nhất quán khi nào cần chuyển đổi và khi nào cần diễn giải lại?


Có gì trong bài viết Wikipedia mà bạn không hiểu? " chuyển đổi kiểu , đánh máyép buộc là những cách khác nhau, hoàn toàn hoặc rõ ràng, thay đổi một thực thể của một loại dữ liệu thành một loại dữ liệu khác ... Mỗi ngôn ngữ lập trình có quy tắc riêng về cách các loại có thể được chuyển đổi ..."
gnat

Ý nghĩa ban đầu của "to cast" không có gì tương đồng với lập trình, xem tại đây merriam-webster.com/dipedia/cast
Doc Brown

1
Rất nhiều (chủ yếu từ góc độ ngôn ngữ được quản lý) trên blog của Eric Lippert trong danh mục nhà điều hành diễn viên
AakashM

1
@gnat: Tôi không chắc đó là một câu hỏi nghiêm túc hay chỉ là một nỗ lực trolling. Nhưng tôi muốn biết làm thế nào để biết trình biên dịch sẽ làm gì: chuyển đổi, đúc hoặc ép buộc? Các quy tắc của ngón tay cái là gì?
Alexander Torstling

1
@DocBrown Tôi nghĩ thuật ngữ casttrong ý nghĩa điện toán tương tự như đúc theo nghĩa luyện kim, theo đó hình dạng của kim loại nóng chảy được cải tổ khi đổ vào khuôn: britannica.com/EBchecked/topic/377665/metallemony/81884/Casting
KChaloux

Câu trả lời:


10

Đúc trong C là duy nhất, khá giống với các ngôn ngữ khác. Nó cũng không bao giờ thông minh.

Đúc trong C chuyển đổi giá trị từ loại này sang loại khác bằng cách sử dụng các quy tắc được xác định cẩn thận. Nếu bạn thực sự cần biết, hãy đọc tiêu chuẩn. Mặt khác, các điểm chính là:

  1. Chuyển đổi giữa các loại số nguyên bảo tồn giá trị, nếu có thể. Nếu đích đến có nhiều bit hơn thì điều này đang mở rộng và thường an toàn, nhưng có thể liên quan đến việc mở rộng dấu hiệu. Nếu hẹp hơn, bit sẽ bị mất.
  2. Chuyển đổi giữa các loại con trỏ bảo tồn giá trị con trỏ, nhưng kết quả thường không được xác định, thường không di động và thường hữu ích cho các tình huống nâng cao.
  3. Chuyển đổi giữa các kiểu số nguyên và con trỏ là OK nếu số nguyên đủ lớn và bảo toàn mẫu bit (bất cứ điều gì có thể xảy ra với ý nghĩa). Nếu số nguyên quá nhỏ, kết quả không xác định nhưng không hữu ích. Như một quy tắc 'dài' đủ rộng cho 'void *', nhưng không có gì đảm bảo! Con trỏ được tạo theo cách này có thể không hợp lệ, trong tất cả các loại cách thú vị.
  4. Chuyển đổi giữa các kiểu float và số nguyên là các chuyển đổi số học như được xác định bởi một thói quen thư viện thích hợp (có cắt bớt, không làm tròn).
  5. Bạn có thể bỏ giá trị trả về của hàm thành void. Tôi không bao giờ có. Nó không làm gì cả.

Một số phôi được áp dụng ngầm và trong một số trình biên dịch sẽ đưa ra cảnh báo. Tốt nhất để lưu ý các cảnh báo!

Định nghĩa từ điển cho diễn viên là tốt nhất bỏ qua, như là không có ích. Nhiều diễn viên được mô tả tốt hơn bằng các điều khoản chuyển đổi hoặc ép buộc, vì vậy cũng đáng để biết những điều đó.

C ++ phức tạp hơn nhiều, nhưng bạn không hỏi điều đó, phải không?


Tôi quan tâm đến các quy tắc của ngón tay cái, và không phải là chi tiết rất nhỏ, nhưng tôi quan tâm đến các ngôn ngữ khác ngoài C nếu điều đó giúp làm sáng tỏ mọi thứ.
Alexander Torstling

2
Những gì tôi đã đưa ra ở đây là chung chung như là hợp lý. Để viết mã C / C ++ chuyên nghiệp, cấp thấp, chi tiết rất nhỏ là rất quan trọng. Hầu hết các ngôn ngữ không có loại vấn đề này trong chuyển đổi loại của chúng. Xin lỗi nếu nó không giải quyết vấn đề của bạn.
david.pfx

Ngoại trừ việc chuyển đổi từ T*sang void*và trở lại luôn được xác định rõ.
Tuyến Miles

@Miles: Trên thực tế, chuyển đổi T * thành bất kỳ U * và ngược lại là bắt buộc để duy trì giá trị con trỏ ban đầu. Trong câu trả lời của tôi, tôi chỉ nói "thường không xác định" để nói ngắn gọn, "vì một số chi tiết rất lộn xộn.
david.pfx

1
@supercat: Xem n1570 S6.3.2.3. Chuyển đổi / vấp vòng giữa T *, U * và void * luôn duy trì giá trị con trỏ chỉ với một ngoại lệ. Nếu bất kỳ T * nào không được căn chỉnh chính xác, đó là hành vi không xác định. Tôi chấp nhận quan điểm của bạn, nhưng chỉ đến mức đó.
david.pfx

2

Phần này của từ điển Webster đưa ra định nghĩa đúng:

a: tạo hình cho (một chất) bằng cách đổ ở dạng lỏng hoặc nhựa vào khuôn và để đông cứng mà không chịu áp lực
b: hình thành theo quy trình này

Vì vậy, trước khi truyền, "đối tượng" của bạn (không phải là đối tượng OOP) theo một hình dạng (loại) nhất định. Khi bạn đúc lại, đó là "đổ bê tông" xung quanh nó để biến nó thành một hình dạng mới, đó là những gì bạn làm với việc đúc. Bạn có một số là số nguyên hình lục giác, và sau khi truyền, bạn sẽ nhận được một chuỗi hình chữ nhật.


2
Ngoài ra : "Để gán một vai trò nhất định cho (một diễn viên)".
Kelly Thomas

Vâng Tôi chắc chắn đây là điều tốt nhất. +1.
david.pfx

2

Có thể hữu ích khi tách các phôi C thành hai nhóm:

  1. Các phôi số - chuyển đổi một số giữa một đại diện này sang một đại diện khác, cố gắng giữ giá trị. Ví dụ - (int)3.1sẽ là 3. Có các quy tắc chính xác xác định điều gì xảy ra khi giá trị chính xác không thể được giữ.

  2. Các con trỏ phôi - Giữ địa chỉ bộ nhớ, nhưng thay đổi cách nó được quy định. Ví dụ, for float x=3.5, *(int *)&xwill give 1080033280- số nguyên này được biểu thị bằng cùng một mẫu bit đại diện cho float 3.5.


Keep the memory address, but change the way it's dereferenced.Hủy bỏ hội nghị một con trỏ trừng phạt loại không được xác định. Tiêu chuẩn chỉ đảm bảo việc truyền từ A *đến B *& trở lại sẽ tạo ra sự giống nhau A *, điều này có thể không hợp lệ đối với sự quy định ở vị trí số 1 - hoặc nếu B *là một char *, nó có thể được sử dụng để đọc biểu diễn đối tượng của bất kỳ loại nào. Đối với tất cả các loại khác, B *con trỏ hội nghị là loại xảo quyệt, UB và vi phạm bí danh nghiêm ngặt. Dù sao, ngay cả khi trình biên dịch không bỏ qua ví dụ 2 ở trên vì lý do đó, bạn đang đưa ra các giả định không thể thực hiện được về các mẫu bit
underscore_d

1
cast (v): to receive form in a mold

Trong C ++, các loại phôi khác nhau có thể được làm rõ ràng hơn, với reinterpret_castý nghĩa "đối xử với các byte này như thể chúng đã là thứ khác". Trong C, bạn có thể làm cho điều đó hoàn toàn rõ ràng bằng cách sử dụng a union, truyền với (type)toán tử sẽ cố gắng giữ kết quả tương đương về số, cho đến khi mất độ chính xác.


2
Trong C con trỏ phôi luôn luôn diễn giải lại và phôi giá trị luôn bảo tồn giá trị tốt nhất có thể. Trong C ++ có nhiều cách để thực hiện cast con trỏ, đó là lý do tại sao có các kiểu cast rõ ràng hơn.
Jan Hudec

Ngữ nghĩa đúc con trỏ C không nhất thiết phải "diễn giải lại". Sẽ là hợp pháp cho một bộ xử lý sử dụng địa chỉ từ nhưng muốn tương tác độc đáo với mã dựa trên byte để có một từ int*đó là một từ char*[với byte thứ hai chọn byte cao hoặc thấp của từ]. Việc tạo một (int*)từ (char*)sẽ yêu cầu thêm một từ bổ sung sẽ là bất kỳ giá trị nào sẽ chỉ định byte đầu tiên của int.
supercat
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.