2010-09-20 26 views

Trả lời

2

đây bạn

int i = 40; // cấp phát bộ nhớ cho số nguyên i và gán giá trị 40 cho nó

char *p = (char*)&i; 

vì vậy đây bạn đang xác định một biến con trỏ và gán cho nó địa chỉ của tôi sau khi đúc nó đến char*

giả sử i được cấp phát tại 1021 address vì vậy p sẽ có địa chỉ đó với giới hạn 1 byte để giữ first 8 bit from the representation of 40;

vì 40 đã được bao phủ trong 8 bit đầu tiên của 2 byte, nó sẽ giữ một tương đương char là 40 nhưng khi bạn đang in nó với %d nó shopuld in 40;

+1

Ngoại trừ việc máy có thể là endian lớn trong trường hợp này, bạn sẽ nhận được 0, – JeremyP

+0

Tại sao cần cast, sự khác biệt giữa 'char * p = (char *) & i' và 'char * p = & i' là gì? –

7
p=(char *)&i;//What actually happens here? 

Địa chỉ phải là i và chuyển đến con trỏ char. Vì vậy, giá trị của *p hiện là byte đầu tiên của i. Giá trị đó là gì, phụ thuộc vào nền tảng.

+4

Rất có thể đó là 0 hoặc 40 (tùy thuộc vào độ tin cậy của máy). –

+0

Tại sao cần cast, sự khác nhau giữa 'char * p = (char *) & i' và 'char * p = & i' là gì? –

1

Điều đó tùy thuộc. Trên Windows, đầu ra sẽ là 40, nhưng điều này chỉ vì nhiều trùng hợp ngẫu nhiên:

Trước hết, printf không (không thể) kiểm tra loại đối số của nó, vì nó thấy% d ở định dạng chuỗi, nó giả định rằng đối số đã cho là một int. Mặc dù * p chỉ là một char, kết quả được đẩy lên một int (như đối với mọi đối số không được xác định trong nguyên mẫu hàm).

Thứ hai, p sẽ trỏ đến bộ nhớ được thực hiện bởi biến i, nhưng vì đó là con trỏ char, nó sẽ chỉ mất một byte từ bộ nhớ của i. Vì Windows/Intel sử dụng quy ước đầu tiên ít nhất là đáng kể, 40 sẽ được lưu dưới dạng mẫu byte "40 0 0 0" vì vậy, vì * p lấy byte đầu tiên (char), kết quả sẽ là 40. Nếu tôi có giá trị 256 hoặc lớn hơn, kết quả sẽ không chính xác.

+0

Xem thêm http://stackoverflow.com/questions/34826036/confused-about-pointer-dereferencing –

5

Hãy bắt đầu bằng cách nhìn vào cách các nội dung của ip sẽ được đặt ra trong bộ nhớ (giả sử đơn đặt hàng lớn về cuối nhỏ):

 
Item    Address    0x00 0x01 0x02 0x03 
----    -------    ---------------------- 
    i    0x08000000   0x00 0x00 0x00 0x28 
    p    0x08000004   0x?? 0x?? 0x?? 0x?? 

Kể từ p đang được khai báo là một biến tự động, nó không được khởi tạo với bất kỳ thứ gì và chứa mẫu bit ngẫu nhiên được biểu thị bởi 0x??.

Trong dòng

p = (char *)&i; 

biểu thức &i đánh giá đến địa chỉ của i, hoặc 0x08000000, và loại của nó là pointer to int, hoặc int *. Dàn diễn viên chuyển đổi loại từ int * thành char * và kết quả được gán cho p.

Sau đây là cách điều trông trong bộ nhớ sau khi chuyển nhượng:

 
Item    Address    0x00 0x01 0x02 0x03 
----    -------    ---------------------- 
    i    0x08000000   0x00 0x00 0x00 0x28 
    p    0x08000004   0x08 0x00 0x00 0x00 

Vì vậy, giá trị của p bây giờ là địa chỉ của i. Trong dòng

printf("%d", *p); 

kiểu của biểu thức *pchar, và giá trị của nó là bất cứ điều gì được lưu trữ trong địa chỉ 0x08000000, mà trong trường hợp đặc biệt này là 0. Kể từ printf là một chức năng variadic, giá trị của *p là được quảng cáo từ loại char để nhập int.

Vì vậy, đối với trường hợp cụ thể này, ouput là "0". Nếu đơn đặt hàng nhỏ gọn, bản đồ sẽ trông giống như

 
Item    Address    0x03 0x02 0x01 0x00 
----    -------    ---------------------- 
    i    0x08000000   0x00 0x00 0x00 0x28 
    p    0x08000004   0x08 0x00 0x00 0x00 

và đầu ra sẽ là "40".

Lưu ý rằng toàn bộ ví dụ này giả định rằng số nguyên và ký tự con trỏ có cùng kích thước và bố cục; điều đó không được đảm bảo là đúng ở mọi nơi (xem phần Online C Standard (n1256 draft), mục 6.2.5, đoạn 27), vì vậy bạn không thể dựa vào việc này ở mọi nơi theo cách bạn mong đợi (giả sử tôi nghĩ rằng intchar không tương thích các loại như được định nghĩa theo tiêu chuẩn, nhưng tôi có thể sai về điều đó). Loại punning nói chung là không an toàn.

+0

Mô tả của bạn giả định rằng các con trỏ 'int *' và 'char *' có cùng kích thước và bố cục, nhưng hành vi hiển thị của chương trình không. Tiêu chuẩn C đảm bảo rằng bất kỳ đối tượng nào cũng có thể được truy cập dưới dạng một mảng các ký tự, do đó mã OP sẽ truy cập vào byte đầu tiên (địa chỉ thấp nhất) của 'i'. Giá trị của byte đó, như những người khác đã chỉ ra, phụ thuộc vào việc thực hiện. –

+0

@KeithThompson Tại sao cast cần thiết, sự khác biệt giữa 'char * p = (char *) & i' và 'char * p = & i' là gì? –

+0

Tại sao cần cast, sự khác nhau giữa 'char * p = (char *) & i' và 'char * p = & i' là gì? –

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