Trong hầu hết các ngôn ngữ lập trình, mảng được chứa theo dạng một vùng nhớ liên tục (nếu là chuỗi thì mảng thực ra chứa địa chỉ của những chuỗi, và các địa chỉ này cũng được chứa trong vùng nhớ liên tục).
Tuy nhiên, địa chỉ bộ nhớ được truy cập theo 1 chiều cho nên mảng bắt buộc phải có cách chuyển từ n chiều thành 1 chiều.
Ví dụ, tôi có mảng 1 chiều a (1 to 3) thì trong vùng nhớ, các phần tử được sắp xếp như sau:
| a(1) | a(2) | a(3) |
giả sử mỗi phần tử mảng là một đơn vị địa chỉ (một ô trong bộ nhớ), và mảng bắt đầu từ địa chỉ 1001:
a(1) ở địa chỉ 1001; a(2) ở địa chỉ 1002; a(3) ở địa chỉ 1003
Tuy nhiên, nếu tôi có mảng 2 chiều: a (1 to 3, 1 to 2) [3 dòng, 2 cột] thì sao?
Cách xếp trọng cột, tức là xếp cột 1 trước cột 2::
| a(1,1)| a(2,1) | a(3,1) | a(1,2) | a(2,2) | a(3,2) |
a((1,1) ở 1001; a(2,1) ở 1002; a(3,1) ở 1003, a(1,2) ở 1004; a(2,2) ở 1005; a(3,2) ở 1006
Cách xếp trọng dòng, tức là xếp dòng 1 trước dòng 2 trước dòng 3:
| a(1,1) | a(1,2) | a(2,1) | a(2,2) | a(3,1) | a(3,2) |
a((1,1) ở 1001; a(1,2) ở 1002; …
Lệnh ReDim:
Lệnh này lập một vùng nhớ mới; trỏ mảng vào vùng nhớ này; và báo cho hệ thống biết là vùng nhớ cũ không còn xài nữa.
Lệnh ReDim Preserve:
Tương tự như vậy, nhưng thêm phần chép dữ liệu vùng nhớ cũ vào vùng nhớ mới.
Nếu trong mảng 1 chiều trên, a được đổi thành a(1 to 5) thì lệnh sẽ lấy một khoảng bộ nhớ khác với 5 ô (ví dụ ở 2001-2005). Ta có a mới:
| a(1) | a(2) | a(3) | a(4) | a(5) |
a(1) ở 2001; a(2) ở 2002; a(3) ở 2003; a(4) ở 2004; a(5) ở 2005
Để thực hiện copy dữ liệu, Redim Preserve sẽ dùng hàm tượng tự như MemCpy (hàm này cóp py từng khối chứ không phải từng ô) cóp py 1001-1003 vào 2001-2003.
Nếu trong mảng 2 chiều trên, a được đổi thành a(1 to 4, 1 to 2) [tăng lên 1 dòng] thì sao?
Cách xếp trọng cột:
| a(1,1)| a(2,1) | a(3,1) | a(4,1) | a(1,2) | a(2,2) | a(3,2) | a(4,2) |
Đến lúc cóp py dữ liệu Preserve không thể nào cóp py 1001-1006 vào 2001-2006 được. Vì chép 1001-1003 thì xuôi, nhưng đến 1004 thì vốn là a(1,2), nếu chép vào 2004 thì bị trật phần tử (2004 là địa chỉ mới của a(4,1), trong khi địa chỉ mới của a(1,2) phải là 2005).
Mặt khác, cũng với cách xếp trọng cột, a được đổi thành a(1 to 3, 1 to 3) [tăng lên 1 cột] thì sao?
| a(1,1)| a(2,1) | a(3,1) | a(1,2) | a(2,2) | a(3,2) | a(3,3) | a(2,3) | a(3,3) |
Ta thấy 1001-1006 có thể chép thẳng vào 2001-2006.
Vì vậy ngôn ngữ trọng cột bắt buộc không cho phép thay đổi số hàng. Mà chỉ được thay đổi số cột
@siwtom: cảm ơn bạn đã nhắc, tôi gõ nhầm thật: tôi gõ "trọng cột" (row major); trong khi "trọng dòng" (row major) mới đúng.
Hầu hết các ngôn ngữ sau này đều dùng "trọng dòng". Tôi nhớ mang máng Delphi vốn gần với Pascal, mà Pascal thì vốn được đặt ra để dạy Angol 60 cho nên nó thiết kế theo ý nghĩa đại số hơn. Theo tôi nghĩ thì BASIC vốn đi đôi với FORTRAN, là ngôn ngữ cổ cho nên nó dùng trọng cột (nghĩ vậy chứ chả có gì quyết đoán).