Hỏi về ép kiểu trong con trỏ trong C/C++

#include <stdio.h>
int main() {
	int n = 260;
	int* p = &n; 
	char* pp = (char*) p; 
	*pp = 0;
	printf("n = %d\n", n); 
	return 0;
}

Mấy bác cho e hỏi tại sao chương trình lại ra kết quả là n=256 với ạ!

1 Like

256 => byte cuối là 0 => kết luận :smiley:

4 Likes

E mới học về con trỏ nên chưa hiểu lắm, giải thích rõ hơn giúp e dc ko ạ?

Ví dụ số n=1234, em lấy p là chuỗi trỏ vào n, thì em có thể thấy p lúc này là “1234”, em gán p[0] = 0 thì n sẽ trở thành 0234 hay 234.

Đó là cách người viết, còn máy viết thì khác 1 tí. Thứ nhất hệ cơ số máy tính dùng để biểu diễn số nguyên là hệ 256 thay vì hệ 10. Thứ 2, ở trường hợp này, máy em viết số nhỏ tới lớn, hay phải qua trái, thay vì lớn tới nhỏ/trái qua phải như chúng ta viết. 260 máy viết là (4)(1), vì 4*1 + 1*256 = 260. Sau đó p là chuỗi trỏ tới (4)(1) và xóa 4 đi còn (0)(1), giá trị của nó lúc này sẽ là 256.

Fun fact số chúng ta đang viết là mượn từ Ả rập, mà chữ ả rập viết từ phải qua trái, nên họ viết 1234 thực chất đọc từ phải qua trái là 4321, nhưng khi vay mượn thì mấy ông châu âu viết y hệt 1234 chứ ko viết theo cách đọc 4321 nên bây giờ ta mới viết số lớn trước nhỏ sau “ngược đời” :V

7 Likes
int n = 260; // n = 00 00 00 00 00 00 01 04 H
int* p = &n; // p trỏ tới byte 00 đầu tiên của  n
char* pp = (char*) p;  
// do char chỉ có 1 byte nên pp chỉ tới byte nhỏ nhất của n 
// là byte có giá trị 04 cuối cùng
*pp = 0;
// gán *pp =0 tức là set giá trị trong ô nhớ cuối của n = 0
// lúc này n trở thành n = 00 00 00 00 00 00 01 00 H
*(pp + 2) = 1;
// set giá trị trong ô nhớ gần cuối cách 2 ô nhớ giá trị là 1
// lúc này n trở thành n= 00 00 00 00 00 01 01 00
printf("n = %d\n", n); 

// kết quả 65792

// Kq trên còn phụ thuộc vào Endianness.
3 Likes

Cái này đôi khi nó sẽ liên quan tới kiến trúc biểu diễn số (big endian và little endian) một chút khi converse qua lại, em cũng nên tìm hiểu qua
p/s: ngày xưa đi pv cũng gặp câu này, ko biết kết quả bao nhiêu, tạch, thật đau lòng :sob:

1 Like

Bạn có thể nói rõ giúp mình chỗ "biểu diễn số nguyên là hệ 256 " cho một số có được không? Mình không rõ quy tắc để tách 1 số nguyên ra như vậy. Phần còn lại thì mình đã hiểu.

Dễ lắm, số nguyên đc viết dưới dạng (a0)(a1)(a2)…(an) hệ cơ số b sẽ có giá trị là có a0 * b^0 + a1 * b^1 + a2 * b^2 +… + an * b^n. Trong đó a_i là chữ số của từng hạng, 0 <= a < b, b là cơ số.

Ví dụ 321 hệ cơ số 10 sẽ có giá trị là 3 * 10^0 + 2 * 10^1 + 1* 10^2 = 123.

321 hệ cơ số 256 giá trị = 3 * 256^0 + 2 * 256^1 + 1 * 256^2 = bấm máy tính ra =]

Nếu em thấy lạ vì hệ cơ số khác 10 em chưa xài qua bao giờ thì thật ra em đã xài hệ cơ số 60 từ trước giờ rồi đó =] Em thử chuyển 1 giờ 20 phút 30 giây sang số giây thì đó chính là giá trị của số (30)(20)(1) hệ cơ số 60.

Còn làm sao chuyển số giây thành giờ phút thế kia thì em tự biết cách rồi, với hệ 256 chỉ cần đổi số 60 thành 256 là đc

Cách tổng quát để biểu diễn số n trong hệ cơ số b là:

  • nếu n = 0, ghi ra 0 và kết thúc
  • nếu n khác 0, ghi ra số dư của phép chia n / b, và gán n = n / b, rồi làm tương tự cho đến khi n = 0

Vd 1000 hệ 60
1000 / 60 = 16 dư 40, vậy ghi ra 40 hàng đơn vị, gán n = 16
16 / 60 = 0 dư 16, ghi ra 16 hàng chục, gán n = 0
n = 0, kết thúc.
Vậy 1000 viết là (40)(16) hệ 60. Viết trái qua phải là 16 (phút) 40 (giây)

4 Likes

Cám ơn mọi người nhiều ạ!

anh1
Khi khai báo int n = 260 tức là máy tính cấp phát cho n 4 byte bộ nhớ( 4 ô nhớ mỗi ô nhớ 1 byte). Trình tự ghi dữ liệu vào bộ nhớ như sau:
Đầu tiên, Byte thấp của n sẽ được ghi vào ô nhớ số 1
Tiếp theo, Byte cao của n sẽ được ghi vào ô nhớ số 2
Các ô nhớ còn lại không dùng hết mặc định ghi 0
anh 2

  1. Bạn khai báo con trỏ *pp kiểu char trỏ tới ô nhớ đầu tiên của n thông qua câu lệnh
    char * pp = (char *) p; => lúc này pp trỏ tới ô nhớ đầu tiên của n

  2. lệnh *pp = 0 => làm thay đổi giá trị ô nhớ 1 từ 0000 0100 thành 0000 0000
    anh3

  3. lệnh printf(“n = %d\n”, n); lấy giá trị của n trong bộ nhớ sau đó in ra. Trình tự lấy giá trị từ bộ nhớ ra ngược lại so với lúc ghi vào, byte nào ghi vào sau sẽ được lấy ra trước, ở đây byte cao của n được ghi vào sau nên sẽ được lấy ra trước.
    Do vậy dữ liệu lấy ra sẽ là 0000 0001 0000 0000 = 256

2 Likes

Con trỏ p trỏ tới byte đầu tiên là 04 chứ không phải là 00 đâu bạn

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?