Bạn cần cảnh báo trình biên dịch nghiêm túc hơn.
C không yêu cầu trình biên dịch để từ chối chương trình không hợp lệ, nó chỉ yêu cầu "chẩn đoán" cho vi phạm quy tắc. Chẩn đoán có thể là thông báo lỗi nghiêm trọng hoặc cảnh báo.
Thật không may, nó phổ biến cho các trình biên dịch đưa ra cảnh báo cho các bài tập kiểu con trỏ không tương thích.
void main()
Điều này là sai; nó phải là int main(void)
. Trình biên dịch của bạn có thể cho phép bạn thoát khỏi nó, và nó có thể không gây ra bất kỳ vấn đề có thể nhìn thấy, nhưng không có điểm trong việc không viết nó một cách chính xác. (Nó không phải khá rằng đơn giản, nhưng đó là đủ gần.)
int *p;
float q;
q = 6.6;
Đó là ok.
p = &q;
p
thuộc loại int*
; &q
thuộc loại float*
. Chỉ định một cái khác (không có dàn diễn viên) là một vi phạm ràng buộc . Cách đơn giản nhất để nhìn vào nó là nó đơn giản là bất hợp pháp.
Nếu bạn thực sự muốn làm việc này, bạn có thể sử dụng một dàn diễn viên:
p = (int*)&q; /* legal, but ugly */
nhưng có ít lý do chính đáng để làm như vậy. p
là con trỏ đến int
; nó phải trỏ đến một đối tượng int
trừ khi bạn có rất lý do chính đáng để làm cho nó trỏ đến một thứ khác. Trong một số trường hợp, chính chuyển đổi có thể có hành vi không xác định.
printf("*p = %f \n q = %f, p = %p, &q = %p \n",*p,q,p,&q);
Định dạng %f
đòi hỏi một lập luận double
(một cuộc tranh luận float
được thăng double
trong bối cảnh này nên float
sẽ là ok). Nhưng *p
thuộc loại int
. Gọi số printf
với đối số sai khiến cho hành vi của chương trình của bạn không được xác định.
%p
yêu cầu đối số thuộc loại void*
, không chỉ bất kỳ loại con trỏ nào. Nếu bạn muốn in một giá trị con trỏ, bạn nên bỏ nó để void*
:
printf("&q = %p\n", (void*)&q);
Nó có khả năng để làm việc mà không có dàn diễn viên, nhưng một lần nữa, hành vi này là không xác định.
Nếu bạn nhận được bất kỳ cảnh báo nào khi bạn biên dịch chương trình, thậm chí không bận tâm chạy chương trình đó. Trước tiên hãy sửa các cảnh báo.
Đối với câu hỏi trong tiêu đề của bạn, con trỏ thuộc loại int*
và float*
là các loại khác nhau. An int*
phải trỏ đến đối tượng int
; a float*
phải trỏ đến một đối tượng float
. Trình biên dịch của bạn có thể cho phép bạn trộn chúng, nhưng kết quả của việc làm như vậy hoặc là được thực hiện xác định hoặc không xác định. Ngôn ngữ C, và đặc biệt là nhiều trình biên dịch C, sẽ cho phép bạn loại bỏ rất nhiều thứ không có ý nghĩa nhiều.
Lý do chúng là các loại riêng biệt là (cố gắng) ngăn chặn hoặc ít nhất là phát hiện, lỗi khi sử dụng. Nếu bạn khai báo một đối tượng kiểu int*
, bạn đang nói rằng bạn dự định cho nó trỏ đến một đối tượng int
(nếu nó không phải là một con trỏ rỗng). Lưu trữ địa chỉ của đối tượng float
trong đối tượng int*
của bạn gần như chắc chắn là một sai lầm. Thực thi an toàn loại cho phép các lỗi như vậy được phát hiện càng sớm càng tốt (khi trình biên dịch của bạn in một cảnh báo thay vì khi chương trình của bạn bị treo trong một bản demo cho một khách hàng quan trọng).
Có khả năng (nhưng không được đảm bảo) rằng int*
và float*
có cùng kích thước và có cùng biểu diễn nội bộ. Nhưng nghĩa là đối tượng int*
không phải là "một bộ sưu tập gồm 32 (hoặc 64) bit chứa địa chỉ ảo", nhưng "cái gì trỏ đến đối tượng int
".
Vui lòng hiển thị mã bạn đang sử dụng để có được kết quả đó. –
Nếu tôi đưa bạn đúng, bạn có thể muốn sử dụng một công đoàn ... –
Đó là 'int main (void)', không phải 'void main()'. 'void main()' rất hữu ích cho việc phát hiện các sách được viết bởi các tác giả không biết rõ C. –