01/10/2018, 14:33

Ép kiểu con trỏ C/C++

#include <stdio.h>

void main()
{
	int x = 1023;
	int *p = &x;
	printf("%d %d %d %d
", p[0], p[1], p[2], p[3]);

	char *q = (char *)&x;
	printf("%d %d %d %d
", q[0], q[1], q[2], q[3]);
}

Output:

1023 -858993460 7339520 2039742
-1 3 0 0
Press any key to continue . . .

Kết quả hàng dưới giải thích ntn vậy mn.

Dark.Hades viết 16:35 ngày 01/10/2018

Đây là một chương trình lỗi, mình không hiểu sao nó không crash. Có lẽ bạn may mắn nhờ compiler.

Còn dòng dưới đơn giản là nó chuyển int về char. Thằng char này nó đi từ -256 -> 255, vậy nên đối với các số lớn nó sẽ tự scale về tới khi nào trong khoảng giá trị mà char biểu diễn được.

Lí do 2 thằng phía sau nó giá trị 0 là do compiler không cấp bộ nhớ cho thằng này, vậy nên chỉ có thể đọc được giá trị rác của nó ở dạng int, còn khi casting sang char nó không mang gì theo nên tự chuyển về 0.
Nếu là trong C thì nó chính là NULL.

HK boy viết 16:40 ngày 01/10/2018

Nhưng tại sao q[1] lại ra 3 nhỉ?

Dark.Hades viết 16:41 ngày 01/10/2018

Có lẽ đó là do compiler tạo thêm vùng nhớ cho con trỏ p, nhiều compiler cũ hoặc setting tránh seqmentation fault khi truy cập quá 1-2 phần tử app không crash ngay.

Nhìn qua là app này lỗi từ ông xuống cháu rồi, mọi lời giải thích chỉ có hỏi compiler đó, còn code đúng mới giải thích đúng đc

*grab popcorn* viết 16:39 ngày 01/10/2018

Do in tèo xài Little Endian đó OvO
1023 = 0x03FF
Lưu trữ thành 0xFF, 0x03, 0x00, 0x00
(Nếu thuận suy nghĩ là sẽ là 0x00, 0x00, 0x03, 0xFF mới đúng or biểu diễn theo Big Endian)

stackoverflow.com
Marcus

C program to check little vs. big endian

c, byte, endianness
answered by Marcus on 03:05AM - 09 Oct 12
anon45952904 viết 16:40 ngày 01/10/2018

1023 -858993460 7339520 2039742

Gía trị đầu là value tại địa chỉ con trò p chỉ tới.
3 giá trị sau là giá trị rác của các địa chỉ kế theo

[spoiler][quote=“helloworld17, post:1, topic:63181”]
-1 3 0 0
[/quote]
dòng này in ra 4 decimal của địa chỉ, nó là 1 string.

[spoiler]Update: q là 1 chuổi mà
in thế này sẽ ra nó
printf("%p\n", q);
dòng này bạn chỉ cần xem lại kỹ pointer của char, string là sẽ rõ.[/spoiler]

Mình nhầm với const string.

1023 -> 2 bytes
int -> 4 bytes.
char -> 1 byte
=>
q[0] ->0xFF,
q[1] ->0x03,
q[2]->0x00 (cái này compiler cấp để align đủ 4 byte)
q[3]->0x00 (cái này compiler cấp để align đủ 4 byte)

Lâu rồi, mình cũng tranh thủ vớt vát C/C++ phòng ngày quay lại

HK boy viết 16:35 ngày 01/10/2018

Dòng đầu dễ nhìn ra mà. Nhưng thớt đang hỏi dòng sau.

Hello World viết 16:33 ngày 01/10/2018

Mn có thể ns rõ hơn chỗ 0xFF 0x33 0x00 0x00 được k ạ

rogp10 viết 16:40 ngày 01/10/2018

Đầu tiên 1023 (thập phân) = (00) 03 FF (thập lục phân) (vì 256 * 4 = 1024 :v)

Do Intel (x86/x64 nói chung) viết ngược (little-endian) nên byte 0 phải là FF (-1 signed) và byte 1 là 03. 2 byte còn lại sẽ là 00.

Thực ra FF = -1 signed là quá đẹp rồi vì -1 + 1 = 0 ứng với FF + 1 = 00.

anon45952904 viết 16:37 ngày 01/10/2018

Do Intel (x86/x64 nói chung) viết ngược (little-endian) nên byte 0 phải là FF (-1 signed) và byte 1 là 03. 2 byte còn lại sẽ là 00.

Viết ngược hay lưu trữ (nhớ) ngược?

Jacaré Junior viết 16:34 ngày 01/10/2018

Casting từ 4 byte xuống 1 byte là cạn lời luôn rồi, giải thích sao nổi :v

PhamHai viết 16:44 ngày 01/10/2018
  • Cách hiển thị số có dấu ( mã bù 2)
  • Cách máy tính lưu dữ liệu ( litle endian, big endian)
    Là những thứ các bạn cần tìm hiểu lại. Đoạn code trên ko lỗi gì cả, chỉ vi phạm luật strict-aliasing. Cái này thường gặp khi định convert mảng 4 byte thành số float
Bài liên quan
0