2010-04-09 25 views

Trả lời

20

Nói chung, bạn không thể. Trong một số trường hợp, nếu có bảo đảm về những gì p trỏ đến, bạn có thể xem nội dung tại và sau địa chỉ đó để tìm hiểu. Nói chung, chức năng của bạn nên biết những gì nó đang được thông qua, trừ khi nó chỉ vượt qua nó cùng.

Đối số dữ liệu và hàm trong C chỉ là một loạt các bit gộp lại với nhau. Trừ khi bạn sử dụng một số bit để cho bạn biết những gì các bit được, không có cách nhất quán để xác định nó.

+6

Bỏ phiếu này ... bạn biết vì bạn đã chắc chắn về các loại trong phần còn lại của chương trình. Nếu điều đó nghe có vẻ mong manh thì đó là vì nó mỏng manh. Chào mừng bạn đến C. Sử dụng một hệ thống ít mong manh, nơi bạn có thể. –

+0

Tôi nhớ một số Motif (của tất cả mọi thứ) mã một lúc trở lại, nơi bạn sẽ nhận được một con trỏ, và bạn sẽ xem xét các byte đầu tiên sau khi con trỏ để xác định loại là gì, và sau đó bạn đối phó với loại đó một cách thích hợp. Thật là một mớ hỗn độn. – WhirlWind

+0

Tôi sẽ không làm điều này trong thực tế. Tôi đã chỉ tò mò về cách mà điều này có thể được thực hiện. Ngoài ra, phần mở rộng GNU C cung cấp toán tử typeof() mà (tôi nghĩ) sẽ có thể xác định loại của những gì bị dereferenced (ví dụ: typeof (* p)), nhưng tôi chưa sử dụng nó. – Yktula

5

Câu trả lời ngắn gọn - bạn không thể.

Trong C không có thông tin thời gian chạy trừ khi bạn cung cấp thông tin, nhưng hãy xem gia đình printf(3) và xem cách dễ dàng chụp chân mình với thông số định dạng không khớp và loại đối số thực tế.

Loại hệ thống là bạn của bạn. Sử dụng nó.

5

Chắc chắn bạn có thể và cũng dễ dàng. Đó là C, làm bất cứ điều gì bạn muốn, làm thế nào bạn muốn nó.

Tạo hệ thống kiểu. Đặt tất cả mọi thứ bạn đi vào một cấu trúc, làm cho byte đầu tiên hoặc hai số ma thuật để xác định cấu trúc chứa vượt quá số ma thuật.

Thực hiện một số chức năng để tạo/nhận/đặt/hủy "biến đã nhập".

Thực hiện một số chức năng khác để thêm và đăng ký loại mới khi chạy.

Tạo một vài định nghĩa để dễ đọc và định kiểu cấu trúc hơn.

Trước khi bạn biết, bạn sẽ có một hệ thống kiểu độc quyền đẹp, bạn có thể sử dụng cho các dự án của bạn, và nó sẽ luôn luôn chính xác những gì bạn muốn và cần bởi vì BẠN đã tạo ra nó.

Bạn có thể phát điên và phát triển nó thành một đối tượng đầy đủ theo định hướng như hệ thống. Hoặc tiết kiệm cho mình công việc và sử dụng công việc của tất cả những người khác đã phát điên - http://en.wikipedia.org/wiki/GObject

+0

Vì vậy, làm thế nào để làm việc này khi chức năng bạn viết được gọi là từ mã bạn không kiểm soát? – WhirlWind

+2

Nếu chức năng đang được gọi từ mã bạn không kiểm soát, thì bạn đang tạo API/Thư viện, vì vậy bạn phải ghi lại giao diện và các chức năng để tạo/nhận/đặt/hủy các biến đã nhập. Nếu vì lý do nào đó, callee là người kiểm soát và họ không muốn/từ chối sử dụng hệ thống 'đã nhập' tùy chỉnh của bạn, sau đó bạn không may mắn. Bạn phải để họ quyết định cách họ sẽ chuyển cho bạn thông tin đã nhập, và viết mã cho điều đó. – Antebellum

1

Tôi đã phải đối mặt với một vấn đề tương tự và tôi thấy mình phải viết một bộ hướng dẫn cho một dự án ngôn ngữ lập trình. Tôi đã đi lên chống lại vấn đề này bởi vì tôi đã có một mảng con trỏ đến chức năng để các chức năng có thể được liệt kê và chạy trong một vòng lặp for (cho những thứ như trợ giúp trực tuyến và cú pháp vv). Ví dụ:

struct List_Str *(*InstructionSet[])(struct List_Str *ContextPrefix,struct List_Str *ContextSuffix)= 
{ 

    AAVF,Add,AddEmotions,AddEmoDebug,AddScope,... 

}; 

Bây giờ bạn có thể dễ dàng làm điều tương tự với char * thay vì struct List_Str * loại, sau đó chuyển đổi tất cả dữ liệu sang định dạng chuỗi sử dụng snprintf và atoi và atof và chức năng chuyển đổi khác. Nếu bạn thực hiện:

man isalpha 

Điều này cho bạn thấy nhiều chức năng trong cách xác định loại dữ liệu được giữ trong chuỗi. Việc xếp tất cả các loại thành định dạng "xâu chuỗi" cho phép tính linh hoạt và đều đặn, nhưng tự động chuyển đổi dữ liệu từ chuỗi thành số nguyên, nổi, vv, là gian truân, nhưng hiệu quả khi thói quen bị phỉ báng.

Nếu bạn dự định giữ dữ liệu nhị phân, thì bạn không thể sử dụng chuỗi, vì 0 ký tự có thể nằm trong dữ liệu nhị phân và điều này làm rối loạn chức năng strlen. Hơn nữa, bạn không có ý tưởng về độ dài của những gì đã được malloc'd một khi nó rời khỏi phạm vi, do đó, lưu trữ độ dài của dữ liệu dereferenced trước khi dữ liệu được đề nghị trong vài byte đầu tiên của char *.

Một điều cuối cùng, tôi sẽ không khuyên bạn nên lưu trữ dữ liệu trong khoảng trống *, quá mơ hồ. Tôi khuyên bạn nên sử dụng char * vì nó là một chút cụ thể hơn, có thể chứa tất cả mọi thứ mà void * có thể và trình biên dịch sẽ cho bạn biết trước nếu bất cứ điều gì trông fishy.

+2

Nếu bạn sử dụng 'char *' làm con trỏ dữ liệu chung, IMHO quá dễ dàng vô tình dereference con trỏ mà không cần chuyển đổi thành kiểu thích hợp. –