C++ Code:
void ht(char dc[]="HANOI",int n=10);
Mình đang đọc cuốn C++ của thầy Phạm Văn Ất tại http://diendan.congdongcviet.com/showthread.php?t=1093(cám ơn thầy đã viết ra một tài liệu rất hay):có một đoạn code mình muốn các bạn cùng thảo luận về đoạn code này xem có vấn đề gì và cách giải quyết để mọi người cùng tránh. Thân.
C++ Code:
#include<iostream.h> #include<conio.h> void ht(char *dc="HANOI",int n=10); void ht(char *dc,int n) { for(int i=1;i<=n;i++) Cout<<"\n\n"<<dc; } void main() { ht(); ht("abc",3); ht("def"); getch(); }
Đã được chỉnh sửa lần cuối bởi meterpreter : 30-09-2011 lúc 05:59 AM. Lý do: chỉnh sửa cho phù hợp. vì nhầm lẫn một chút + xóa bớt getch();clrscr();
C++ Code:
void ht(char dc[]="HANOI",int n=10);
Lỗi này đơn giản thôi. Đây là lỗi khi chuyển đổi từ hằng xâu sang xâuC++ Code:
#include<iostream> #include<conio.h> using namespace std; void ht(const char *dc="HANOI",int n=10); // void ht(const char *dc,int n) // { for(int i=1;i<=n;i++) } int main() { ht(); getch(); //clrscr(); ht("abc",3);getch();//clrscr(); ht("def"); return 0; getch(); }
ps nhỏ: Một số trình biên dịch có thể chấp nhận đc lỗi này
Perfect như vậy có 2 cách khắc phục đó là:
1:
C Code:
char dc[] = "HANOI";
2:
C Code:
const char *dc = "HANOI";
Trong C sẽ không có cảnh báo cho lỗi này, C++ thì có cảnh báo chỉ vì nó phân biệt char * với const char* là hai kiểu dữ liệu phân biệt. Chuẩn C++ không hỗ trợ cho việc chuyển đổi từ một kiểu hằng sang một kiểu không phải là hằng, "HANOI" là một hằng chuỗi vì nó được bao bọc bởi dấu ngoặc kép và kiểu của nó là const char* do vậy nó khác với kiểu char *. Để minh họa mình lấy ví dụ sau.
C Code:
const int y = 8; // y là hằng và không thể bị sửa đổi const int* pY = &y; // bạn không thể sửa đổi y thông qua pY cout << y << endl; // in ra số 8 int* pY2 = (int *)pY; // ép kiểu tường minh pY có kiểu int * *pY2 = 7; // kết quả là undefined cout << y << endl; // giá trị của y in ra là bao nhiêu?
Trên máy của mình chuơng trình vẫn chạy nhưng cả 2 lần in ra y đều có kết quả là 8.
Mặc dù mình thấy cái ví dụ của bạn ko liên quan tới bài viết lắm
Nhưng vẫn muốn hỏi bạn về đoạn code này
Nếu như cout << *pY2 thì k quả = ? Giải thích tại sao lại ko = 8const int y = 8; // y là hằng và không thể bị sửa đổi
const int* pY = &y; // bạn không thể sửa đổi y thông qua pY
cout << y << endl; // in ra số 8
int* pY2 = (int *)pY; // ép kiểu tường minh pY có kiểu int *
*pY2 = 7; // kết quả là undefined
cout << y << endl; // giá trị của y in ra là bao nhiêu?
còn kết quả y = 8 thì bạn cứ in thế nào thì y cũng bằng 8 thôi nên đừng thắc mắc
Mình lướt rất nhiều tô píc trong 4frum, có rất nhiều tranh cãi về vấn đề char s[] hay char *s khác nhau giống nhau thế nào. Code trên mình minh họa cho việc cố tình thay đổi một vùng nhớ đã được khai báo là hằng, sự thay đổi đó dẫn tới hậu quả là vẫn ko thay đổi được nó (trên OS của mình thôi) còn cái gán *pY2 = 7; nó ko được chuẩn C++ định nghĩa do đó kết quả trả về là không đoán trước được (bạn mất quyền kiểm soát kết quả trả về). Tại sao mình lấy ví dụ như vậy để mọi người hiểu rằng const char * và char * là hoàn toàn khác nhau và nếu không may bạn gán một biến chứa dữ liệu kiểu const char * vào biến chứa dữ liệu kiểu char * thì hậu quả là khôn lường(vì rất có khả năng bạn dùng biến kiểu char * để thay đổi biến kiểu const char *). Chỉ thế thôi. Hi vọng điều này giải thích hợp lý cho nụ cười của bạn.
SR lần nữa vì có một sự nhầm lẫn khi tạo nên topic này. Nhưng giờ thì có vẻ cũng ổn.
Đã được chỉnh sửa lần cuối bởi meterpreter : 28-09-2011 lúc 02:17 AM. Lý do: chỉnh sửa cho hợp lý
*pY2 = 7; Mình in ra vẫn thế thôi. Tại sao lại mất quyền kiểm soát ?
Còn cái mình hỏi là cái in ra y ? Đương nhiên = 8. Mình thấy thắc mắc khi bạn đặt dấu ? ở đó
Còn chuyện const char* và char* là hoàn toàn khác nhau đâu có gì để bàn cãi
Đọc thì char * hay const char * đều như nhau cả thôi. Nhưng đến khi ghi thì mới có chuyện. Đây là 1 trường hợp điển hình xảy ra khi biên dịch trên win với trình biên dịch vc.
C Code:
char *s = "HANOI"; s[0] = 'h';
"HANOI" là kiểu const char *. Đoạn code đã cố gắng ép qua char * và gán vào cho s. Hậu quả thì bạn cứ chạy thử sẽ rõ.
Trong mô hình bộ nhớ của đa số các chương trình trong win, bộ nhớ của chương trình được chia ra làm nhiều section. Mỗi section sẽ được phân quyền khác nhau. Có 3 quyền cơ bản là chỉ đọc, đọc/ghi, thực thi. Ở đây chuỗi "HANOI" được đặt trong vùng nhớ có quyền chỉ được đọc. Do đó bạn đọc thông qua biến s thì ko có vấn đề gì. Nhưng nếu bạn ghi thì bạn ko có quyền và chương trình sẽ crash khi cố thực hiện việc đó. Chính vì nguyên nhân này, trình biên dịch phải cảnh báo cho bạn biết khả năng sẽ có lỗi nếu như cố ép từ const char * sang char *. Đây chỉ là cảnh báo, vì nếu bạn ép kiểu nhưng chỉ thực hiện việc đọc nội dung vùng nhớ thì chương trình sẽ vẫn bình an vô sự.
Đã được chỉnh sửa lần cuối bởi meoconlongvang : 28-09-2011 lúc 11:19 AM.
Càng yêu mèo thì mèo càng mập. Mèo càng mập ta lại càng yêu.
const int y = 8;
const int* pY = &y;
int* pY2 = (int *)pY;
Bạn ơi mình đã ép kiểu tường minh cho pY từ kiểu const int * thành kiểu int *, mà khi định nghĩa pY mình đã cho nó nắm địa chỉ của y vì pY ban đầu được khai báo là const int * nên giá trị mà pY nắm giữ (y) không thể bị thay đổi bởi pY. Nếu cố tình thay đổi thì bạn sẽ ko thay đổi được (tức kết quả ngoài sự mong đợi) không chỉ dừng ở đó kết quả là ko thể đoán biết trước, mình nói là hệ thống của mình cho kết quả là 8 nhưng qua hệ thống khác thì ko biết được, nó có thể là 10, 100 etc.
@mèo: hệ thống ko crash bạn àh, tớ vẫn compile và run mà ko bị crash mặc dù tớ cố gắng ghi (thay đổi y) thông qua pY với việc ép kiểu pY.
Đã được chỉnh sửa lần cuối bởi meterpreter : 28-09-2011 lúc 11:26 AM.