Video: C++ Bài 25 - Mảng và con trỏ ( Phần 1) 2025
Tên của mảng là một con trỏ đến mảng đó. Mảng là một dãy các biến được lưu trữ trong bộ nhớ. tên mảng trỏ đến mục đầu tiên.
Đây là một câu hỏi thú vị về con trỏ: Bạn có thể có tiêu đề chức năng, chẳng hạn như dòng sau, và chỉ cần sử dụng sizeof để xác định có bao nhiêu phần tử trong mảng? Nếu vậy, chức năng này sẽ không cần phải có người gọi chỉ định kích thước của mảng đó.
int AddUp (int Numbers []) {Xem xét hàm này tìm thấy trong ví dụ Array01 và main () gọi nó là:
void ProcessArray (int Numbers []) { cout << "inside function: Kích thước bằng byte là" << sizeof (Numbers) << endl;} int main (int argc, char * argv []) {int MyNumbers [] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; cout << "bên ngoài chức năng: Kích thước byte là"; cout << sizeof (MyNumbers) << endl; ProcessArray (MyNumbers); return 0;}
Khi bạn chạy ứng dụng này, đây là những gì bạn thấy:
Bên ngoài chức năng, mã biết rằng kích thước của mảng là 40 byte. Nhưng tại sao mã nghĩ rằng kích thước là 4 sau khi nó là bên trong mảng? Lý do là mặc dù nó xuất hiện rằng bạn đang đi qua một mảng, bạn đang thực sự đi qua mộtcon trỏ đến một mảng. Kích thước của con trỏ chỉ là 4, và đó là những gì mà dòng cout cuối cùng in ra.
int MyNumbers [5];
trình biên dịch biết rằng bạn có một mảng, và toán tử sizeof cung cấp cho bạn kích thước của toàn bộ mảng. Tên mảng, sau đó, là
cả hai một con trỏ và một mảng! Nhưng nếu bạn tuyên bố một tiêu đề chức năng mà không có một kích thước mảng, chẳng hạn như void ProcessArray (int Số []) (
trình biên dịch coi điều này như chỉ đơn giản là một
con trỏ và không có gì nhiều hơn nữa. Dòng cuối này, trên thực tế, tương đương với dòng sau: void ProcessArray (int * Numbers) <
Như vậy, bên trong các hàm mà một trong hai dòng khai báo, hai dòng mã sau
tương đương <: Số [3] = 10; * (Số 3) = 10; Tương đương này có nghĩa là nếu bạn sử dụng một khai báo extern trên một mảng, chẳng hạn như
extern int MyNumbers [];
và sau đó lấy kích thước của mảng này, trình biên dịch sẽ bị lẫn lộn. Dưới đây là ví dụ: Nếu bạn có hai tệp, số. cpp và main. cpp, nơi mà con số. cpp tuyên bố một mảng và main. cpp bên ngoài khai báo nó (như thể hiện trong ví dụ Array02), bạn sẽ nhận được một lỗi biên dịch nếu bạn gọi sizeof:
#include using namespace std; extern int MyNumbers []; int main (int argc, char * argv []) {cout << sizeof (MyNumbers) << endl; return = 0;}
Trong Mã:: Blocks, trình biên dịch gcc cho chúng ta lỗi này:
lỗi: ứng dụng không hợp lệ của 'sizeof' đến kiểu không đầy đủ 'int []'
Giải pháp là đặt kích thước của mảng trong ngoặc đơn.Chỉ cần chắc chắn rằng kích thước là giống như trong tập tin mã nguồn khác! Bạn có thể giả mạo trình biên dịch bằng cách thay đổi số, và bạn
sẽ không nhận được lỗi
. Nhưng đó là phong cách lập trình xấu và chỉ cần yêu cầu lỗi. Mặc dù mảng
chỉ đơn giản là một dãy các biến nằm sát nhau trong bộ nhớ, tên của mảng thực sự chỉ là một con trỏ đến phần tử đầu tiên trong mảng. Bạn có thể sử dụng tên như một con trỏ. Tuy nhiên, làm điều đó chỉ khi bạn thực sự cần phải làm việc với một con trỏ. Sau khi tất cả, bạn thực sự không có lý do để viết mã đó là bí ẩn, chẳng hạn như * (Số 3) = 10;. Cuộc trò chuyện cũng đúng. Xem hàm này: void ProcessArray (int * Numbers) {cout << số [1] << endl;} Chức năng này lấy một con trỏ như một tham số, tuy nhiên bạn truy cập nó như một mảng. Một lần nữa, không viết mã như thế này; thay vào đó, bạn nên hiểu
lý do tại sao mã như thế này hoạt động
. Bằng cách đó, bạn có kiến thức sâu hơn về các mảng và cách chúng tồn tại bên trong máy tính, và kiến thức này lần lượt có thể giúp bạn viết mã hoạt động đúng.
Mặc dù, tên mảng chỉ là một con trỏ, tên của một mảng các số nguyên không phải là chính xác giống như một con trỏ đến một số nguyên. Kiểm tra các dòng mã (tìm thấy trong ví dụ Array03): int LotsONumbers [50]; int x; LotsONumbers = & x; Trỏ con trỏ LotsONumbers
đến một cái gì đó khác: một cái gì đó được khai báo như một số nguyên. Trình biên dịch không cho phép bạn làm điều này; bạn nhận được một lỗi. Đó không phải là trường hợp nếu LotsONumbers được tuyên bố là int * LotsONumbers; sau đó mã này sẽ làm việc. Nhưng như được viết, mã này sẽ cho bạn một lỗi biên dịch. Và tin rằng nó hay không, đây là lỗi trình biên dịch bạn nhận được trong Mã số:: Blocks:
lỗi: loại không tương thích trong phân công của 'int *' đến 'int [50]'
Lỗi này ngụ ý trình biên dịch thấy một phân biệt rõ ràng giữa hai loại, int * và int []. Tuy nhiên, tên mảng thực sự là một con trỏ, và bạn có thể sử dụng nó như là một; bạn không thể làm tất cả mọi thứ với nó mà bạn có thể với một con trỏ bình thường, như chỉ định lại nó. Khi sử dụng các mảng, hãy lưu ý những lời khuyên dưới đây. Điều này sẽ giúp bạn giữ mảng của bạn không có lỗi: Giữ cho mã của bạn nhất quán. Nếu bạn tuyên bố, ví dụ, một con trỏ đến một số nguyên, không coi nó như một mảng.
Giữ mã của bạn rõ ràng và dễ hiểu. Nếu bạn vượt qua các con trỏ, bạn có thể lấy địa chỉ của phần tử đầu tiên, như trong & (MyNumbers [0]) nếu điều này làm cho mã rõ ràng hơn - mặc dù nó tương đương với MyNumbers.
Khi bạn khai báo một mảng, cố gắng đặt một số bên trong dấu ngoặc, trừ khi bạn đang viết một hàm mà lấy một mảng.
Khi bạn sử dụng từ khóa extern để khai báo một mảng, hãy tiếp tục và cũng đặt kích thước mảng bên trong ngoặc đơn. Nhưng hãy nhất quán! Không sử dụng một lần và số khác một lần nữa. Cách dễ nhất để nhất quán là sử dụng một hằng số, chẳng hạn như const int ArraySize = 10; trong một tập tin tiêu đề phổ biến và sau đó sử dụng nó trong khai báo mảng của bạn: int MyArray [ArraySize];.