30/09/2018, 18:46
Thắc mắc về lập trình C
#include<stdio.h>
int main()
{
char a = “ab”;
printf("%c", a);
return 0;
}
Em không hiểu tại sao nó lại xảy ra lỗi này.
“Initialization makes integer from pointer without a cast [enabled by default]|.”
Và kết quả in ra màn hình là một kí tự tiền “$”.
Ai giải thích giúp em với
Bài liên quan
bạn đưa vào 1 xâu a rồi khi in lại để là %c tức là 1 ký tụ nên lỗi thôi bạn thử đổi thành %s xem
ab là hai kí tự rồi bạn
cái gì thế kìa ? char a = “ab”? char a = ‘a’ hay char a =‘b’ thôi chứ
Mấy cái này mình biết, Khi khai báo kiểu char bằng string nên nó báo warning.
Nhưng ý mình là :
1 cái warning đó thực sự là gì, tại sao nó lại báo là “integer from pointer”
2, Cái kết quả trả về.
Mình đang nghĩ tới cách mà c quản lý bộ nhớ, nhưng mà không hiểu nó làm thế nào trong trường hợp này. Có khi nào trong trường hợp này c bị sai. Thực sự c đang đọc cái gì.
char
là một số nguyên (integer) 8-bit, nhớ nhésố nguyên
không phải kiểuint
. Khi bạn gánchar a = "ab";
, a là biến thông thường, số nguyên kích thước 8-bit, “ab” là một const string (chuỗi hằng), được lưu trong một vùng nhớ mà chỉ có thể trỏ tới bằng con trỏ (pointer) thôi. Nên nó báo “Việc khởi tạo một số nguyên từ con trỏ không có chuyển kiểu (cast)” error/warning thế là hợp lý rồi mặc dù nó không được rõ ràng làm (Message từ compiler thường rất khó hiểu).return 0
ở hàmmain
?. Trong C, thường quy định/quy ước nếu hàm trả về 0 tức là ‘success’ còn khác 0 là ‘fail’. Hàmmain
trả về 0 tức là nó thông báo cho hệ điều hành là mình đã chạy ‘success’.Em cảm ơn Anh, ý đầu em hiểu rồi.
Giải sử Em vẫn chạy chương trình bỏ qua cảnh báo thì biến a giá trị nó sẽ như thế nào.
Em thực hiện in ra giá trị của nó printf("%c", a); thì em thấy kết quả trả về trên một số hệ điều hành kết quả khác nhau.
VD: - Code block trên windows: trả về “$”
- Trên red hat là “à”
Nó sẽ covert địa chị chứa string “ab” thành một số nguyên rồi gán cho biến
a
(đương nhiên sẽ bị làm tròn vì địa chỉ bộ nhớ thường 32-bit, còn char có 8-bit). Bây giờ biếna
sẽ chứa một số nguyên không rõ ràng (vì phụ thuộc vào địa chỉ lưu của chuỗi “ab” cái mà phụ thuộc vào hệ điều hành, mỗi lần chạy khác nhau).Sau đó bạn sử dụng
%c
để in ký tự, thì hàmprintf
sẽ chuyển số nguyên thành ký tự có mã tương ứng theo bảng ASCII, trường hợp của bạn $ có mã là 36, …Bạn nên nhớ ký tự được biểu diễn bởi một số nguyên tương ứng trong bảng mà ASCII hay unicode.
Bạn tham khảo bảng mà ASCII ở đây (
www.asciitable.com
Anh giải thích chi tiết ghê, nhưng mà Em vẫn khó hiểu quá hixhix.
mỗi lần chạy khác nhau: Em chạy nhiều lần nhưng kết quả vẫn như thế.
Em dùng printf("%d", a) để in ra giá trị số nguyên của nó, kết quả là -16, trong khi đó mã ascii của à là 133 (Em đang dùng trình biên dịch của red hat).
đương nhiên sẽ bị làm tròn Em không hiểu làm tròn là sao. Nó sẽ thêm các bit 0 vào cho đủ 32 bit, hay là theo một quy luật nào đó.
Vì kiểu
char
chỉ là một số 8-bit, với kích thước con trỏ thường 32-bit. Khi gán một số to cho một số nhỏ thì sẽ có phần bị mất đi.Giống như em rót nước từ cái ấm nước đầy (con trỏ 32-bit) vào cái chén trà nhỏ (kiểu char 8-bit) thì chén trà bị đầy thì nước sẽ tràn.
Giả sử địa chỉ của chuối
"ab" = 0x80561231
thì giá trị của biếna = 0x31
thử chạy chương trình này, giá trị của
a
sẽ giống với 2 số cuối củas
Giờ thì Em đã hiểu thuốc Fugacar diệt trừ giun như thế nào rồi.
Em cảm ơn Anh.