Exercise 15 Lập Trình C – Learn C The Hard Way – Phần 2


Exercise 15: Pointers Dreaded Pointers

Đã lâu rồi mình không ra bài mới, dạo này bận quá. Bài hôm nay mình sẽ tiếp tục bài hôm trước là bài con trỏ.
Bài này sẽ giải thích cặn kẽ về con trỏ theo đúng như lời của tác giả Learn C The Hard Way.

Bài trước đây nhé: Exercise 15: Pointers Dreaded Pointers phần 1
Bài viết đọc thêm: Con trỏ từ cơ bản tới nâng cao phần 1Con trỏ từ cơ bản tới nâng cao phần 2.

Explaining Pointers

Khi bạn gõ ages[i], thì i chính là “index” hay còn gọi là chỉ số của mảng ages. Bạn gõ ages[0] nghĩa là bạn lấy phần tử thứ 0 trong mảng (Trong C, phần tử đầu tiên là phần tử thứ 0). Và đó cũng là cách để chúng ta truy xuất phần tử ở trong mảng, cái này rất đơn giản phải không nào.
Quan trọng! Khi chúng ta khai báo mảng int ages[] như vậy thì máy tính sẽ làm làm và hiểu những thứ sau đây:
1. Máy tính sẽ tạo một vùng nhớ (block of memory) để chứ dữ liệu kiểu int.
2. ages sẽ chứa địa chỉ đầu tiên của vùng nhớ này. Các bạn thử test đoạn chương trình sau để kiểm chứng ý này:

#include <stdio.h>

int main()
{
    int ages[] = {23, 43, 12, 89, 2};
    printf("%d", ages);
    return 0;
}

Cái số bạn nhìn thấy trên màn hình là địa chỉ đó.
3. Địa chỉ của phần tử tiếp theo trong mảng là bao nhiêu? Bạn chỉ cần lấy ages + i (với i là chỉ số của mảng). Kiểm chứng bằng đoạn code sau đây:

#include <stdio.h>

int main()
{
    int ages[] = {23, 43, 12, 89, 2};
    printf("%d\n", ages);
    printf("%d", ages + 1);
    return 0;
}

Bạn sẽ thấy 2 kết quả in ra cách nhau 4 đơn vị. Vì sao lại vậy. Trong kiến trúc CPU máy tính (32 hoặc 64 bit) thì kiểu int trong C sẽ là 4 byte. Và mảng trên được khai báo kiểu int, vậy thì mỗi phần tử trong mảng sẽ được cấp 4 byte bộ nhớ. Và điều này giải thích vì sao kết quả trên lại lệch nhau 4 byte.
4. Bạn có thấy là khi bạn dùng biến ages + i thì bạn có thể “trỏ” tới bất cứ phần tử nào trong mảng không. Người ta gọi đây là con trỏ hay pointer. Con trỏ chính là cũng là một biến, nhưng biến này sẽ chứa địa chỉ, địa chỉ này là địa chỉ của vùng nhớ mà con trỏ trỏ tới.

Chúng ta qua phần tiếp theo.

Practical Pointer Usage

Có thể nói con trỏ chính là nét đẹp nhất trong ngôn ngữ C. Bạn nào học C mà yếu con trỏ thì coi như chưa biết C.
Dùng con trỏ chúng ta có những lợi ích gì?
1. Hệ điều hành cung cấp cho chúng ta một vùng nhớ nào đó, và chúng ta dùng con trỏ sẽ làm việc trực tiếp trên vùng nhớ này. Bao gồm luôn cả chuỗi (strings) và structs (structs chúng ta sẽ học ở bài sau).
2. Bạn có thể vượt qua các vùng nhớ lớn để đi tới những function chỉ với một con trỏ. Nghĩa là bạn dễ đàng và linh hoạt trong việc kiểm soát bộ nhớ.
3. Bạn có thể dễ dàng lấy được địa chỉ của một funciton nào đó, và bạn có thể sử dụng nó như là một “dynamic callback”.
4. Complex scanning of chunks of memory such as converting bytes off a network socket into data structures or parsing files.

The Pointer Lexicon

Đây mình sẽ để nguyên văn của tác giả về các thuật ngữ và các phép tính trên con trỏ:
type *ptr “a pointer of type named ptr”
*ptr “the value of whatever ptr is pointed at”
*(ptr + i) “the value of (whatever ptr is pointed at plus i)”
&thing “the address of thing”
type *ptr = &thing “a pointer of type named ptr set to the address of thing”
ptr++ “increment where ptr points”

Nếu đọc không hiểu, thì bạn cứ test và in ra màn hình, tức khắc bạn sẽ hiểu. Test như đoạn code trên mình test thôi, nếu như không biết cách test thì bạn để lại comment bên dưới cho mình.

Pointers Are Not Arrays

Không vấn đề gì, có ai đó hỏi bạn, con trỏ và mảng giống nhau hay khác nhau, bạn cần dứt khoát rằng chúng hoàn toàn khác nhau. Ví dụ đơn giản như thế này, bạn hãy khai báo một con trỏ và một mảng, sau đó lấy kích thước của chúng bằng lệnh sizeof(), bạn sẽ thấy sự khác biệt.

#include <stdio.h>

int main()
{
    int ages[] = {23, 25, 26, 27};
    int *pointer;
    printf("%d\n", sizeof(ages));
    printf("%d", sizeof(pointer));
    return 0;
}

Reseach

Thực hành càng nhiều càng tốt, để thấy cái hay của con trỏ.
Nghiên cứu thật nhiều về nó để có thể master in C language!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s