Xin chào, và chào mừng trở lại.
Trong bài giảng này, tôi muốn nói về việc sử dụng con trỏ và cấu trúc,
chúng liên quan như thế nào.
Chúng ta có thể có các phần tử bên trong một cấu trúc là
một con trỏ, và sau đó chúng ta cũng có thể làm cho chính các cấu trúc của chúng ta trở thành con trỏ.
Hai khái niệm rất hữu ích.
Vì vậy, cấu trúc là quan trọng ở đây c cho phép con trỏ hai cấu trúc.
Vì vậy, khi chúng ta tạo một biến kiểu cấu trúc, chúng ta có thể tạo
nó dưới dạng một con trỏ.
Con trỏ đến cấu trúc dễ thao tác hơn chính cấu trúc.
Vì vậy, một lần nữa, nó là một thứ quan trọng,
giúp mọi thứ dễ dàng hơn rất nhiều và nó cũng hiệu quả hơn.
Trong một số triển khai cũ hơn của ngôn
ngữ c, một cấu trúc
không thể được chuyển như một đối số cho một hàm, nhưng chúng
ta biết rằng một con trỏ có thể. Vì vậy, đây là một lý do khác tại
sao bạn muốn có một cấu trúc là một con trỏ khi bạn khai báo
nó bởi vì sau đó bạn có thể chuyển nó xung quanh trong các phiên bản cũ
hơn của c, bạn có thể chuyển nó như một đối số cho một hàm.
Ngay cả khi bạn có thể chuyển một cấu trúc làm đối số, thì việc
chuyển một con trỏ sẽ hiệu quả hơn.
Chúng tôi biết rằng điều đó hiệu quả hơn. Chúng ta đã từng nói về điều này trong quá khứ
làm thế nào để vượt qua quan trọng có thể hiệu quả hơn.
Trong trường hợp này, nó thậm chí còn
hiệu quả hơn vì nếu bạn đang truyền toàn bộ cấu trúc, nếu cấu
trúc lớn và chứa nhiều phần tử, bạn đang sao chép
tất cả các phần tử trong cấu trúc vào tham số đó.
Nếu bạn đang chuyển một con trỏ chỉ sao chép địa chỉ.
Vì vậy, nó thậm chí còn quan trọng hơn
với con trỏ là đối số có cấu trúc vì cấu trúc có thể lớn.
Vì vậy, nhiều biểu diễn dữ liệu sử dụng các cấu trúc, chứa các con trỏ
đến các cấu trúc khác.
Bạn sẽ thấy điều này rất nhiều trong tất cả các
cấu trúc chương trình c là con trỏ và vì những lý do mà chúng tôi đã đề cập.
Thực tế là bạn có thể chuyển chúng dưới dạng tham số trên các phiên bản cũ
hơn để xem và nó cũng hiệu quả hơn bởi vì bạn, chúng
tôi thực hiện mọi thứ theo từng giá trị, việc sao chép
địa chỉ hiệu quả hơn nhiều so với việc
sao chép tất cả các phần tử của cấu trúc lớn này.
Vì vậy, khai báo một cấu trúc như một con trỏ khá đơn giản.
Khi bạn xác định một biến là một con trỏ để đánh dấu, bạn chỉ cần sử dụng dấu hoa
thị đó sau loại dữ liệu.
Và chúng tôi đã nói rằng cấu trúc thực sự là một kiểu mới.
Trong trường hợp này, cấu trúc ngày quan trọng của chúng tôi.
Chúng tôi chỉ nói cấu trúc ngày và sau đó sử dụng con trỏ ngày dấu
hoa thị và có thể bạn sẽ muốn khởi tạo nó thành null.
Bởi vì hãy nhớ rằng, khi bạn nói con trỏ cấu trúc ngày con trỏ ngày
cấu trúc ngày con trỏ không cấp phát bất kỳ bộ nhớ nào,
nó sẽ tạo bộ nhớ để lưu trữ con trỏ thực tế.
Nó không tạo bộ nhớ cho dữ liệu bên trong nó.
Vì vậy, bạn có
thể gán cho điểm ngày này hoặc địa chỉ của ngày cấu trúc khác
hoặc bạn có thể cấp phát bộ nhớ cho nó ở một nơi khác
hoặc bạn cũng có thể khởi tạo nó
bằng một số dữ liệu theo cách đó.
Vì vậy, con trỏ biến ngày tháng có thể được chỉ định giống như
các con trỏ khác, bạn có thể đặt nó trỏ đến
ngày hôm nay bằng câu lệnh gán nếu chúng ta đã có khai báo ngày hôm nay.
Chúng tôi sẽ chỉ sử dụng ký hiệu và để lấy địa chỉ của nó.
Vì vậy, chúng tôi tạo một cấu trúc ngày bình thường và đó là ngày hôm nay.
Vì vậy, điều đó sẽ tạo ra bộ nhớ cho ba yếu tố.
Và sau đó chúng tôi tạo con trỏ của chúng tôi và chúng tôi
chỉ cần gán cho nó địa chỉ của ngày kia.
Khá đơn giản. Chúng tôi đã làm điều đó với các kiểu dữ liệu
thông thường, không khác gì khi bạn làm điều đó với các cấu trúc.
Sau đó, bạn có thể truy cập gián tiếp vào bất kỳ thành viên nào của cấu trúc dữ liệu được trỏ đến bởi con trỏ ngày tháng.
Vì vậy, chúng tôi sẽ cần phải làm một cái gì đó như thế này.
Nếu bạn muốn truy cập phần tử của
cấu trúc con trỏ ngày, trước tiên bạn phải hủy tham chiếu nó.
Và vì vậy, có lẽ sẽ hữu ích nếu đặt nó trong dấu ngoặc đơn để nó rất đơn giản.
Bạn phải khử tham chiếu con trỏ ngày để nhận giá trị
của ngày hôm nay trỏ đến,
giá trị của địa chỉ của ngày hôm nay mà nó
trỏ đến để đặt các giá trị cụ thể.
Vì vậy, bạn sẽ hủy tham chiếu
nó và sau đó chấm ngày bằng 21 và điều đó sẽ gán 21 cho con
trỏ ngày của bạn.
Bây giờ ở trên chỉ nói bất cứ điều gì ngày hôm nay đang trỏ
đến, chúng tôi muốn truy cập giá trị đó và đặt ngày là 21.
Trong trường hợp này, dấu ngoặc đơn là bắt buộc vì dấu
chấm có mức độ ưu tiên cao hơn dấu hoa thị.
Nếu bạn không đặt dấu ngoặc đơn vào đó, nó sẽ bị hỏng bởi vì nó sẽ cố gắng thực hiện
dấu chấm trước trước khi nó thực sự đưa con trỏ đến con trỏ, để
trỏ nó đến dữ liệu.
Vì vậy, về cơ bản nó sẽ cố gắng truy cập dữ liệu bằng con trỏ null.
Và do đó, bằng cách hủy tham chiếu, bạn sẽ nhận được giá trị.
Bây giờ khi chúng ta sử dụng cấu trúc một con trỏ.
Nếu chúng ta muốn kiểm tra giá trị của các tháng được lưu trữ trong cấu trúc ngày được trỏ đến bởi con trỏ ngày,
chúng ta có thể làm như thế này.
Chúng tôi hủy tham chiếu con trỏ, đặt trong dấu ngoặc đơn, vì vậy nó được ưu tiên hơn dấu chấm
và sau đó chúng tôi nói tháng chấm bằng 12.
Đó là cú pháp hoàn toàn hợp lệ.
Nhưng nó hơi rườm rà.
Vì vậy, c có cú pháp riêng, vì vậy bạn không cần phải hủy tham chiếu mọi
thứ và đặt nó bên trong dấu ngoặc đơn cho các cấu trúc.
Khi bạn muốn truy cập những gì cấu trúc đang trỏ tới, bạn không cần
phải hủy tham chiếu nó theo cách này.
Có một toán tử đặc biệt tồn tại trong c cho cấu trúc của con trỏ, và
đó là dấu gạch ngang lớn hơn.
Đó là một dấu gạch ngang theo sau là dấu lớn hơn.
Và điều này cho phép bạn không phải hủy tham chiếu con trỏ.
Vì vậy, thay vì đánh dấu sao x bên trong dấu ngoặc đơn rồi chấm
y, bạn chỉ có thể nói dấu gạch ngang x lớn hơn y.
Bởi vì x là một con trỏ, bạn không cần phải tham chiếu đến nó và bạn muốn truy cập
phần tử bên trong cấu trúc đó bằng bất cứ thứ gì bạn đang trỏ tới.
Vì vậy, bạn sẽ thấy cú pháp này ở khắp nơi. Bạn sẽ không thấy
dấu ngoặc đơn và tham chiếu d. Nó hoàn toàn hợp lệ, nhưng bạn đang nhập nhiều ký tự hơn.
Sẽ hiệu quả hơn nhiều nếu chỉ nói x gạch ngang lớn hơn y.
Vì vậy, câu lệnh if trước đó ở đây thay vì hủy tham chiếu bên trong dấu ngoặc đơn, tất cả những
gì bạn phải làm là nói nếu dấu gạch ngang con trỏ ngày lớn hơn tháng.
Và nó có phần trực quan bởi vì dấu gạch ngang lớn hơn là nói rằng nó đang trỏ đến một cái gì đó.
Và như vậy dấu gạch ngang ngày lớn hơn tháng.
Và con trỏ ngày tháng là một con trỏ và đó là lý do tại sao bạn sử dụng dấu gạch ngang lớn hơn.
Bây giờ nếu đó là một cấu trúc lồng nhau, bạn
sẽ làm dấu gạch ngang lớn hơn so với cấu trúc và sau đó bạn phải thực
hiện một dấu chấm sau đó để truy cập các phần tử của cấu trúc lồng nhau.
Nhưng vì con trỏ ngày là một con trỏ nên bạn phải sử dụng dấu gạch ngang bằng hoặc
dấu gạch ngang lớn hơn.
Vì vậy, đây là một ví dụ, chúng tôi đang tạo ngày cấu trúc của chúng
tôi, chúng tôi có ba yếu tố sau đó chúng tôi tạo con trỏ ngày con trỏ của chúng tôi và chúng tôi chỉ
tạo một biến thông thường hôm nay. Chúng tôi gán cho con trỏ của
chúng tôi địa chỉ của ngày hôm nay và sau đó gán các phần tử thực tế
của cấu trúc, chúng tôi chỉ sử dụng dấu gạch ngang đó lớn hơn và sau đó chúng tôi có thể in nó ra.
Vì vậy, chúng ta hãy xem xét điều này trong các khối mã để xem nó hoạt động như thế nào.
Vì vậy, tôi sẽ đưa ví dụ này vào đây.
Và thông thường khi bạn xác định cấu trúc, bạn xác
định chúng bên ngoài một hàm vì sau đó bạn có thể sử dụng chúng trong bất kỳ hàm nào.
Nó giống như một toàn cầu. Nhưng hãy nhớ rằng
khi bạn xác định cấu trúc, bạn không thực sự tạo ra bất kỳ bộ nhớ nào.
Vì vậy, bạn vẫn tạo các biến dưới dạng biến cục bộ hoặc con
trỏ, nhưng định nghĩa thực sự nằm ngoài hàm.
Vì vậy, nếu bạn muốn sử dụng nó, bạn có thể sử dụng nó trong bất kỳ chức năng nào.
Vì vậy, ở trên cùng, chúng tôi đã tạo một cấu trúc mới của loại ngày
hoặc tên cho đến nay và nó chứa ba số nguyên, chúng tôi kết thúc bằng dấu chấm phẩy.
Sau đó, chúng tôi tạo một vài biến bên trong main.
Ngày hôm nay chỉ là ngày cấu trúc biến bình thường
và sau đó là ngày con trỏ. Chúng tôi biết rằng đó là một con trỏ vì nó có dấu hoa thị trước nó.
Chúng ta biết rằng một con trỏ khi bạn tạo một con trỏ, nó chỉ tạo ra cấp phát bộ nhớ để
lưu trữ địa chỉ đó cho giá trị đó của con trỏ đó.
Vì vậy, chúng tôi thực sự phải gán cho nó một địa chỉ mà chúng tôi làm với ký hiệu và ngày hôm
nay bởi vì điều đó thực sự tạo ra một báo cáo bộ nhớ.
Vì vậy, bây giờ con trỏ ngày sẽ trỏ đến bất cứ điều gì ngày
hôm nay với địa chỉ của ngày hôm nay.
Sau đó, chúng tôi có thể bắt đầu gán dữ liệu cho nó bằng cách sử dụng dấu gạch ngang này lớn hơn rất
hữu ích và chỉ cần gán một dữ liệu như bất kỳ ai khác chỉ cần sử dụng toán tử gán.
Và sau đó khi chúng tôi in nó ra,
bạn sẽ nhận thấy rằng chúng tôi không cần phải khử tham chiếu để in nó ra.
Để in nó ra,
chúng ta chỉ có thể thực sự nói các kiểu dữ liệu cho các chỉ định định dạng ở đây phần trăm
cao hơn phần trăm d tương tự cho các số nguyên và sau đó chúng tôi chỉ sử dụng gạch ngang
vì điều đó thực sự đang thực hiện việc hủy tham chiếu.
Bây giờ chúng tôi có thể thay đổi điều này và điều này sẽ hợp lệ.
Chúng ta phải đặt trong dấu ngoặc đơn và sau đó chúng ta phải nói dấu chấm tháng.
Cách nào cũng được, nhưng hãy làm quen với dấu gạch ngang sau đó lớn hơn vì nó là cú pháp tốt hơn.
Và bây giờ khi chúng tôi xây
dựng cái này, bạn sẽ thấy nó in ra các giá trị con
trỏ ngày tháng và tất cả chúng đều được đặt thành 9 25 và 2015.
Vì vậy, nó cho biết ngày hôm nay là 9 giờ 25 phút 15. Nó được định dạng để in ra theo cách đó.
Công cụ khá đơn giản.
Chỉ cần nhớ rằng dấu gạch ngang lớn hơn, đó là một
cú pháp mới cho con trỏ đến cấu trúc.
Nhưng mọi thứ khác ở đây chỉ là bình thường.
Chúng tôi biết rằng con trỏ phải có tại địa chỉ cửa hàng, vì vậy chúng
tôi biết chúng tôi phải cấp phát bộ nhớ động hoặc chúng tôi phải gán cho nó một cấu trúc hiện có.
Hãy quay lại và nói thêm về cấu trúc và con trỏ.
Bây giờ chúng ta hãy nói về cấu trúc chứa con trỏ.
Chúng tôi biết cách tạo một con trỏ cho một cấu trúc.
Chúng ta có thể cấp phát bộ nhớ cho con trỏ đó nếu chúng ta không
muốn gán một địa chỉ hiện có của một con trỏ hiện có.
Nhưng bạn cũng có thể có các phần tử bên trong một
cấu trúc mà chính nó là một con trỏ. Vì vậy, một con trỏ cũng có thể là một thành viên của một cấu trúc.
Chúng ta không phải sử dụng mảng ký tự đó.
Vì vậy, chúng ta có thể nói struct,
chúng ta có thể đặt tên nó trong con trỏ và sau đó chúng ta có thể sử dụng ở đây trong ví dụ này, chúng
ta có hai số nguyên, hai con trỏ số nguyên p1 và p2, cú pháp hoàn toàn hợp lệ để làm điều đó.
Vì vậy, một cấu trúc được gọi trong con trỏ được định nghĩa để chứa hai con trỏ số nguyên.
Cái đầu tiên được gọi là p1 và cái thứ hai được gọi là p2.
Bạn có thể xác định một biến kiểu struct trong con trỏ giống như con
trỏ thông thường, struct, int, con trỏ.
Các con trỏ biến hiện có thể được sử dụng giống như các cấu trúc khác.
Con trỏ không phải là một con trỏ.
Đó là con trỏ int. Nó chứa hai phần tử bên trong được đánh
là con trỏ, nhưng bản thân con trỏ không phải là một con trỏ thực tế.
Vì vậy, hãy chú ý đến điều đó. Đó là một biến cấu trúc có hai con trỏ là thành viên
của nó, điều đó khác.
Vì vậy, nếu chúng ta muốn truy cập các phần tử bên
trong biến con trỏ nằm trong con trỏ, chúng ta không
sử dụng dấu gạch ngang lớn hơn vì con trỏ không phải là con trỏ, nó là một cấu trúc.
Chúng tôi sẽ sử dụng dấu
chấm để truy cập p1 và truy cập p2.
Vì vậy, trong ví dụ này, chúng tôi tạo cấu trúc của
chúng tôi, chúng tôi tạo một biến. Nó không phải là một con trỏ được gọi là con trỏ.
Và sau đó chúng tôi tạo hai
số nguyên, i1 bằng 100 và i2 không được khởi tạo.
Bây giờ p1 và p2 là con trỏ.
Vì vậy, chúng phải chứa các địa chỉ bộ nhớ hợp lệ nơi các địa chỉ đã
được cấp phát bộ nhớ.
Và đó là những gì trong i1 và i2 đang làm.
Khi bạn khai báo các biến số nguyên, bộ nhớ đang được cấp phát cho các số nguyên đó.
Và do đó, bằng cách gán địa chỉ i1 và i2 cho p1 và p2, điều đó hoàn toàn tốt vì
i1 và i2 có bộ nhớ được cấp phát vì chúng là số nguyên.
Bây giờ nếu con trỏ số nguyên không phải là con trỏ số nguyên mà chúng là con trỏ
ký tự, thì bạn phải cấp phát bộ nhớ động.
Vì vậy, bây giờ chúng tôi chỉ đang sử dụng số nguyên, vì vậy chúng tôi gán địa chỉ của hai số nguyên cho p1 và p2.
Bây giờ chúng ta có thể nói con trỏ sao. p2 bằng 97, âm
97.
Tại sao chúng ta phải hủy tham chiếu nó
ở đó bởi vì con trỏ. p2 là những gì chúng tôi đang tham khảo.
Con trỏ. pt p2 là một con trỏ.
Chúng tôi không truy cập vào một phần tử của một cấu trúc.
Chúng tôi đang tham khảo tất cả các con trỏ. p2.
Và chúng tôi sẽ gán giá trị của bất kỳ giá trị nào trỏ đến âm 97.
Vì vậy, hãy nhận thấy sự khác biệt ở đó.
Chúng tôi không tạo một con trỏ cấu trúc.
Chúng tôi đang tạo một con trỏ biến thông thường,
nhưng nó chứa hai phần tử là con trỏ.
Vì vậy, nếu chúng ta muốn gán cho hai phần tử đó bên trong cấu trúc, chúng ta phải hủy tham
chiếu chúng bằng cách sử dụng toán tử hướng dẫn, và đó là những
gì chúng ta làm ở đó.
Và sau đó trong hai báo cáo in của chúng tôi.
Một lần nữa, chúng tôi muốn in ra các giá trị của những gì mà p1 đang
trỏ đến, vì vậy chúng tôi hủy tham chiếu nó
giống như p2 và sau đó chúng tôi cũng
muốn in ra một lần nữa các giá trị mà con trỏ đang trỏ tới.
Vì vậy, trong điều đầu tiên, chúng tôi đang nói i1
bằng phần trăm tôi dấu phẩy con trỏ. p1 bằng phần
trăm I.
Vì vậy, đầu tiên bên trong dấu ngoặc kép chỉ là in ra văn bản thực tế
đó, nó không hủy tham chiếu bất kỳ thứ gì sau dấu phẩy là nơi chúng ta đang thực hiện hủy tham chiếu.
Đầu tiên chúng tôi in ra i1 là 100 và sau
đó in ra các con trỏ p1 sẽ là 100.
I2 thực sự sẽ là âm
97 sau khi chúng ta gán nó cho p2.
Vậy còn mảng ký tự hay con trỏ ký tự. Trong bài trước, chúng ta đã nói
về cách bạn có thể tạo mảng ký tự như một phần
tử bên trong con trỏ. Nhưng những gì về con trỏ ký tự,
chúng ta nên làm điều gì
đó như đầu tiên và cuối cùng có
mảng ký tự hay chúng ta chỉ nên làm điều gì đó như đầu tiên và
cuối cùng với con trỏ ký tự là phần tử. Lựa chọn tốt hơn là gì.
Chà, chúng ta sẽ xem. Nó thực sự một lần nữa là một điều quan trọng nhưng có những lợi thế khi sử dụng các con trỏ.
Vì vậy, khi chúng tôi tạo con trỏ đến các ký tự bên trong các phần tử của
chúng tôi, nó thường tốt hơn một chút.
Nhưng bạn cần hiểu điều gì đang xảy ra ở đây khi bạn tạo
mảng char mảng phần tử dưới dạng một phần tử hoặc một con trỏ dưới dạng một phần tử, cả
hai đều hợp lệ. Nhưng có một sự khác biệt lớn.
Vì vậy, nếu chúng ta nói tên struct
veep hoặc vp và chúng ta nói Talia và Summers, sau đó chúng
ta nói tên con trỏ struct. Vì vậy, hãy nhớ rằng, tên cấu trúc chứa các mảng ký tự.
Tên con trỏ cấu trúc chứa các con trỏ.
Và chúng tôi ở đây đang khởi tạo các con trỏ bằng Brad và Fallingjaw.
Và sau đó chúng ta in chúng ra, chúng ta sẽ in ra phần
tử đầu tiên, là một ký tự a và vp và sau
đó là phần tử đầu tiên của kho bạc, là một con trỏ tới đầu tiên.
Vì vậy, struct đặt tên biến veep.
Điều đang xảy ra ở đây là các chuỗi được lưu trữ bên trong cấu trúc.
Cấu trúc đã phân bổ tổng cộng 40 byte để chứa hai tên, chúng là
các mảng ký tự.
Đó là những gì đang xảy ra khi chúng ta tạo các mảng ký tự bên trong một con trỏ.
Chúng tôi đang phân bổ 40 byte để giữ hai
tên 20 và 20 đó.
Đối với các tên con trỏ biến kho báu cho dù chúng ta có hai con trỏ đầu tiên và cuối cùng, đây
là các chuỗi được lưu trữ ở bất cứ nơi nào trình biên dịch lưu trữ các hằng số chuỗi.
Cấu trúc giữ hai địa chỉ
vì chúng là con trỏ. Con trỏ chứa, cái gì, giá trị là địa chỉ.
Vì vậy, tất cả những gì cần làm là cấp phát hai con trỏ bên trong cấu trúc đó.
Đó là 16 byte cho hầu hết các hệ thống, con trỏ thường là 8 byte hoặc 4 byte.
Cấu trúc struct p name không phân bổ không gian để lưu các chuỗi vì
nó chỉ cấp phát không gian cho chính các con trỏ.
Con trỏ có giá trị là địa chỉ.
Địa chỉ mà nó trỏ tới không có bộ nhớ được cấp phát cho việc đó.
Vì vậy, khi bạn tạo hai con trỏ đó, sẽ không có bộ nhớ nào được cấp cho hai con trỏ đó.
Nó không phân bổ không gian.
Vì vậy, nó chỉ có thể được sử dụng với các chuỗi đã được phân bổ không gian cho chúng ở nơi khác.
Bất cứ khi nào bạn có con trỏ bên trong một cấu trúc,
bạn phải sử dụng malloc hoặc calloc.
Nếu không, chúng có thể được lưu trữ ở bất kỳ nơi nào lưu trữ hằng số chuỗi.
Và đó là sự khác biệt lớn. Vì vậy, con trỏ và cấu trúc tên p
chỉ nên được sử dụng để quản lý các chuỗi đã được tạo và cấp phát ở những nơi khác trong chương trình.
Bạn không muốn gán dữ liệu
cho nó trừ khi bạn đã cấp phát động nó hoặc nó đã được cấp phát
ở một nơi khác, có thể bởi một
cấu trúc hiện có hoặc một cái gì đó. Nhưng thông thường, bạn sẽ muốn định vị lại những con trỏ đó.
Một lần nữa, rất khác.
Bạn đang phân bổ 40 byte cho hai mảng ký tự này bên trong cấu trúc tên.
Đối với cấu trúc tên p, bạn có hai con trỏ.
Không có bộ nhớ nào được cấp phát cho điều đó khi bạn tạo một biến kiểu đó.
Nó chỉ tạo bộ nhớ cho hai con trỏ ký tự, mỗi con trỏ là tám byte.
Để thực sự cấp phát bộ nhớ cho những gì đầu tiên và cuối cùng trỏ đến, bạn phải thực hiện một malloc.
Vì vậy, một trường hợp có ý nghĩa khi sử dụng con trỏ và cấu trúc
để xử lý các
chuỗi là nếu bạn đang cấp phát động bộ nhớ đó.
Đó thường là khi bạn sử dụng
nó vì các kiểu dữ liệu được phép khác sẽ tự động cấp phát bộ nhớ cho bạn.
Vì vậy, bạn muốn sử dụng một con trỏ để lưu trữ địa chỉ.
Điều này có lợi thế là bạn có thể yêu cầu malloc chỉ phân bổ lượng không
gian cần thiết cho một chuỗi. Chúng ta đã nói về những ưu điểm của phân bổ bộ nhớ động.
Khi bạn tạo mọi thứ một cách tĩnh tại thời điểm biên dịch,
bạn sẽ chỉ tạo một số byte cụ thể.
Điều gì sẽ xảy ra nếu bạn cần nhiều byte hơn, bạn bị hỏng, chương trình của bạn sẽ không hoạt động.
Bạn phải quay lại và biên dịch lại. Với các chuỗi được cấp phát động,
bạn có thể điều chỉnh lại, bạn có thể tạo nhiều bộ nhớ tùy thích, điều này làm
cho nó hiệu quả hơn nhiều trong chương trình.
Vì vậy, bạn sẽ sử dụng malloc trên bất kỳ con trỏ nào được tạo bên trong một cấu trúc.
Vì vậy, trong trường hợp này, bạn có một số tên có tên cấu trúc.
Bạn có hai con trỏ, con trỏ ký tự tên và họ.
Và sau đó bạn có một số nguyên, các chữ cái.
Hai chuỗi bên trong ở đây không được lưu trữ trong cấu trúc.
Chúng tôi chỉ tạo bộ nhớ cho các con trỏ chứa địa chỉ.
Chúng tôi muốn tạo bộ nhớ cho fname và lname cho những gì con trỏ đang trỏ tới.
Vì vậy, chúng tôi muốn lưu trữ nó trong một đoạn được quản lý bởi vị trí bộ nhớ động, đang sử dụng malloc.
Địa chỉ của hai chuỗi là những gì được lưu trữ, không phải là những gì chúng trỏ đến.
Vì vậy, địa chỉ là những gì các hàm xử lý chuỗi thường hoạt động, điều này tốt và
đó là lý do tại sao bạn muốn sử dụng con trỏ trong đó bởi
vì sau đó bạn không cần phải làm như vậy, bạn có thể chuyển chúng dễ dàng hơn rất nhiều.
Vì vậy, đây là một ví dụ. Chúng tôi có một chức năng được gọi là lấy thông tin.
Nó cần một con trỏ.
Và chúng ta có thể vượt qua con trỏ đó một cách rất dễ dàng.
Bây giờ chúng ta cũng sẽ tạo một mảng khác hoặc
cho mảng con trỏ của chúng ta mà chúng ta đang
được chuyển đến nó, chúng ta sẽ cấp phát
bộ nhớ cho nó.
Vì vậy, bạn sẽ thấy rằng chúng tôi tạo một ký tự được gọi là tạm thời và
sau đó chúng tôi lưu trữ một số dữ liệu trong tạm thời đó.
Chúng tôi yêu cầu người dùng lấy một thứ gì đó. Chúng tôi không quen thuộc với các tiện ích, nhưng nó giống với bản scanf được lưu một chút.
Sau đó, chúng tôi cấp phát bộ nhớ cho fname bên trong con trỏ đó và chúng tôi làm điều đó giống như chúng tôi
cấp phát bộ nhớ cho bất kỳ ký tự nào. Chúng tôi gọi là malloc,
chúng tôi truyền số lượng byte vào.
Trong trường hợp này, chiều dài str là 10 cộng với 1 cho dấu chấm hết rỗng.
Và sau đó hãy nhớ rằng, malloc biến một ngôi sao trống, vì vậy chúng tôi chuyển nó thành một ngôi sao ký tự.
Nhưng điều này rất quan trọng ở đây. Lời gọi malloc này cần thiết cho bất kỳ cấu trúc nào có chứa con trỏ.
Bây giờ chúng ta đã chuyển con trỏ này vào và con trỏ không bao giờ được cấp phát bộ
nhớ cho nó.
Vì vậy, chúng tôi đang phân bổ bộ nhớ bên trong đây. Sau đó, chúng tôi có thể thực hiện bản sao của chúng tôi rất dễ dàng.
Chúng ta có thể sao chép tạm thời vào fname của cấu trúc pst của chúng ta đã được chuyển vào
dưới dạng một tham số.
Và sau đó, chúng tôi có thể yêu cầu họ nhập họ của họ, chúng tôi có thể bổ sung thêm
bộ nhớ cho họ và sau đó được lưu trữ trong biến struct của họ.
Đây là những gì bạn sẽ cần làm khi bạn có con trỏ đến các ký
tự bên trong cấu trúc của mình, bạn phải thực hiện malloc.
Bởi vì một lần nữa, những con trỏ chỉ lưu trữ địa chỉ.
Chúng cấp phát đủ bộ nhớ để lưu một địa chỉ, không
đủ bộ nhớ để lưu một chuỗi.
Vì vậy, bất cứ điều gì mà địa chỉ đó trỏ đến, bạn phải cấp phát bộ nhớ cho địa
chỉ đó và bạn làm điều đó giống như bình thường
với malloc, sự khác biệt duy nhất ở đây là bạn sử dụng dấu gạch ngang lớn hơn
dấu để truy cập phần tử thực bên trong cấu trúc đó, đó là con trỏ ký tự, vì vậy bạn có
thể gán nó cho nó và đang thực hiện việc hủy tham chiếu.
Vì vậy, bạn sẽ muốn chơi với những thứ này. Điều này rất phổ biến đối
với các con trỏ ký tự bên trong cấu trúc.
Chúng tôi sẽ có một thử thách mà bạn cần phải làm điều này. Nhưng hãy thử với đoạn mã này, đi vào
bên trong các khối mã, bắt đầu cấp phát bộ nhớ cho các chuỗi hoặc con
trỏ ký tự bên trong cấu trúc và xem cách sau đó
bạn có thể sử dụng bản sao str để thực sự đưa dữ liệu vào bên trong đó, nhưng
trước tiên bạn phải cấp phát bộ nhớ trước khi gán .
Nếu bạn đang làm hằng số như trong ví dụ trước, ai biết được bộ nhớ đó được cấp phát ở đâu.
Vì vậy, một lần nữa, rất nhiều khái niệm quan trọng được trình bày trong bài giảng này.
Ý tưởng về một cấu trúc là một con trỏ trong cú
pháp mới này, nơi
bạn có thể sử dụng dấu gạch ngang sau đó lớn hơn thay vì
sử dụng toán tử điều hướng, rất hay.
Và sau đó thực sự có các phần tử là con trỏ và cách bạn
phải cấp phát bộ nhớ cho các con trỏ ký tự. Cảm ơn bạn.