2010-05-29 42 views
8

Tôi nghe nói rằng C không an toàn kiểu như vậy và tôi nghĩ rằng tôi có thể sử dụng nó như một lợi thế cho dự án hiện tại của mình.C: Con trỏ tới bất kỳ loại nào?

Tôi đang thiết kế một thông dịch viên với mục tiêu cho máy ảo cực kỳ nhanh, nhanh hơn nhiều so với Ruby và Python chẳng hạn.

Bây giờ tôi biết rằng tối ưu hóa sớm "là gốc rễ của tất cả các điều ác" nhưng đây là một vấn đề khá khái niệm.

  • tôi phải sử dụng một số loại struct để đại diện cho tất cả các giá trị trong ngôn ngữ của tôi (từ số qua chuỗi để liệt kê và bản đồ)

có những điều sau đây có thể?

struct Value { 
ValueType type; 
void* value; 
} 
  • tôi sẽ lưu trữ các giá trị thực tế ở những nơi khác, ví dụ: một mảng riêng biệt cho các chuỗi và số nguyên, giá trị * sau đó sẽ trỏ đến một số thành viên trong bảng này.

  • Tôi luôn biết loại giá trị thông qua biến loại, vì vậy sẽ không có bất kỳ vấn đề nào với lỗi loại.

Bây giờ là:

Đây có phải là thậm chí có thể về cú pháp và gõ?

+0

Tôi cho rằng bạn cũng có kế hoạch viết trình quản lý bộ nhớ của riêng mình? –

Trả lời

7

Có, bạn có thể sử dụng void* để trỏ đến bất kỳ thứ gì và sau đó truyền sang loại thích hợp khi cần (đó là cách malloc và những thứ này có thể hoạt động).

void* về cơ bản là "trỏ tới một khối bộ nhớ tùy ý".

0

Có các mức độ an toàn loại khác nhau, nhưng vì C là một ngôn ngữ được đánh máy mạnh, nó thực sự ở phần cuối của quang phổ an toàn hơn. Điều đó sẽ không ngăn cản bạn làm những gì bạn đề xuất. Ví dụ bạn đưa ra là hợp lệ về cú pháp và có thể được sử dụng để triển khai hệ thống mà bạn mô tả. Tuy nhiên, hãy nhớ rằng nếu bạn tiếp tục và cố gắng phát minh lại bánh xe bằng cách tạo máy ảo của riêng bạn, bạn sẽ không thể đánh bại hiệu suất của các ngôn ngữ hiện có như Ruby và Java.

+0

Java được biên dịch trước bytecode, nó phải nhanh hơn trình thông dịch thời gian chạy theo định nghĩa. Dù sao, "dragme" không nói về Java vì vậy tôi không hiểu tại sao bạn đề cập đến nó? –

+0

Java cũng có một JIT, nhanh hơn so với precteciled bytecode theo định nghĩa :) –

+0

(Ngoài các khía cạnh JIT, mà tôi thừa nhận,) Java bytecode chạy trên máy ảo. Các máy ảo không phải là "theo định nghĩa" nhanh hơn các trình thông dịch thời gian chạy. Trên thực tế, các máy ảo là các trình thông dịch thời gian chạy. – warrenm

7

Nếu bạn biết một loạt các loại bạn muốn hỗ trợ, điều này có thể dễ dàng được thực hiện với một union để tránh phôi khắp nơi:

struct Value 
{ 
    ValueType type; 
    union 
    { 
     int*  iptr; 
     char*  sptr; 
     float*  fptr; 
     struct map* mptr; 

     /* ... */ 

     void* vptr; /* catch all, extensions */ 

    } ptrs; 
}; 
+0

Được cấp, điều này không nhất thiết phải ngắn hơn việc nhập một dàn diễn viên, đặc biệt nếu chuyển đổi diễn ra sớm. – Amber

+0

Tất nhiên nó không cần thiết, nó chỉ cho phép bạn viết một loạt các macro tiện lợi. –

+0

Và ai đó nhìn vào mã có thể thấy các loại giá trị khác nhau hơn là chỉ void *. Sử dụng công đoàn trong một AST/thông dịch viên là một mô hình rất phổ biến. –

2

Chắc chắn nó được. Bạn sẽ chỉ cần một công tắc lớn trên type để phân biệt loại giá trị cụ thể. Loại tốt nhất để sử dụng cho lĩnh vực của bạn type lẽ sẽ là một enum với một hằng số cho mỗi loại ngôn ngữ của bạn, như vậy:

typedef enum type { 
    Integer, 
    String, 
    /* and so on... */ 
} ValueType; 

Cũng nên nhớ bạn đã bỏ con trỏ void* cho một loại cụ thể trước khi sử dụng nó.

0

Không sao để viết mã đó, nhưng có thể bạn đã thiết kế "ngôn ngữ" (ok, thông dịch viên :)) trước những thứ khác.

Btw, tôi khuyên bạn nên đọc object oriented programming in c book. Khi bạn đã hiểu các khái niệm chính, bạn có thể xem xét việc triển khai Python Objects, để bạn có thể nghĩ về cách các phương thức tương tác với các đối tượng và cách chúng được lưu trữ, v.v.

Tạm biệt!

0

Kiểm tra CCAN's type safe callbacks cho các macro giúp bạn tránh các phôi xấu. Tôi biết bạn không viết một callback, nhưng rất nhiều callbacks trông như thế này:

void my_callback(void *context) 

Và một số loại có thể được đúc để (void *) và truyền cho context. Việc đúc trong hàm đó trở nên phức tạp, đặc biệt nếu cuộc gọi lại khởi chạy một chuỗi có một đối số (void *).

Dù sao, bạn có thể tìm thấy một số bit hữu ích nếu bạn theo liên kết.

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