C là vậy đó cậu do đó người ta thường nói lập trình C là dành cho người lớn hiểu mình đang làm gì: Cậu xin 5 nhưng cậu vẫn có thể sài 8 nhưng hậu quả là do cậu gánh chịu.
tôi vừa gõ thử cái này để kiểm tra cấp phát bộ nhớ cho xâu kí tự
C Code:
#include<stdio.h> #include<conio.h> #include<string.h> #include<stdlib.h> void main() { char *s=NULL; int i; clrscr(); getch(); }![]()
chương trình chỉ cấp phát cho s có 5 byte (hàm malloc)
nhưng khi nhập vào xâu lớn(vd: hello every body), có tới 15 kí tự , nếu tính cả \0 thì là 16, vậy mà s vẫn nhận đầy đủ, lệnh sizeof(s) chỉ trả ra 4 byte
có bác nào có thể giải thích giùm tôi được không
C là vậy đó cậu do đó người ta thường nói lập trình C là dành cho người lớn hiểu mình đang làm gì: Cậu xin 5 nhưng cậu vẫn có thể sài 8 nhưng hậu quả là do cậu gánh chịu.
s được khai báo là 1 pointer, nên sizeof(s) = sizeof(pointer), = 4 trên 32bit, 2 trên 16bit, 8 trên 64bit.
gets với content lớn hơn kích thước cấp cho s sẽ gây lỗi nghiêm trọng, thường là Heap corrupt, và app thường sẽ bị crash.
ô nhớ cấp cho biến động nằm ngay trong bộ nhớ của chương trình, ở trên khi s dùng vượt quá số ô nhớ được cấp phát nó sẽ tràn ra các ô nhớ đằng sau, gấy sai cho các biến khác có ô nhớ cấp phát ngay sau nó. Vấn đề là quái ở chỗ nếu chương trình trên tôi sửa một chút:
char *s=NULL,*s1=NULL;
s=(char *) malloc(5*sizeof(char));
s1=(char *) malloc(10*sizeof(char));
đánh liên tiếp 2 lệnh malloc tôi nghĩ s và s1 sẽ được cấp phát các ô nhớ liền nhau. vậy nếu dùng lệnh
strcpy(s,"hello every body");
strcpy(s1,"oh yes! very good");
hoặc dùng 2 lệnh gets liên tiếp để nhập s, s1 vào
thì đáng lẽ khi in 2 biến này ra, s1 sẽ sai !
thực tế tôi chạy chương trình:
nếu dùng 2 lệnh strcpy() hoặc 2 lệnh gets() thì s, s1 in ra đều đúng !
nếu dùng 1 lệnh strcpy() và 1 lệnh gets() thì chỉ s in sai phần cuối của xâu, s1 in ra vẫn đúng. số kí tự in đúng của xâu s luôn là 10 kí tự(đấy là tôi nhập vào s xâu 20 kí tự)
=> bạn nên kiểm chứng lại điều này (chưa chắc là đúng đâu): in ra 2 con trỏ hoặc in ra hiệu số giá trị của 2 con trỏtôi nghĩ s và s1 sẽ được cấp phát các ô nhớ liền nhau
-thân
Hoàn toàn không có gì chắc chắn và 99,9% sai khi nói s và s1 sẽ được cấp hai vùng nhớ liền kề nhau. Cơ chế cấp phát bộ nhớ của C RTL, Windows, OS cực kỳ phức tạp, cấp phát ra sao thì cũng gần như không thể biết được.
Vd với VC sau nay, cáccác hàm new, malloc đều là wrapper của HeapAlloc, vậy HeapAlloc làm việc ra sao, chúng ta phải RE xuống NtHeapAlloc, NtVirtualAlloc, rồi xuống kernel, thậm chí xuống tới CPU với cơ chế virtual memory để tìm hiểu. Gần như không thể !!!;(
Xin cái gì thì dùng cái đó, đừng thắc mắc hay thử để chết cái đùng.
đồng ýHoàn toàn không có gì chắc chắn và 99,9% sai khi nói s và s1 sẽ được cấp hai vùng nhớ liền kề nhau
trở lại với cái post đầu tiên
vì khai báo là char* s, nên sizeof(s) lúc nào cũng return =4, cho dù bạn có cấp phát đến ngàn vạn byte cũng thế thôi, vì s ở đây là con trỏ và thực chất con trỏ chỉ có 4 byte giống như int, giống như giải thích dưới đây
nếu khai báo char s[1024], thì sizeof(s) sẽ = 1024, nó không phụ thuộc vàoNguyên bản được gửi bởi TQN
gets(s) bạn sẽ nhập vào bao nhiêu kí tự, muốn biết đã nhập bao nhiêu thì phải dùng strlen(s) chứ không phải là sizeof
Bác chỉ được cái nói đúng, khai báo biến kiểu gì thì nó trả về chính xác cấu trúc của kiểu dữ liệu đó vì nó là con trỏ.
Còn hàm gets theo như mình biết thì nó sẽ lấy tất cả các giá trị kể cả giá trị còn nằm trong vùng đệm, cái này cũng chính là điểm khác nhau của scanf và gets.
Liên quan gì đến gets, và scanf nhỉ?
Có Bro nào máy chỉ có nguyên cái DOS OS test thử xem sao?
Đối với Windows cấp cho mỗi chương trình con win32 một vùng nhớ ảo được phân sẵn tới 4GB, một chương trình có thể định địa chỉ thoải mái trong 4GB này, chỉ cần tuân theo các Rules của Windows là được. Điều này đã giảm đi việc ghi đè dữ liệu hay code lên chương trình khác. Nhưng ở win32 các chương trình sẽ không còn nhìn thấy nhau thoải mái như ở win16.
Win32 cũng chỉ còn có một kiểu bộ nhớ là "Flat memory model" (Kiểu bộ nhớ phẳng liên tục tới 4GB, mà không còn các kiểu bộ nhớ như Small, Tiny, Medium,Large, Huge ) và cũng không có kiểu 64KB cho mỗi segment nữa. Điều này cũng làm đơn giản cho lập trình viên nhiều.
Như vậy phần nào đó ở Win32 cũng làm ảnh hưởng tới các hàm cấp phát bộ nhớ???? Chắc là phải tác giả trả lời có lẽ chính xác hơn nhỉ. Có gì sai, mọi người sửa và bổ sung giúp nhé.
Dreaminess đi sinh nhật đây.
Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó.Email: kevin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
Phone: 0972 89 7667
Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp hoặc bị sự thiếu kỷ luật làm tiêu tan sự nghiệp.
việc cấp phát đọng có thể dùng New dược không tôi thường dùng chúng
đê cấp phát
abc345