Top Ad unit 728 × 90

Latest news

recent

Hàm Sizeof và lưu ý

sizeof là một hàm rất phổ biến trong c và hầu như các ngôn ngữ khác cũng hỗ trợ những hàm tương tự. Nó có nhiệm vụ trả về kích thước tính theo bytes của một kiểu dữ liệu cơ bản, con trỏ, mảng, hay một cấu trúc được định nghĩa bởi lập trình viên.

Thông thường sizeof được sử dụng khi cần tính toán một cách run time kích thước vùng nhớ muốn cấp phát, hay truy xuất một vị trí nào đó trong bộ nhớ và nhiều mục đích rất thông dụng khác. Với các kiểu dữ liệu căn bản, hay mảng thì vấn đề thật rỏ ràng và đơn giản: sizeof(int) = 4 hay sizeof(arrayA) = tổng size của các phần tử trong nó. Tuy nhiên với các cấu trúc tự định nghĩa (struct) thì chúng ta cần phải lưu ý. Hầu hết các trình biên dịch đối xử với các thành phần trong cấu trúc theo wordlength (4 bytes) ví dụ ta có cấu trúc:
struct student{
      char grade;
      int age;
}
Nếu theo lẽ thường thì sizeof(student) = sizeof(char) + sizeof(int) = 5. Tuy nhiên vì trình biên dịch canh các thành phần theo wordlength nên biến age sẽ được gán vào vùng từ nhớ mới thay vì sử dụng 3 byte còn lại của từ nhớ sử dụng bởi grade. Chính vì thế sizeof(student) = 8. Sự mắc mứu này thường gây ra những lỗi memory, hay cấp phát thừa bộ nhớ rất nghiêm trọng. Để thấy vấn đề rỏ hơn tôi sẽ cung cấp thêm một ví dụ:
struct student{
    short grade;
    int age;
    short point;
    int weight;
}
bạn nghĩ mấy sẽ là giá trị của sizeof(student) = ? :) có phải là sizeof(student) = sizeof(short) + sizeof(int) + sizeof(short) + sizeof(int) = 12. Hi hi tui cũng không biết nữa, bạn nên kiểm tra cái này vì nó tùy thuộc vào trình biên dịch của bạn, về phía mình tôi đoán nó có thể là 16. Trong trường hợp đó bạn nghĩ sao khi bạn muốn cấp phát một vùng nhớ cho 200 students bằng hàm sau:
class = (student*)malloc(200 * sizeof(student));
Có vẻ như vấn đề vẫn chưa đến nổi nghiêm trọng, vậy sẽ thế nào nếu không phải là 200 mà là 200000. Khi đó chúng ta sẽ cần giải quyết vấn đề cấp thừa bộ nhớ ở đây. Tôi có thể làm việc đó như thế nào? thay đổi kiểu dữ liệu trong cấu trúc cho thích hợp? vâng đó là một trong những vấn đề đáng xem xét tuy nhiên trong tình hướng ở trên giải pháp thật sự đơn giản. Chỉ cần thay đổi thứ tự khai báo các thành phần như sau:
struct student{
    short grade;
    short point;
    int age;
    int weight;
}
:) tôi thật sự thích thú khi khám phá ra điều này :p nó cho thấy "the best solution is the simplest solution"


Binh Nguyen - Bioz
Hàm Sizeof và lưu ý Reviewed by Bioz on 12:59:00 PM Rating: 5

5 comments:

  1. Nói chung trong C/C++ thì khai báo struct nên theo 2 quy tắc đơn giản sau:
    1. Xếp các thành phần từ nhỏ đến lớn.
    2. Các mảng có kích thước lớn trong struct nên được để cuối cùng.

    Ngoài ra để hạn chế hiện tượng sai khi dùng sizeof như bạn đề cập đến trong bài, thì có thể dùng macro #pragma pack(1). Macro này sẽ force trình biên dịch không thực hiện align cho các struct:

    #pragma pack(1)
    struct student{
    char grade;
    int age;
    }
    #pragma pack()

    sau khi khai báo thế này thì sizeof(student) = 5.

    ReplyDelete
  2. Cảm ơn sự bổ sung của bạn, mong có cơ hội thảo luận thêm.

    ReplyDelete
  3. cái này hay thiệt. Nhưng theo em nghĩ chỉ dùng cho kiểu cấu trúc mình khai báo thôi. giả sử khi mình sử dụng một thư viện của người khác, làm sau mình có thể qui định lại kích thước kiểu cấu trúc của người khác?
    ah, em cũng chưa hiểu lắm nếu thiếu hay trùng vùng nhớ thì mới lo, khi ấy nếu mình dùng malloc() cấp phát thêm có được không? còn khi mà mình cấp phát vùng nhớ dư thì có vấn đề gì?

    ReplyDelete
  4. Đã dùng thư viện thì mình ko thể làm được gì nữa ngòai sử dụng.vùng nhớ ko có cái gọi là cấp phát thêm vì như đã nói mình khó quản lý nơi cấp phát, nó do hệ điều hành làm. Vì vậy thêm ở đây phải hiểu là hủy đi rồi cấp phát lại với kích thước lớn hơn. Khi mình cấp phát dư thì vùng nhớ đó bị block, các chương trình khác không thể sử dụng vùng nhớ đó, dẫn đến lãng phí. Dư chút chút ko sao, chứ nếu chương trình quản lý ko khéo số dư sẽ tích lũy dần, bộ nhớ cứ cấp mà ko giải phóng, dẫn đến sử dụng hết bộ nhớ máy tính -> máy bị treo.

    ReplyDelete
  5. Thanks ban nha,rất có ích với mình :d

    ReplyDelete

chia sẻ cho chúng tôi ý tưởng hay khó khăn của bạn ...

All Rights Reserved by IEEV © 2009 - 2016
Powered By Blogger, Designed by Sweetheme

Contact Form

Name

Email *

Message *

Powered by Blogger.