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

Trần Tuấn An viết 20:57 ngày 30/09/2018

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

17XGOD viết 20:47 ngày 30/09/2018

ab là hai kí tự rồi bạn

Lam Thi viết 20:59 ngày 30/09/2018

cái gì thế kìa ? char a = “ab”? char a = ‘a’ hay char a =‘b’ thôi chứ

Nguyễn Nam Phú viết 20:47 ngày 30/09/2018

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ì.

Pham Van Hai viết 20:57 ngày 30/09/2018
  1. Trong C, kiểu char là một số nguyên (integer) 8-bit, nhớ nhé số nguyên không phải kiểu int. Khi bạn gán char 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).
  2. Kết quả trả về ý bạn lệnh return 0 ở hàm main?. 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àm main trả về 0 tức là nó thông báo cho hệ điều hành là mình đã chạy ‘success’.
Nguyễn Nam Phú viết 20:55 ngày 30/09/2018

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à “à”

Pham Van Hai viết 20:58 ngày 30/09/2018

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ến a 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àm printf 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

Nguyễn Nam Phú viết 20:53 ngày 30/09/2018

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 đó.

Pham Van Hai viết 20:52 ngày 30/09/2018

mỗi lần chạy khác nhau

  • Ý anh là mỗi lần chạy có thể khác nhau, có thể không.

đương nhiên sẽ bị làm tròn

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ến a = 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ủa s

#include<stdio.h>
int main()
{
	char *s = "ab";
	char a = s;
	printf("a = %x\n", a);
	printf("s = %x\n", s);
	return 0;
}
Nguyễn Nam Phú viết 20:48 ngày 30/09/2018

Giờ thì Em đã hiểu thuốc Fugacar diệt trừ giun như thế nào rồi.
Em cảm ơn Anh.

Bài liên quan
0