[MUSIC CHƠI] DAVID J. Malan: Được rồi. Đây là CS50. Và đây là sự bắt đầu của tuần 5. Và như bạn có thể nhận thấy, một số vật liệu là nhận được nhiều hơn một chút phức tạp, dày đặc hơn chút. Và nó rất dễ dàng, đặc biệt là nếu bạn đã có thói quen một thời gian, là cố gắng để viết nguệch ngoạc xuống nhất bất cứ điều gì chúng tôi làm, chúng tôi đang nói trong lớp. Nhưng nhận ra, đó không phải là có lẽ phương pháp sư phạm lý tưởng để học tập các loại vật liệu, và vật chất nói chung. Và vì vậy chúng tôi rất vui mừng thông báo Gheng riêng của CS50 mà Luân Công đã bắt đầu chuẩn bị một bộ kinh điển của các ghi chú cho khóa học, với hy vọng đó là, một, những không chỉ phục vụ như là một tham chiếu và một nguồn tài nguyên xem xét các tài liệu và đi trở lại thông qua các tài liệu có thể có thoát bạn lần đầu tiên, nhưng cũng vì thế mà con bạn có thể là nhiều hơn lên hơn xuống, khi nó đến thời gian giảng dạy, để bạn có thể tham gia chu đáo hơn, như trái ngược với scribbly hơn. Với mà nói, những gì bạn sẽ tìm thấy trên trang web này là tài liệu như thế này. Và thông báo, ở phía trên bên trái, có không chỉ là một bảng nội dung, mà còn mã thời gian đó ngay lập tức sẽ nhảy bạn đến phần thích hợp trong đoạn video trực tuyến. Và những gì Chang ở đây đã thực hiện là, về cơ bản, tài liệu những gì xảy ra ở đây bài giảng cụ thể. Và rất nhiều các bài giảng đã online với URL này. Và chúng tôi sẽ tiếp tục gửi phần còn lại của những người vào cuối tuần này, do đó, tận dụng lợi thế của tài nguyên đó. Vì vậy, không có thêm ado, chúng tôi bắt đầu bóc lại lớp đã được chuỗi trong một thời gian. Và những gì chúng ta đã nói một chuỗi thực sự là tuần cuối cùng? Vì sao, để char. Và char sao, tốt, những gì Điều đó thực sự nghĩa là gì? Vâng, tất cả thời gian này, nếu chúng ta đã được gọi một chức năng, như getString, và lưu trữ cái gọi là trở lại giá trị của getString trong một variable-- nó được gọi là s loại string-- chúng tôi đã viết các dòng mã lên đó ở trên. Và đó là khi tôi thấy tôi chữ viết tay phóng đại ở đây Tôi nhận ra chỉ là cách tàn bạo này. Tuy nhiên, chúng ta hãy giả sử rằng, ở phía bên tay phải là, tuy nhiên, một cách hợp lý mô tả về những gì được diễn ra tất cả điều này thời gian với getString. getString, tất nhiên, nhận được một chuỗi. Nhưng điều đó thực sự có nghĩa gì? Nó có nghĩa là nó được một đoạn bộ nhớ từ hệ điều hành bằng cách gọi một chức năng, được gọi là malloc. Nhưng thêm về điều này sau. Và sau đó nó populates rằng đoạn bộ nhớ với các chữ cái người dùng có gõ vào, sau đó, tất nhiên, một ký tự null, hoặc dấu gạch chéo ngược không ở cùng. Trong khi đó, ở phía bên tay trái của câu chuyện này, tất cả các thời gian này, chúng ta đã khai báo một biến, như s. Và biến đó là những gì bây giờ sẽ bắt đầu ghé một con trỏ. Nó không phải là một hộp bên trong mà chúng tôi đưa chuỗi, Daven, mỗi gia nhập, mà chúng ta đặt trong vuông hộp ở bên trái chính xác những gì? Vâng? TƯỢNG: Địa chỉ của nơi mà nó nằm trong bộ nhớ. DAVID J. Malan: Chính xác. Địa chỉ nơi Daven nằm trong bộ nhớ. Và không phải là nơi tất cả các Daven nằm, cho mỗi gia nhập, nhưng cụ thể là địa chỉ của những gì? Vâng? TƯỢNG: nhân vật đầu tiên. DAVID J. Malan: Ký tự đầu tiên trong Daven, trong đó, trong trường hợp này, Tôi đề xuất là tùy tiện và không thực tế 1, OX1, mà chỉ có nghĩa là số thập lục phân của 1. Nhưng nó có thể đi là một số lượng lớn hơn nhiều rằng chúng ta có thể rút ra với 0x như một tiền tố, đại diện cho một nhân vật thập lục phân. Và bởi vì chúng ta không cần phải biết nơi phần còn lại của các nhân vật của Daven là, vì những gì thiết kế đơn giản quyết định đã được thực hiện nhiều năm trước đây? Vâng? TƯỢNG: dấu gạch chéo ngược 0. DAVID J. Malan: Vâng, chính xác. Các dấu gạch chéo ngược 0 cho phép bạn, mặc dù trong thời gian tuyến tính, để đi qua chuỗi, đi từ trái sang phải, với một vòng lặp, hoặc một thời gian vòng lặp, hoặc một cái gì đó giống như đó, và xác định, oh, đây là kết thúc của chuỗi đặc biệt này. Vì vậy, chỉ với địa chỉ tại khởi đầu của một chuỗi, chúng ta có thể truy cập toàn bộ nó, bởi vì tất cả điều này trong khi, một chuỗi vừa được một ngôi sao char. Vì vậy, nó chắc chắn tốt để tiếp tục sử dụng thư viện CS50 và trừu tượng này, vậy để nói chuyện, nhưng chúng tôi sẽ bắt đầu để xem chính xác những gì đã xảy ra bên dưới toàn bộ thời gian này. Vì vậy, bạn có thể nhớ lại ví dụ này, quá, từ lần cuối cùng, so sánh 0, mà không thực sự so sánh. Tuy nhiên, chúng tôi bắt đầu để giải quyết này. Nhưng có lẽ như một bồi dưỡng, một người nào đó tôi có thể quan tâm trong một con voi màu hồng ngày hôm nay, cũng được thực hiện bởi Chang? Làm thế nào về bạn ở phía trước? [Không nghe được]. Nào lên. Và trong khi chờ đợi, khi bạn đưa ra, chúng ta hãy xem xét cho một thời điểm nào mã này đã thực sự làm. Đó là tuyên bố hai biến lên đầu, s và t, và kêu gọi getString. Đây không phải là một chương trình sử dụng rất, bởi vì nó không cho bạn biết phải làm gì. Nhưng chúng ta hãy giả sử chúng tôi tập trung vào những phần ngon ngọt. Và sau đó chúng tôi làm, nếu s bằng bằng t, cần nói printf, bạn đã gõ cùng một điều. Xin chào. Tên của bạn là gì? Janelle: Janelle. DAVID J. Malan: Janelle, Rất vui được gặp bạn. Vì vậy, thách thức của bạn tại tay cho con voi này là lần đầu tiên chúng tôi vẽ một bức tranh về những gì được đại diện trong những lần đầu tiên hai dòng. Vì vậy, s và t có thể đại diện như thế nào trên màn hình? Và bạn chỉ có thể vẽ nó với ngón tay của bạn trên màn hình lớn này. Vì vậy, có hai nửa để mỗi bên của phương trình đó. Vì vậy, có s bên trái, và sau đó GetString bên phải. Và sau đó có t bên trái, và sau đó GetString bên phải. Vậy làm thế nào chúng ta có thể bắt đầu vẽ một bức tranh mà đại diện cho những gì đang xảy ra ở đây trong bộ nhớ, bạn sẽ nói gì? Và hãy để tôi giải thích cho bạn những gì bạn đang làm như bạn đi. Janelle: OK. Vâng, trước tiên, nó sẽ được yêu cầu bạn để có được chuỗi đầu vào. Và nó sẽ store-- oh, xin lỗi. DAVID J. Malan: OK. Tốt. Và điều này được gọi là gì? Oh, OK. Tiếp tục đi. Tôi không có ý làm gián đoạn. Janelle: Xin lỗi. Vì vậy, nó sẽ nhập vào địa chỉ of-- không chắc chắn. Tôi không thể nhớ số chính xác, nhưng tôi tin rằng nó đã được bắt đầu từ 0. DAVID J. Malan: Đó là tất cả phải, bởi vì tôi thực hiện các con số này lên, vì vậy không có câu trả lời đúng. Janelle: Bắt đầu với vòng cung 0. DAVID J. Malan: OK, vì vậy phần tử 0. Chắc chắn rồi. Janelle: Và sau đó nếu là như chỉ là một hai letter-- DAVID J. Malan: OK, lại cho bạn. Janelle: Vì vậy, phần tử 0 và sau đó phần 1 hoặc phần 2. DAVID J. Malan: Và đó mảnh hình ảnh được vẽ bạn ngay bây giờ? Các cuộc gọi đến getString? Hoặc tuyên bố của s? Janelle: Tờ khai của s, tôi tin. Oh, getString, bởi vì nó sẽ được nhập vào mỗi [? khu vực. ?] DAVID J. Malan: Tốt. Chính xác. Mặc dù điều này có hiệu quả trả về một mảng, thu hồi, khi chúng tôi quay trở lại một chuỗi, chúng ta có thể chỉ mục vào đó sử dụng chuỗi 01 và 2. Về mặt kỹ thuật, đây là những lẽ đại diện bởi các địa chỉ cá nhân, nhưng đó là tốt. Vì vậy, giả sử, nếu tôi có thể chỉ nhanh chuyển tiếp đến nơi chúng tôi rời đi thời gian qua, nếu một trong dây là một g b e, dấu gạch chéo ngược 0, do đó đại diện của gabe đầu vào, làm thế nào chúng ta có thể đại diện của bây giờ? Nếu đây là bộ nhớ đó là được trả lại bởi getString? Janelle: Nó sẽ được đại diện bởi một vòng cung? DAVID J. Malan: bởi một vòng cung? Vâng, không có. Hãy chỉ nói rằng, những bức tranh, hãy để tôi chỉ cần đi trước và đề nghị, nếu điều này là s, điều này là giá trị trả lại getString. Và bạn đã vẽ này là 0, 1, 2, là hoàn toàn hợp lý, bởi vì chúng tôi có thể chỉ mục vào chuỗi, như vậy. Nhưng chỉ để phù hợp với Lần cuối cùng, hãy để tôi đi trước và tự ý đề nghị này là địa chỉ 1, đây là địa chỉ 2, đây là địa chỉ 3, và vv. Và như vậy, chỉ để được siêu rõ ràng, những gì đang xảy ra đi vào như là một kết quả của việc dòng mã đầu tiên, bạn sẽ nói gì? Janelle: Địa chỉ 1? DAVID J. Malan: Chính xác. Vì vậy, giải quyết 0x1. Và khi đó, hãy để tôi đi trước và lặp lại nhiều về những gì bạn đã thực hiện và thêm t riêng của tôi ở đây. Nếu tôi được nhập vào gabe một lần nữa, lần thứ hai, khi được nhắc nhở với getString, ở đâu, tất nhiên, là gabe sẽ đi đâu? Vâng, presumably-- Janelle: Giống như ở đây? DAVID J. Malan: Vâng. Janelle: Hoặc nó cũng có trong các hộp giống nhau không? DAVID J. Malan: Hãy để tôi đề xuất, yeah, chính xác, vì vậy trong các hộp bổ sung. Nhưng điều quan trọng bây giờ là, ngay cả mặc dù tôi đã rút ra những khá gần together-- 0x1, điều này 0x2-- được trong thực tế, này ngay bây giờ có thể là địa chỉ 0x10, ví dụ, và 0x11, 0x12 và, và vv. Và như vậy, nếu đó là trường hợp, những gì sẽ kết thúc ở đây trong t? Janelle: 0x10? DAVID J. Malan: Chính xác. Vì vậy, 0x10. Và vì vậy bây giờ, câu hỏi cuối cùng. Bạn đã, bởi đến nay, đã có để làm việc khó khăn nhất cho một con voi cho đến nay. Bởi bây giờ, nếu tôi kéo lên mã một lần nữa, khi tôi làm, theo ba, nếu s tương đương với bằng t, những gì tôi thực sự cách so sánh mà chúng tôi đã rút ra ở đây? Janelle: Hai địa chỉ? DAVID J. Malan: Chính xác. Vì vậy, tôi nói là s tương đương bằng t? Nói cách khác, là 1 tương đương bằng 10? Và tất nhiên, Câu trả lời rõ ràng là bây giờ, không có. Và như vậy chương trình này là cuối cùng sẽ in những gì, bạn sẽ nói gì? Janelle: Nó sẽ được, bạn đã gõ điều tương tự? DAVID J. Malan: Vì vậy, nếu s là 1 và t là 10? Janelle: Bạn gõ những điều khác nhau. DAVID J. Malan: Chính xác. Bạn gõ những điều khác nhau. Tất cả các quyền. Vì vậy, một tràng pháo tay, nếu chúng ta có thể, ở đây. [Vỗ tay] Đó là đau đớn. Tôi biết. Thực hiện độc đáo. Vì vậy, bây giờ chúng ta hãy xem nếu chúng ta không thể trêu chọc nhau những gì sửa chữa được. Và tất nhiên, khi chúng ta cố định this-- mà bây giờ tôi sẽ đại diện cho trong green-- chúng tôi đã làm một vài cải tiến ở đây. Đầu tiên, giống như một sự tỉnh táo kiểm tra, tôi kiểm tra đầu tiên nếu s bằng vô giá trị và t bằng null. Và chỉ để được rõ ràng, khi might s hay t là vô giá trị trong mã như thế này? Khi s hoặc t có thể là null. Vâng? TƯỢNG: [không nghe được]. DAVID J. Malan: Chính xác. Nếu chuỗi mà người sử dụng gõ vào là cách quá dài để phù hợp với bộ nhớ, hoặc một số trường hợp góc kỳ lạ như thế, GetString, như chúng ta sẽ thấy, theo nghĩa đen ngày hôm nay, trong tài liệu của nó, nhấn mạnh, họ sẽ trả về null như một giá trị trọng điểm đặc biệt, hay chỉ là sắp xếp của một biểu tượng đặc biệt đó có nghĩa là một cái gì đó đã đi sai. Vì vậy, chúng tôi muốn kiểm tra đó, bởi vì nó chỉ ra không cho rằng là một giá trị rất nguy hiểm. Thông thường, nếu bạn cố gắng làm điều gì đó với rỗng liên quan đến một function-- đi qua nó như đầu vào, cho instance-- chức năng Rất có thể sẽ sụp đổ và cùng với nó, đi xuống toàn bộ chương trình của bạn. Vì vậy, dòng thứ ba này bây giờ chỉ là một sự tỉnh táo kiểm tra, kiểm tra lỗi, nếu bạn sẽ. Đó là một thói quen tốt ngay bây giờ cho chúng tôi nhận được vào bất cứ lúc nào chúng tôi cố gắng sử dụng một giá trị có thể, có khả năng, không có giá trị. Bây giờ, trong dòng thứ tư ở đây, "Nếu strcmp (s, t)," tốt, những gì mà đề cập đến? Vâng, chúng tôi cho rằng đây là một rất ngắn gọn chức năng đặt tên cho chuỗi so sánh. Và mục đích của nó trong cuộc sống là để so sánh Đối số đầu tiên của mình đối với nó thứ hai, nhưng không phải về địa chỉ của họ, như chúng ta đã vô tình một lúc trước đây với mã màu đỏ, nhưng chứ không phải để so sánh hai chuỗi trong trực giác mà con người cách bằng cách so sánh này, chống lại điều này, chống lại điều này, chống lại điều này, và sau đó dừng lại nếu và khi một hoặc cả hai ngón tay của tôi đánh dấu gạch chéo ngược 0. Strcmp Vì vậy, một người nào đó thực hiện năm trước để thực hiện cho chúng ta các chức năng mà chúng tôi hy vọng chúng tôi đã có thể nhận bằng cách so sánh hai giá trị đơn giản. Bây giờ mà nói, tôi giữ cho bản vẽ tất cả những con số khác nhau. Nhưng thực tế là, tôi đã làm cho những lên toàn bộ thời gian. Và vì vậy tôi sẽ đi trước và viết nguệch ngoạc những hiểu để thực hiện một thời điểm đó, ở cuối trong ngày và di chuyển về phía trước, chúng tôi không thực sự sẽ quan tâm những gì giải quyết điều này là thực sự trong bộ nhớ. Vì vậy, tôi sẽ không để vẽ các các loại số rất nhiều nữa, Tôi chỉ là một bản tóm tắt này đi một ít thân thiện hơn chỉ với mũi tên. Nói cách khác, nếu s là một con trỏ, tốt, chúng ta hãy rút ra nó, theo nghĩa đen, như một con trỏ, một mũi tên chỉ từ bản thân đến cái gì khác, và không phải lo lắng quá nhiều về các minutia của các địa chỉ này trong đó, một lần nữa, tôi đã lên anyway. Nhưng chúng ta sẽ thấy những địa chỉ, đôi khi, khi gỡ lỗi mã. Bây giờ trong khi đó, chương trình này ở đây các bản sửa lỗi, tất nhiên, rằng vấn đề bằng cách so sánh hai chuỗi. Tuy nhiên, chúng tôi chạy vào một vấn đề khác. Đây là từ các bản sao chương trình thời gian qua, theo đó, tôi đã cố gắng để tận dụng chỉ là ký tự đầu tiên trong một chuỗi. Nhưng những gì đã được triệu chứng chúng ta đã thấy lần cuối cùng khi một người sử dụng gõ vào một giá trị, giống như gabe chữ thường, cho s, sau đó chúng tôi phân công của thành t, như trong dòng thứ ba đó, và sau đó tôi đã cố gắng để tận t khung 0? Ảnh hưởng của là gì thay đổi t khung 0 ở đây? TƯỢNG: Nó đã thay đổi s. DAVID J. Malan: Yeah, Tôi đã thay đổi s, là tốt. Bởi vì những gì đã thực sự xảy ra? Vâng, hãy để tôi xem nếu tôi có thể làm sạch lên bức tranh này, như sau. Nếu s, một lần nữa, từ gam, a, b, e, dấu gạch chéo ngược, 0, và s chúng tôi sẽ tiếp tục vẽ như một hộp ở đây, nhưng không có nhiều địa chỉ. Hãy ngừng làm những điều lên. Chúng ta hãy vẽ một bức tranh để đơn giản hóa thế giới. Khi tôi tuyên bố t với chuỗi t, tạo ra rằng đoạn bộ nhớ. Quảng trường xảy ra là 32 bit trong hầu hết các máy tính. Trong thực tế, nếu bạn đã từng nghe nói về một máy tính có một kiến ​​trúc 32-bit, thực sự ưa thích, nói chuyện, mà chỉ cần có nghĩa là nó sử dụng địa chỉ 32-bit. Và như là một kỹ thuật sang một bên, nếu bạn đã bao giờ tự hỏi lý do tại sao máy tính cũ, nếu bạn thực sự cố gắng để canh chúng với rất nhiều RAM, chỉ có thể có tối đa bốn GB RAM, cũng đó là bởi vì, theo nghĩa đen, máy tính cũ của bạn có thể chỉ tính cao như 4 tỷ đồng, 4 tỷ byte, bởi vì nó được sử dụng 32-bit số cho địa chỉ. Nhưng trong mọi trường hợp, trong này Ví dụ, câu chuyện của đơn giản hơn nhiều. t chỉ là một con trỏ, hoặc thực sự là một ngôi sao char, hay còn gọi là chuỗi. Và làm thế nào để tôi muốn cập nhật hình ảnh này bây giờ với dòng thứ hai của mã, sau dấu chấm, chấm, chấm? Khi tôi làm chuỗi t s bằng dấu chấm phẩy, làm thế nào để thay đổi hình ảnh này? Vâng? TƯỢNG: [không nghe được]. DAVID J. Malan: Vâng. Chính xác. Tôi chỉ cần đặt một mũi tên từ hộp t để cùng một địa chỉ, cùng một lá thư đầu tiên cho. Hoặc về mặt kỹ thuật, nếu điều này chàng trai vẫn ở 0x1, nó giống như tôi đã 0x1 và 0x1 ở đây ở đây. Nhưng một lần nữa, những người quan tâm về các địa chỉ? Đó chỉ là ý kiến ​​cho rằng bây giờ là vấn đề. Vì vậy, đây là những gì đang xảy ra ở đây. Vì vậy, tất nhiên, nếu bạn làm t khung 0, đó là mảng ký hiệu, của course-- và thẳng thắn, có vẻ giống như có một mảng ở đây, nhưng bây giờ có điều kỳ lạ này. Biết rằng các ngôn ngữ lập trình, C, cung cấp cho bạn tính năng này, theo đó, ngay cả khi t là một con trỏ, hoặc s là một con trỏ, bạn vẫn có thể sử dụng quen thuộc, khung vuông thoải mái ký hiệu để đi đến các yếu tố đầu tiên, hoặc các yếu tố thứ hai, hoặc bất kỳ yếu tố mà con trỏ đang trỏ đến vì, có lẽ, nó là, như trong trường hợp này, chỉ vào một số mảng. Vì vậy, làm thế nào để chúng tôi sửa lỗi này? Thành thật mà nói, đây là nơi mà nó có một chút áp đảo ở cái nhìn đầu tiên. Nhưng đây là một phiên bản mới và cải tiến. Vì vậy, lần đầu tiên, tôi nhận được loại bỏ các thư viện CS50, chỉ để lộ rằng s thực sự là một ngôi sao char, chỉ cần một từ đồng nghĩa. Và t cũng là một ngôi sao char. Nhưng những gì đang xảy ra trên phía bên phải của dòng đó trong đó t được gán một giá trị? Malloc là gì? Những gì nó strlen? Sizeof (char) là gì? Tại cái quái thực hiện điều này dòng nhìn rất phức tạp? Nó đang làm gì ở mức cao? Đó là những gì lưu trữ trong t? Vâng? TƯỢNG: Nó phân bổ một số tiền nhất định của không gian bộ nhớ. Đó là để lưu trữ, tôi đoán, chữ [không nghe được]. DAVID J. Malan: hoàn hảo. Hoàn hảo. Nó được phân bổ một số số lượng không gian bộ nhớ để lưu trữ, có lẽ, những lá thư trong tương lai. Và đặc biệt, malloc do đó đang trở lại những gì? TƯỢNG: Trả lại [không nghe được]? DAVID J. Malan: Chính xác. Quay trở lại địa chỉ của bộ nhớ, mà là một cách nói, trả về địa chỉ của byte đầu tiên của bộ nhớ. Nhiệm vụ của tôi để nhớ Tôi thực sự bao nhiêu bộ nhớ giao hoặc hỏi malloc cho. Bây giờ bao nhiêu vậy? Vâng, mặc dù có rất nhiều dấu ngoặc ở đây, malloc chỉ mất một đối số duy nhất. Và tôi chỉ định strlen của s, do đó, cho tôi như nhiều byte như có trong s, nhưng thêm một. Tại sao? Vâng? ĐỐI TƯỢNG: Các dấu gạch chéo ngược 0. DAVID J. Malan: Chính xác. Chúng ta phải làm vệ sinh chút. Vì vậy, bởi vì có một dấu gạch chéo ngược 0, chúng ta nên nhớ điều đó. Nếu không, chúng ta sẽ để tạo ra một chuỗi ký tự không có mà terminator đặc biệt. Trong khi đó, chỉ để được siêu hậu môn, tôi có sizeof (char), chỉ trong trường hợp ai đó chạy của tôi mã không trên thiết bị CS50, nhưng có thể là một máy tính khác nhau hoàn toàn nơi ký tự là một byte, theo quy ước, nhưng hai byte, hoặc một cái gì đó lớn hơn thế. Nó chỉ là siêu, siêu không thích lỗi. Mặc dù, trên thực tế, đó là rất có thể sẽ là một 1. Bây giờ, trong khi đó, tôi đi trước và sao chép chuỗi, khung t i bằng khung t s. Và tôi sẽ hoãn đến tuần trước mã nguồn để xem những gì đang xảy ra. Nhưng takeaway chính, và Lý do tôi đặt mã bây giờ màu xanh lá cây, là bởi vì đó là dòng cuối cùng, t khung bằng 0 toupper, có tác dụng Tận mà chuỗi? t và / hay không? Đó là dòng cuối cùng của mã. Chỉ cần t, bởi vì những gì đã xảy ra thời gian này, nếu tôi hơi lùi lại, bước cuối cùng, những gì đã xảy ra là, khi tôi gọi malloc, Tôi về cơ bản có được một đoạn bộ nhớ đó là kích thước giống như bản gốc, bởi vì đó là số học tôi đã làm. Tôi đang lưu trữ trong t địa chỉ trong đó đoạn bộ nhớ. Mặc dù điều này có vẻ tốt đẹp và đẹp, đẹp và trống, thực tế là có, những gì chúng tôi sẽ tiếp tục gọi điện thoại, giá trị rác tại đây. Đó là đoạn bộ nhớ sẽ rất kinh cũng phải được sử dụng trước, một vài giây, vài phút trước. Vì vậy, hoàn toàn có thể là số hoặc các chữ cái đó, chỉ cần một cách tình cờ. Nhưng chúng không có giá trị, cho đến khi tôi bản thân mình cư đoạn này bộ nhớ với các ký tự thực tế, như tôi làm gì trong đó cho vòng lặp đó. Tất cả phải không? Vì vậy, bây giờ, đỉnh cao của ba ví dụ dường như đã được phá vỡ thời gian qua, Ví dụ hoán đổi này, chức năng này làm việc theo ý nghĩa nó đổi a và b. Nhưng nó không làm việc trong ý nghĩa nào khác? Vâng? TƯỢNG: [không nghe được]. DAVID J. Malan: Chính xác. Nếu tôi được gọi chức năng này từ another-- ví dụ, từ một chức năng như chính, nơi Tôi có một biến x, y, như tôi đã làm tuần trước, cùng một mã, và tôi vượt qua trong x và y Trao đổi với, và sau đó gọi Swap-- này, tất nhiên, là phiên bản chính xác là những gì chúng tôi đang về để see-- nó không làm việc. Vì vậy, việc sửa chữa là gì? Vâng, vì vậy chỉ để được rõ ràng, hãy để tôi đi trước và- cho tôi một thứ hai ở đây, và xem nếu tôi có thể cho bạn thấy những tác phẩm mới nhất, mà sẽ in-- chúng ta hãy xem nếu tôi có thể tìm thấy thực fast-- OK này, [không nghe được]. OK, có nó được. Vì vậy, bỏ qua các lệnh tôi chỉ cần gõ. Tôi muốn nó lấy tại phút cuối cùng là một ví dụ từ lần cuối cùng, mà bây giờ được gọi không có Swap. Vì vậy, không hoán đổi là nơi chúng tôi rời khỏi thời gian qua, theo đó, tôi khởi tạo x = 1 và y 2. Sau đó tôi gọi Swap, đi qua trong 1 và 2. Và sau đó chức năng này làm việc trong một nghĩa nào đó, nhưng nó không có vĩnh viễn ảnh hưởng đến hiệu x và y. Vậy câu hỏi ở bàn tay là, làm thế nào bây giờ Chúng ta thực sự sửa chữa vấn đề này? Các giải pháp trong tầm tay là gì? Vâng, trong swap.c, đó là mới ngày hôm nay, nhận thấy một vài sự khác biệt. x và y đều giống nhau. Nhưng điều rõ ràng là khác nhau về dòng 25? Có gì mới ở đó, nếu bạn nhớ những gì nó trông giống như một giây trước? TƯỢNG: [không nghe được]. DAVID J. Malan: Vâng. Vì vậy, các dấu và là một mảnh mới cú pháp không chỉ ở chương trình này, mà còn nói chung trong CS50. Cho đến nay, tôi không nghĩ rằng chúng tôi đã nhìn thấy bất kỳ ví dụ hoặc thực sự nói về chúng trong bất kỳ chi tiết, trừ, có thể, đánh phủ đầu trong phần, một ký hiệu như thế này. Vâng, nó quay ra dấu và là một trong trong những phần cuối cùng của cú pháp mới chúng ta sẽ tìm hiểu. Tất cả điều đó có nghĩa là địa chỉ của một số biến. Tại những địa chỉ không x sống? Nhưng địa chỉ không y sống? Bởi vì nếu vấn đề cơ bản trước khi được rằng x và y đã được thông qua là bản sao, những gì chúng tôi thực sự muốn làm được cung cấp Trao đổi với giống như một kho báu bản đồ dẫn đến nơi x và y thực sự là trong bộ nhớ RAM, do đó Trao đổi có thể làm theo bản đồ mà và đi đến bất cứ nơi nào x hoặc y đánh dấu vị trí và thay đổi các giá trị thực tế 1 và 2 có. Vì vậy, hoán đổi cần phải thay đổi một chút quá. Và ở cái nhìn đầu tiên, sức mạnh này dường như một chút tương tự như char sao. Và thực sự nó là. Vì vậy, một là một con trỏ đến kiểu dữ liệu, dựa trên phần nhấn mạnh điều này? Vì vậy, nó là một int. Vì vậy, một là không còn là một int, đó là địa chỉ của một int. Và tương tự, b là bây giờ đi là địa chỉ của một int. Vì vậy, khi tôi gọi hoán đổi từ chính, Tôi sẽ không để cho Swap 1 và 2. Tôi sẽ để cho nó như Ox-một cái gì đó và Sửu-một cái gì đó, hai địa chỉ đó sẽ dẫn Hoán đổi các vị trí thực tế của họ trong bộ nhớ máy tính của tôi. Vì vậy, bây giờ, thực hiện còn lại của tôi cần phải thay đổi một chút. Có gì khác nhau rõ ràng là bây giờ trong ba dòng mã? Có những ngôi sao chết tiệt tất cả khắp nơi, tất cả phải không? Vì vậy, những gì đang xảy ra ở đây? Vâng? TƯỢNG: Đó rõ ràng là [không nghe được]. DAVID J. Malan: Chính xác. Vì vậy, trong context-- này và đây không phải là các quyết định thiết kế tốt nhất, phải thừa nhận rằng, năm trước. Trong bối cảnh này, nơi bạn chỉ cần có một ngôi sao, và bạn không có một kiểu dữ liệu, như int, ngay lập tức bên trái, thay vào đó bạn có một dấu bằng, rõ ràng, trong bối cảnh này, khi bạn nói một ngôi sao, có nghĩa là đi đến địa chỉ đó là trong một. Thực hiện theo các bản đồ kho báu, vậy để nói chuyện. Và trong khi đó, ở dòng 37, nó có nghĩa là điều tương tự. Tới địa chỉ một, và đưa những gì đang có? Dù là ở vị trí đó b quy định cụ thể. Nói cách khác, đi đến b. Nhận giá trị đó. Tới một và, theo các bằng ký, các nhà điều hành chuyển nhượng, đưa giá trị đó. Tương tự như vậy, int tạm thời chỉ là một int. Không có gì cần phải thay đổi về nhiệt độ. Nó chỉ là một kính phụ tùng từ Annenberg cho một ít sữa hoặc nước cam. Nhưng tôi cần phải nói, đi đến b. Tới điểm đó và đặt giá trị ở nhiệt độ đó. Vì vậy, những gì đang xảy ra sau đó? Khi tôi thực sự gọi Trao đổi thời gian này, nếu khay đầu tiên này ở đây đại diện cho chính, khay thứ hai này đại diện cho Swap khi, Tôi vượt qua ký hiệu và ký hiệu x y từ chính để Trao đổi, chỉ để được rõ ràng, chồng này khung nhận là gì? Vâng? TƯỢNG: [không nghe được]. DAVID J. Malan: Chính xác. Địa chỉ của x và địa chỉ của y. Và bạn có thể nghĩ về những như địa chỉ bưu điện. 33 Oxford Street và 35 Oxford Street, và bạn muốn di chuyển hai tòa nhà mà là ở những địa chỉ. Đó là loại một ý tưởng vô lý, nhưng đó là tất cả chúng ta có ý nghĩa bởi địa chỉ. Nơi trên thế giới có thể bạn tìm thấy hai ints? Nơi trên thế giới có thể bạn thấy hai tòa nhà? Vì vậy, nếu cuối cùng, sau tất cả thời gian tôi đi vào mã nguồn của ngày hôm nay và biên dịch Trao đổi và chạy ./swap, cuối cùng, cho lần đầu tiên chúng ta thực sự thấy rằng giá trị của tôi có thực sự được trao đổi thành công. Và bây giờ, chúng tôi thậm chí có thể mất lưu ý đến điều này, nói rằng, gdb. Vì vậy, hãy để tôi đi vào cùng một tập tin. Hãy để tôi đi trước và chạy gdb của ./swap. Và bây giờ, trong Swap, tôi sẽ đi trước và thiết lập một điểm break trong chính. Và bây giờ tôi sẽ đi trước và chạy chương trình. Và bây giờ chúng ta thấy mã của tôi dừng lại ở dòng đó. Nếu tôi đi trước và in ấn x, những gì tôi có thể thấy ở đây? Đó là một câu hỏi. Nói một lần nữa? TƯỢNG: [không nghe được]. DAVID J. Malan: Vì vậy, số ngẫu nhiên, có thể. Có lẽ tôi có được may mắn, và nó đẹp và đơn giản, giống như 0. Nhưng có lẽ đó là một số số ngẫu nhiên. Trong trường hợp này, tôi đã gặp may. Nó chỉ xảy ra là 0. Nhưng nó thực sự là may mắn, bởi vì không phải cho đến khi tôi gõ tiếp theo và sau đó in x có mà dòng mã, dòng 19, được thực hiện. Trong khi đó, nếu tôi gõ tiếp lần nữa, và bây giờ in ra y, tôi sẽ nhìn thấy 2. Bây giờ, nếu tôi gõ tiếp theo, nó sẽ có được một chút bối rối, bởi vì bây giờ, printf sẽ xuất hiện trên màn hình, như nó đã làm. x là 1. Hãy làm điều này một lần nữa. Và bây giờ, đây là nơi mọi thứ trở nên thú vị. Trước khi tôi gọi hoán đổi hoặc thậm chí bước vào đó, chúng ta hãy một chút cái nhìn. x là, một lần nữa, 1. Y là, tất nhiên, sự tỉnh táo nhanh chóng kiểm tra, 2, vì vậy không có khó khăn. Tuy nhiên, ký hiệu x là gì? Câu trả lời, nó loại sôi nổi tìm kiếm. Nhưng ngôi sao int trong dấu ngoặc đơn chỉ là GDP của cách nói này là một địa chỉ. Nó không phải là một int, đó là một con trỏ đến một int, hay còn được gọi là một địa chỉ. Điều điên rồ này là gì? Chúng tôi chưa bao giờ thấy một cái gì đó giống như vậy trước đây. Vì vậy, đây là địa chỉ trong máy tính của tôi bộ nhớ trong đó x sẽ xảy ra để sống. Đó là Ox-một cái gì đó. Và đây là, thẳng thắn, lý do tại sao Tôi đã bắt đầu vẽ mũi tên, thay vì các con số, bởi vì những người thực sự quan tâm mà int của bạn là một đặc biệt địa chỉ đó là lớn. Nhưng bffff0c4, đây là tất cả thực chữ số thập lục phân, đó là 0 đến f. Vì vậy, chúng tôi sẽ không sống quá dài về những gì những điều này. Nhưng nếu tôi in ra y, Tất nhiên, tôi thấy 2. Nhưng dấu và y, tôi thấy địa chỉ này. Và thông báo, cho tò mò, cách xa nhau là x và y? Bạn có thể bỏ qua hầu hết địa chỉ. Bốn byte. Và đó là phù hợp với chúng tôi trước đó cho rằng lớn như thế nào là một int? Bốn byte. Vì vậy, có vẻ như mọi thứ đều xếp hàng độc đáo, như bạn có thể hy vọng, trong bộ nhớ. Vì vậy, bây giờ, chúng ta hãy nhanh chóng chuyển tiếp đến cuối của câu chuyện này. Chúng ta hãy đi trước và gõ bước, đi sâu vào chức năng Swap. Bây giờ nhận thấy, nếu tôi gõ một, đó là trùng với địa chỉ của x. Nếu tôi gõ b, nó giống hệt nhau đến địa chỉ của y. Vì vậy, những gì tôi nên xem nếu tôi nói, đi đến địa chỉ một? Vì vậy, in một ngôi sao. Vì vậy, sao có nghĩa là đi đến đó, trong bối cảnh này. Ký hiệu có nghĩa là địa chỉ của những gì. Vì vậy, ngôi sao một phương tiện 1. Và sao in b mang lại cho tôi 2. Và hãy để tôi giả định, thời điểm này, có ít nhất mã tiền thu được để thực hiện bây giờ có thể được lý thông qua theo cách đó. Nhưng chúng tôi sẽ xem xét lại ý tưởng này trước khi dài. Vì vậy, phiên bản này của Swap bây giờ là chính xác và cho phép chúng tôi trao đổi kiểu dữ liệu đặc biệt này. Vì vậy, bất kỳ câu hỏi sau đó hoán đổi? Trên sao? Trên địa chỉ? Và bạn sẽ thấy, với vấn đề thiết lập 4, loại, nhưng vấn đề thiết lập 5, chắc chắn, làm thế nào các điều này rất hữu ích và nhận được nhiều hơn nữa thoải mái với họ, như một kết quả. Bất cứ điều gì ở tất cả? Tất cả các quyền. Vì vậy, malloc là, một lần nữa, chức năng này mà chỉ cần cấp phát bộ nhớ, bộ nhớ phân bổ. Và tại sao điều này là hữu ích? Vâng, tất cả thời gian này, bạn đã sử dụng malloc. Nếu bạn xem xét thế nào bây giờ GetString công trình, có lẽ, đó là được yêu cầu một người nào đó cho một đoạn bộ nhớ, bất cứ lúc nào người dùng gõ một chuỗi trong, bởi vì chúng tôi chắc chắn không biết, như nhân viên CS50, lớn như thế nào những chuỗi mà con người sẽ đánh có thể được. Vì vậy, hãy, lần đầu tiên, bắt đầu vỏ lại cách thức hoạt động thư viện CS50, bằng cách của một vài ví dụ đó sẽ dẫn chúng ta ở đó. Vì vậy, nếu tôi mở gedit và mở ra scanf 0, chúng ta sẽ thấy đoạn mã sau. Scanf 0, có sẵn trên các trang web cho ngày hôm nay, có khá nhiều dòng mã ở đây, từ 14 đến 20. Và chúng ta hãy xem những gì nó làm. Nó tuyên bố một int, gọi là x. Nó nói một cái gì đó như thế nào, số lượng xin vui lòng. Và bây giờ nó nói, scanf% i, & x. Vì vậy, có một loạt các công cụ mới có. Nhưng scanf, bạn có thể nghĩ loại như là trái ngược với printf. printf, tất nhiên, bản in ra màn hình. scanf loại quét từ người sử dụng của bàn phím một cái gì đó mà người ấy đã gõ. % I là giống như printf. Điều này có nghĩa mong đợi dùng gõ một int. Và bây giờ, tại sao bạn nghĩ tôi có thể đi qua scanf & x? Nếu mục đích trong cuộc sống của scanf là để có được một cái gì đó từ người sử dụng, ý nghĩa của những gì là đi qua nó, và x, bây giờ không? Vâng? TƯỢNG: [không nghe được]. DAVID J. Malan: Chính xác. Dù tôi, con người, gõ vào, đầu vào của tôi sẽ được lưu tại vị trí đó. Đó là không đủ, nhớ lại, để chỉ vượt qua trong x, bởi vì chúng tôi đã nhìn thấy đã, bất cứ lúc nào bạn vượt qua chỉ là một biến nguyên liệu, như một int, một số chức năng khác, chắc chắn, nó có thể thay đổi điều đó biến, nhưng không phải là vĩnh viễn. Nó có thể không có ảnh hưởng chính. Nó chỉ có thể thay đổi bản sao riêng của địa phương. Nhưng nếu, thay vào đó, bạn không cho tôi int thực tế, nhưng bạn cho tôi hướng dẫn để int đó, tôi bây giờ, là scanf, chắc chắn, tôi có thể làm theo mà giải quyết và đặt một số có vì vậy bạn phải truy cập vào nó là tốt. Vì vậy, khi tôi chạy chương trình này, chúng ta hãy xem. Hãy scanf 0 dấu chấm dấu gạch chéo, scanf 0. Và nếu bây giờ tôi gõ một số như 50, nhờ 50. Nếu bây giờ tôi gõ một số như 1 âm, cho âm 1. Bây giờ tôi gõ một số như 1.5, hm. Tại sao chương trình của tôi bỏ qua cho tôi? Vâng, bởi vì đơn giản, tôi đã nói với nó để mong đợi một int chỉ. Tất cả các quyền. Vì vậy, đó là một phiên bản này. Chúng ta hãy lấy những thứ lên một notch và đề xuất rằng điều này là không tốt. Và ở đây nằm một ví dụ rất đơn giản làm thế nào chúng ta có thể bắt đầu viết mã mà người khác có thể khai thác, thỏa hiệp bằng cách làm những điều xấu. Vì vậy, dòng 16, như vậy tương tự trong tinh thần trước đây, nhưng tôi không tuyên bố nó int thời gian này. Tôi tuyên bố nó char sao, hay còn gọi là chuỗi. Nhưng điều đó thực sự có nghĩa gì? Vì vậy, nếu tôi không chỉ định một address-- và Tôi gọi đó là tùy tiện, đệm, nhưng tôi có thể gọi nó là s, là simple-- và sau đó tôi làm điều này, giải thích cho tôi, nếu bạn có thể, dựa trên trước logic, những gì đang làm scanf ở dòng 18, nếu vượt qua% s và vùng đệm, đó là một địa chỉ? Scanf là gì, nếu bạn áp dụng các cùng một logic chính xác như phiên bản 0, sẽ cố gắng để làm ở đây khi, các loại sử dụng một cái gì đó trong? Vâng? TƯỢNG: [không nghe được]. DAVID J. Malan: Chính xác. Scanf, theo logic trước đó, là sẽ mất chuỗi rằng con người đánh máy in-- nó bây giờ là một chuỗi, nó không phải là một con số, có lẽ, nếu người đó cooperates-- và nó sẽ cố gắng để đưa rằng chuỗi trong bộ nhớ ở bất cứ địa chỉ đệm chỉ định. Và điều này là rất tốt, bởi vì đệm thực sự có nghĩa là một địa chỉ. Nhưng tôi khẳng định chương trình này là lỗi trong một cách rất nghiêm trọng, bởi vì những gì giá trị đệm theo mặc định? Tôi đã khởi tạo vào những gì? Những gì đoạn bộ nhớ? Tôi đã không, phải không? Vì vậy, mặc dù tôi đã phân bổ một sao char đó không còn gọi là s, nó thay vì gọi là, để buffer-- chúng ta hãy vẽ tên biến bây giờ là buffer-- nếu tôi có không gọi là getString hoặc malloc đây, mà hiệu quả có nghĩa là đệm chỉ là một số giá trị rác. Bây giờ điều đó có nghĩa là gì? Nó có nghĩa là tôi đã nói với scanf để mong đợi một chuỗi từ người sử dụng. Và bạn biết gì không? Dù điều này là chỉ đối với: và tôi rút ra dấu hỏi, nhưng trong thực tế, nó sẽ được một cái gì đó giống như OX1, 2, 3, phải không? Đó là một số giá trị không có thật mà chỉ cần sẽ xảy ra là có từ trước. Vì vậy, nói một cách khác, đó là như bộ đệm chỉ là chỉ vào một cái gì đó trong bộ nhớ. Tôi không có ý tưởng gì. Vì vậy, nếu tôi gõ gabe bây giờ, nó sẽ để cố gắng đưa g-a-b-e / 0 ở đó. Nhưng ai mà biết được đó là những gì? Và trong quá khứ, bất kỳ Hiện chúng tôi đã cố gắng để chạm vào bộ nhớ mà không thuộc với chúng tôi, những gì đã xảy ra? Hoặc hầu hết thời gian. Lỗi phân khúc, phải không? Mũi tên này, tôi không có ý tưởng mà nó trỏ. nó chỉ là một số giá trị ngẫu nhiên. Và tất nhiên, nếu bạn giải thích một giá trị ngẫu nhiên như một địa chỉ, bạn sẽ đi đến một số điểm ngẫu nhiên. Vì vậy, gabe might thực sự sụp đổ chương trình của tôi trong trường hợp này đây. Vì vậy, những gì chúng ta có thể làm điều đó gần như là xấu? Xem xét việc này và thứ ba Ví dụ cuối cùng của scanf. Phiên bản này là tốt hơn trong những gì có ý nghĩa? Nếu bạn cảm thấy thoải mái với vấn đề trước đây, điều này là tốt hơn. Tại sao? TƯỢNG: [không nghe được]. DAVID J. Malan: Tốt. Vì vậy, trường hợp này dòng 16 là tốt hơn, trong ý nghĩa rằng chúng ta một cách rõ ràng phân bổ một số bộ nhớ. Chúng tôi không sử dụng malloc, chúng tôi đang sử dụng 2 tuần Cách tiếp cận của chỉ cần khai báo một mảng. Và chúng tôi đã nói trước đó một chuỗi chỉ là một mảng kí tự, vì vậy đây là hoàn toàn hợp pháp. Nhưng đó là, tất nhiên, là bạn lưu ý, kích thước cố định, 16. Vì vậy, chương trình này là hoàn toàn an toàn, nếu tôi gõ trong chuỗi một nhân vật, hai nhân vật chuỗi, 15 chuỗi ký tự. Nhưng ngay khi tôi bắt đầu gõ 16, 17, 18, 1000 chuỗi ký tự, đâu là chuỗi sẽ kết thúc? Nó sẽ kết thúc một phần ở đây. Nhưng sau đó những người hiểu biết những gì khác là vượt ra ngoài ranh giới của mảng cụ thể không? Nó như thể tôi đã tuyên bố 16 hộp ở đây. Vì vậy, thay vì vẽ ra tất cả 16, chúng tôi sẽ chỉ giả vờ rằng tôi đã rút ra 16. Nhưng nếu tôi sau đó cố gắng để đọc một chuỗi đó là lâu hơn nữa, như 50 ký tự, Tôi sẽ bắt đầu đưa a, b, c, d, x, y, z. Và điều này có lẽ là một số phân đoạn bộ nhớ khác rằng, một lần nữa, có thể gây ra chương trình của tôi sụp đổ, bởi vì tôi đã không yêu cầu bất cứ điều gì nhiều hơn chỉ là 16 byte. Vì vậy, những người quan tâm? Vâng, đây là thư viện CS50. Và hầu hết những điều này chỉ là như hướng dẫn lên hàng đầu. Thư viện CS50, tất cả thời gian này, đã có dòng này ở dòng 52. Chúng tôi đã nhìn thấy typedef, hoặc bạn sẽ thấy typedef trong pset 4, mà chỉ cần tạo ra một từ đồng nghĩa, theo đó char sao có thể có nhiều gọi đơn giản là chuỗi. Vì vậy, đây là một trong những vài bánh xe đào tạo chúng tôi đã sử dụng bí mật bên dưới mui xe. Trong khi đó, đây là chức năng, getchar. Bây giờ rõ ràng, không có cơ thể nó. Và trên thực tế, nếu tôi tiếp tục di chuyển, tôi không thực sự thấy bất kỳ hiện thực các chức năng này. Là một kiểm tra sanity, tại sao vậy? TƯỢNG: [không nghe được]. DAVID J. Malan: Vâng. Vì vậy, đây là tập tin tiêu đề. Và tập tin tiêu đề chứa nguyên mẫu, cộng với một số công cụ khác, có vẻ như, như typedefs. Nhưng trong CS50.c, mà chúng tôi đã không bao giờ cho bạn ngay, nhưng đã được trong các thiết bị CS50 tất cả thời gian này, sâu bên trong các thư mục của nó, nhận thấy rằng có một toàn bộ loạt các chức năng tại đây. Trong thực tế, chúng ta hãy di chuyển xuống. Hãy bỏ qua hầu hết trong số họ, cho bây giờ. Nhưng di chuyển xuống getInt và xem cách getInt hoạt động. Vì vậy, đây là getInt. Và nếu bạn đã bao giờ thực sự quan tâm như thế nào có được int hoạt động, đây là tài liệu của nó. Và một trong những điều nó nói là nó cho bạn biết những gì các phạm vi của các giá trị nó có thể quay trở lại. Đó là bản chất âm 2 tỷ tích cực đến 2 tỷ USD, cho hoặc mất. Và hóa ra, tất cả điều này thời gian, mặc dù chúng tôi đã không bao giờ bạn đã kiểm tra cho nó, nếu có điều gì sai, nó chỉ ra rằng tất cả thời gian này, có getInt được trở về đặc biệt liên tục, không phải null, mà là INT_MAX, đó là ước chỉ là một lập trình viên. Điều đó có nghĩa đây là một giá trị đặc biệt. Hãy chắc chắn để kiểm tra này, chỉ cần trong trường hợp họ gặp khó khăn. Nhưng chúng tôi đã không bao giờ làm phiền với điều đó cho đến nay, bởi vì một lần nữa, điều này có nghĩa là để đơn giản hóa. Nhưng làm thế nào getInt được thực hiện? Vâng, một, phải mất không có đối số. Chúng tôi biết điều đó. Nó trả về một int. Chúng tôi biết điều đó. Vậy làm thế nào nó hoạt động bên dưới mui xe? Vì vậy, có vẻ như vô hạn vòng, ít nhất là sự xuất hiện của một. Chú ý rằng chúng ta đang sử dụng getString. Vì vậy, đó là thú vị. getInt cuộc gọi chức năng riêng của chúng tôi, getString. Và bây giờ tại sao có thể là trường hợp này? Tại sao tôi là phòng thủ ở đây trong dòng 165? Điều gì có thể xảy ra trong dòng 164, chỉ để được rõ ràng? Đó là câu trả lời tương tự như trước. Chỉ có thể là ra khỏi bộ nhớ. Điều gì sai với getString, chúng tôi đã có để có thể xử lý đó. Và lý do tôi không trả lại null là rằng, về mặt kỹ thuật, null là một con trỏ. getInt phải trả lại một int. Vì vậy, tôi đã tự ý quyết định, về cơ bản, mà 2 tỷ USD, cho hoặc mất, sẽ là một giá trị đặc biệt mà tôi có thể không bao giờ thực sự có được từ người sử dụng. Nó chỉ là một giá trị tôi sẽ lãng phí để đại diện cho một mã lỗi. Vì vậy, bây giờ, những thứ có được một chút ưa thích. Và nó không hoàn toàn các chức năng tương tự như trước đây, nhưng nó rất giống nhau. Vì vậy, để ý, tôi tuyên bố ở đây, trong dòng 172, cả một int n và một char c. Và sau đó tôi sử dụng dòng sôi nổi này, sscanf, mà nó quay ra không quét một chuỗi từ bàn phím. Nó đứng một chuỗi hiện có người dùng đã gõ vào. Vì vậy, tôi đã gọi là getString, mà có nghĩa là tôi có một chuỗi trong bộ nhớ. sscanf là những gì bạn muốn gọi một chức năng phân tích cú pháp. Nó nhìn vào chuỗi tôi đã gõ vào, nhân vật của nhân vật, và làm điều gì đó hữu ích. Chuỗi được lưu trữ trong dòng. Và tôi biết rằng chỉ bằng cách sao ở đây và nói, oh, OK, Tôi gọi nó không phải là thời gian này, nhưng dòng. Và bây giờ đây là một chút khác nhau. Nhưng điều này có nghĩa là hiệu quả, vì những lý do chúng tôi sẽ phần nào vẫy tay của chúng tôi vào ngày hôm nay, mà chúng tôi đang kiểm tra để xem nếu người dùng gõ và int và có thể một nhân vật khác. Nếu người dùng gõ vào một int, nó sẽ được lưu trữ trong n, bởi vì tôi đi qua này theo địa chỉ, các Bí quyết mới, chúng tôi đã nhìn thấy ngày hôm nay. Nếu người dùng cũng đã gõ trong 123x như thế, mà x sẽ kết thúc một thư trong nhân vật c. Bây giờ nó quay ra rằng sscanf sẽ cho tôi biết, thông minh, có bao nhiêu biến được sscanf thành công có thể điền vào. Vì vậy, theo logic này, nếu chức năng Tôi đang thực hiện được getInt, nhưng tôi đang kiểm tra, có khả năng, cho người sử dụng đã gõ vào một int tiếp theo là cái gì khác, những gì tôi muốn của sscanf trả lại giá trị thực sự được? Nếu mục đích là để có được chỉ là một int từ người sử dụng? Vì vậy, nếu sscanf lợi nhuận 2, có nghĩa là gì? Người dùng gõ vào một cái gì đó như thế nào, theo nghĩa đen, 123x, mà chỉ là vô nghĩa. Đó là một điều kiện lỗi, và Tôi muốn kiểm tra cho điều đó. Vì vậy, nếu sử dụng các loại này, bởi logic này, những gì hiện sscanf trở lại, bạn sẽ nói gì? Vì vậy, nó sẽ trở lại 2, bởi vì 123 sẽ đi ở đây, và x sẽ kết thúc ở đây. Nhưng tôi không muốn x để điền. Tôi muốn sscanf để chỉ thành công trong điền đầu tiên của biến của nó. Và đó là lý do tại sao tôi muốn sscanf để trở về 1. Và nếu điều này là một chút trên đầu cho thời điểm này, đó là hoàn toàn tốt đẹp. Nhận ra, mặc dù là một trong những giá trị của getInt và getString là chúng ta đang làm một heck của một rất nhiều kiểm tra lỗi như thế này để rằng, cho đến nay, bạn có thể khá nhiều gõ bất cứ điều gì ở bàn phím của bạn, và chúng tôi sẽ bắt nó. Và chúng tôi chắc chắn, nhân viên, chắc chắn sẽ không là nguồn gốc của một lỗi trong của bạn chương trình, bởi vì chúng tôi phòng thủ kiểm tra tất cả các ngu ngốc những điều mà một người sử dụng có thể làm, như cách gõ một chuỗi, khi bạn thực sự muốn int. Vì vậy, chúng tôi sẽ đến now-- trở lại này trước khi long-- nhưng tất cả thời gian này, getString và getInt có là bên dưới mui xe sử dụng này Ý tưởng cơ bản của các địa chỉ bộ nhớ. Vì vậy, bây giờ, chúng ta hãy làm cho mọi việc một hơn ít sử dụng. Như bạn có thể nhớ lại, từ Binky cuối cùng time-- nếu con chuột của tôi sẽ rất cooperate-- chúng tôi đã có mã này, mà thẳng thắn, là khá vô nghĩa. Mã này đạt được không có gì hữu ích, nhưng nó là ví dụ rằng giáo sư Parlante được sử dụng để đại diện cho những gì đang diễn ra trong một chương trình liên quan đến bộ nhớ. Vì vậy, hãy kể lại câu này câu chuyện siêu ngắn gọn. Hai dòng đầu tiên, Tiếng Anh, làm những gì, bạn sẽ nói gì? Chỉ trong một cách hợp lý con người, nhưng nhẹ về mặt kỹ thuật, những đòn. TƯỢNG: [không nghe được]. DAVID J. Malan: OK, bạn đang xây dựng địa chỉ cho x và biến y. Không hẳn, bởi vì x và y là không biến trong ý nghĩa truyền thống. x và y là địa chỉ hoặc sẽ lưu trữ địa chỉ. Vì vậy, hãy thử một lần nữa. Không phải là một khởi đầu tồi tệ, mặc dù. Vâng? TƯỢNG: [không nghe được]. DAVID J. Malan: Tốt. Tôi nghĩ đó là một chút bụi. Khai báo hai con trỏ, hai số nguyên. Và chúng ta gọi họ là x và y. Hoặc nếu chúng ta vẽ này như một bức tranh, một lần nữa, nhớ lại khá đơn giản rằng tất cả chúng tôi đang làm với dòng đầu tiên được vẽ một hộp như thế này, với một số giá trị rác trong nó, và gọi đó là x, và sau đó một hộp như thế này, với một số giá trị rác trong đó, gọi đó là y. Chúng tôi đã tuyên bố hai con trỏ mà cuối cùng sẽ lưu trữ địa chỉ của một int. Vì vậy, đó là tất cả. Vì vậy, khi Binky đã làm điều này, các đất sét chỉ trông như thế này. Và Nick chỉ là loại gói lên các mũi tên, như thể họ không chỉ bất cứ nơi nào đặc biệt, bởi vì họ chỉ giá trị rác. Họ đang không được khởi tạo một cách rõ ràng bất cứ nơi nào đặc biệt. Bây giờ dòng tiếp theo của mã, thu hồi, được điều này. Vì vậy, trong một cách hợp lý sử dụng, nhưng tiếng Anh một chút kỹ thuật, dòng mã này đang làm là gì? Vâng? TƯỢNG: [không nghe được]. DAVID J. Malan: hoàn hảo. Đó là việc phân bổ các đoạn của bộ nhớ đó là kích thước của một int. Và đó là một nửa câu trả lời. Bạn trả lời đúng các một nửa của biểu thức. Điều gì đang xảy ra trên phía bên tay trái của dấu bằng? Vâng? TƯỢNG: Và chuyển nhượng nó vào biến x? DAVID J. Malan: Và chuyển nhượng nó vào biến x. Vì vậy, để tóm tắt, giao đất phía bên phải đủ bộ nhớ để lưu trữ một int. Nhưng malloc đặc biệt trả về địa chỉ trong đó đoạn bộ nhớ, mà bạn đã đề xuất chỉ được lưu trữ trong x. Vì vậy, những gì Nick đã làm thời gian qua với Binky là ông kéo con trỏ mà ra, đất sét, chỉ tại một đoạn trắng của bộ nhớ đó là bằng với kích thước của một int. Và quả thực, đó là có nghĩa để đại diện cho bốn byte. Bây giờ, các dòng tiếp theo của mã đã làm điều này, ngôi sao 42 x được. Vì vậy, 42 là đơn giản trên phía bên phải, ý nghĩa của cuộc sống. Phía bên trái, ngôi sao x có nghĩa là gì? Đó cũng có thể có gone-- đó là OK. OK. TƯỢNG: Về cơ bản, đi đến [không nghe được] DAVID J. Malan: Tốt. TƯỢNG: [không nghe được]. DAVID J. Malan: Chính xác. Bên trái có nghĩa là đi đến x. x là địa chỉ. Nó giống như 33 Oxford Street, hoặc OX1. Và ngôi sao x có nghĩa là đi đến đó giải quyết và đưa những gì đang có? 42. Vì vậy, trên thực tế, đó là chính xác những gì Nick đã làm. Ông bắt đầu với bằng, về cơ bản, tinh thần chỉ vào x, sau mũi tên vào hộp màu trắng trên cánh tay phải bên, và đưa số 42 đó. Nhưng sau đó mọi thứ có một ít nguy hiểm, phải không? Của Binky sắp mất đầu. Sao y tương đương với 13, không may mắn, có nghĩa là gì? Vì vậy, có nghĩa là sao y đi đến địa chỉ trong y. Nhưng địa chỉ trong y là gì? Được rồi, đó là giá trị rác, phải không? Tôi vẽ nó như là một dấu hỏi. Nick đã thu hút nó như là một mũi tên cuộn tròn. Và ngay khi bạn cố gắng làm sao y, nói đến đó, nhưng không có một hợp pháp địa chỉ, đó là một số vị trí không có thật, chương trình sẽ sụp đổ. Và đầu Binky của đang diễn ra để bay ra khỏi đây, vì nó đã làm. Vì vậy, cuối cùng, chương trình này chỉ ra lỗ hổng phẳng. Đó là một chương trình lỗi. Và nó cần phải được cố định. Và cách duy nhất, thực sự, để sửa chữa nó sẽ được, ví dụ, dòng này, mà chúng tôi thậm chí không có được, bởi vì chương trình bị rơi quá sớm. Nhưng nếu chúng ta để sửa lỗi này, những gì hiệu quả thực hiện làm y x bằng có? Vâng, về cơ bản nó chỉ y tại bất kỳ giá trị x được chỉ vào. Vì vậy, trong câu chuyện của Nick, hoặc câu chuyện Binky, cả hai x và y đã chỉ tay vào các đoạn màu trắng của bộ nhớ, do đó, cuối cùng, khi bạn làm sao y tương đương với 13 lần nữa, bạn sẽ đặt 13 trong vị trí thích hợp. Vì vậy, tất cả những dòng này là hoàn hảo hợp pháp, trừ trường hợp này, khi nó xảy ra trước khi bạn thực tế bàn giao một số giá trị y. Bây giờ may mắn, bạn không có lý do thông qua tất cả của các loại vấn đề trên của riêng bạn. Hãy để tôi đi trước và mở lên một cửa sổ thiết bị đầu cuối ở đây và mở ra, chỉ trong một thời điểm, một chương trình siêu ngắn cũng là loại vô nghĩa. Nó xấu xí. Nó không đạt được bất cứ điều gì hữu ích. Nhưng nó chứng tỏ các vấn đề bộ nhớ, vì vậy chúng ta hãy có một cái nhìn. Chính, siêu đơn giản. Nó dường như gọi một chức năng, f, và sau đó trả về 0. Đó là loại khó để mess này lên. Vì vậy, chính là khá tốt, cho đến nay. Vì vậy, e là có vấn đề. Và chỉ không đặt nhiều nỗ lực vào việc đặt tên nó ở đây, để giữ tập trung vào các mã. f có hai dòng. Và chúng ta thấy bây giờ là những gì đang diễn ra. Vì vậy, một mặt here-- và hãy để tôi làm này phù hợp với trước example-- trên một mặt, phía bên trái là làm những gì, bằng tiếng Anh? Nó is-- TƯỢNG: Tạo một con trỏ. DAVID J. Malan: Tạo một con trỏ đến một int và gọi đó là x. Vì vậy, nó tạo ra một trong những hộp Tôi tiếp tục vẽ trên màn hình cảm ứng. Và bây giờ, trên cánh tay phải bên, malloc, tất nhiên, được phân bổ một đoạn bộ nhớ. Và chỉ để được rõ ràng, làm thế nào dung lượng bộ nhớ là nó rõ ràng phân bổ, nếu bạn chỉ loại làm toán ở đây? Vì vậy, nó là 40 byte. Và tôi biết rằng chỉ bởi vì tôi biết một int, trên thiết bị CS50, ít nhất, là bốn byte. Vì vậy, 10 lần 4 là 40. Vì vậy, đây được lưu trữ một x, địa chỉ của ra đầu tiên của 40 ints mà đã được phân bổ không gian trở lại, trở lại, trở lại, trở lại. Và đó là những gì quan trọng về malloc. Nó không mất một chút bộ nhớ ở đây, một chút ở đây, một chút ở đây. Nó cung cấp cho bạn một đoạn bộ nhớ, liên tục kế nhau, từ điều hành hệ thống. Bây giờ những gì về điều này, x 10 khung bằng 0? Dòng tùy ý mã. Nó không đạt được bất cứ điều gì hữu ích. Tuy nhiên, nó là thú vị, vì x khung 10--? Vâng? TƯỢNG: [không nghe được]? DAVID J. Malan: x khung 10 không phải là vô giá trị. Các chi tiết vô chỉ đến chơi với chuỗi, ở phần cuối của một chuỗi. Nhưng một ý nghĩ tốt. Làm thế nào lớn là mảng này, ngay cả mặc dù tôi đã phân bổ 40 byte? Đó là 0 đến chín, phải không? Đó là 10 int, tổng số. 40 byte, nhưng 10 ints, lập chỉ mục từ 0 đến 0. Vì vậy, khung x 10 là gì? Nó thực sự là một số giá trị rác không rõ. Đó là bộ nhớ mà không thuộc về tôi. Tôi không cần phải chạm vào đó byte số 41, 42, 43, 44. Tôi sẽ hơi quá xa. Và quả thực, nếu tôi chạy chương trình, nó có thể rất tốt sụp đổ. Nhưng đôi khi, chúng ta sẽ nhận được may mắn. Và như vậy chỉ để chứng minh this-- và thẳng thắn, bạn không bao giờ biết trước khi bạn làm it-- hãy chạy này. Nó không thực sự sụp đổ. Nhưng nếu tôi thay đổi điều này, cho Ví dụ, để được giống như 1000, thực hiện điều này thực sự cố ý, chúng ta hãy xem nếu chúng ta có thể làm cho nó sụp đổ thời gian này. OK, nó đã không sụp đổ. Làm thế nào về 100.000? Chúng ta hãy làm lại nó, và bây giờ chạy lại nó. OK. Phù. Tất cả các quyền. Vì vậy, rõ ràng, một lần nữa, các phân đoạn của bộ nhớ, có thể nói, là hợp lý lớn, vì vậy chúng tôi có thể nhận được may mắn một lần nữa và một lần nữa. Nhưng cuối cùng, khi bạn nhận được vô lý và thực sự đi xa ra trên màn hình, bạn chạm vào bộ nhớ mà thực sự, thực sự không thuộc về bạn. Nhưng thẳng thắn mà nói, những các loại lỗi sẽ là khó khăn hơn để tìm ra một mình. Nhưng may mắn thay, như lập trình, chúng tôi có công cụ cho phép chúng ta làm điều này cho chúng ta. Vì vậy, đây là, có lẽ, một trong những các chương trình xấu nhất, thậm chí còn xấu hơn sản lượng của gdb. Nhưng nó luôn luôn có một dòng hoặc hai mà là siêu hữu ích. Valgrind là một chương trình giúp bạn không gỡ một chương trình, mỗi gia nhập, nhưng thấy bộ nhớ liên quan đến vấn đề, cụ thể. Nó sẽ tự động chạy mã của bạn bạn và tìm kiếm ít nhất hai điều. Một, bạn đã làm một cái gì đó tình cờ như bộ nhớ liên lạc điều đó không thuộc về bạn? Nó sẽ giúp bạn tìm thấy những trường hợp này. Và thứ hai, nó sẽ giúp bạn tìm thấy một cái gì đó gọi là rò rỉ bộ nhớ, mà chúng tôi có hoàn toàn bỏ qua, ngây thơ, một thời gian và phúc lạc. Nhưng hóa ra, tất cả thời gian này, bất cứ khi nào bạn đã gọi là getString trong rất nhiều các chương trình của chúng tôi, bạn đang yêu cầu các hoạt động hệ thống bộ nhớ, nhưng bạn có bất kỳ ký ức của từng đem lại cho nó trở lại, làm unalloc, hoặc miễn phí, như nó được gọi là. Không, bởi vì chúng tôi đã không bao giờ yêu cầu bạn làm như vậy. Nhưng tất cả thời gian này, các chương trình bạn đã viết trong C đã được rò rỉ bộ nhớ, yêu cầu người điều hành hệ thống hơn và nhiều hơn nữa bộ nhớ cho chuỗi và không có điều gì, nhưng không bao giờ đưa nó trở lại. Và bây giờ đây là một chút của một sự đơn giản hóa, nhưng nếu bạn đã bao giờ chạy máy Mac của bạn hoặc máy tính của bạn một thời gian khá, mở rất nhiều chương trình, có thể đóng chương trình, và mặc dù bạn máy tính đã không bị rơi, nó nhận được chậm hơn rất nhiều, như thể nó thực sự sử dụng rất nhiều bộ nhớ hoặc nguồn lực, mặc dù, nếu bạn thậm chí không chạm vào bàn phím, có thể be-- nhưng không thể always-- thể là các chương trình bạn đang chạy mình có rò rỉ bộ nhớ. Và họ tiếp tục yêu cầu hệ điều hành nhiều hơn và bộ nhớ hơn, nhưng quên về nó, không thực sự sử dụng nó, nhưng Do đó, dùng bộ nhớ đi từ các chương trình khác có thể muốn nó. Vì vậy, đó là một lời giải thích phổ biến. Bây giờ đây là nơi của Valgrind đầu ra là hoàn toàn tàn bạo với những người kém và thoải mái hơn như nhau. Nhưng thú vị thứ là phải lên đây. Người ta nói với tôi một ghi không hợp lệ kích thước bốn xảy ra trong chương trình này, đặc biệt, ở dòng 21 của memory.c. Nếu tôi đi đến đường 21, hm, có thực sự là một ghi không hợp lệ kích thước bốn. Tại sao kích thước bốn? Vâng, number-- này và nó có thể là anything-- là một int. Vì vậy, nó là bốn byte. Vì vậy, tôi đặt bốn byte nơi họ không thuộc về tôi. Đó là những gì Valgrind thực sự nói với tôi. Hơn nữa, nó cũng sẽ cho tôi biết, như chúng ta sẽ thấy, khi bạn chạy này trong pset trong tương lai, nếu và khi bạn đã bị rò rỉ bộ nhớ, mà thực sự Tôi có, bởi vì tôi đã gọi malloc, nhưng tôi đã không thực sự gọi là, trong trường hợp này, miễn phí, cuối cùng mà chúng ta sẽ thấy là đối diện của malloc. Vì vậy, bây giờ, tôi nghĩ rằng, một ví dụ cuối cùng. Vì vậy, cái này là nhiều hơn một chút phức tạp, nhưng nó có lẽ lý do lớn nhất để hãy cẩn thận với bộ nhớ, và lý do mà nhiều chương trình và / hoặc các máy chủ web, thậm chí cho đến ngày nay, được thực hiện trên của kẻ xấu ở đâu đó trên internet người bằng cách nào đó gửi các gói tin giả mạo máy chủ của bạn cố gắng để thỏa hiệp tài khoản của bạn, hoặc mất dữ liệu của bạn, hoặc chỉ thường đi qua một máy tính. Tràn bộ đệm, là tên cho thấy, phương tiện tràn không phải là một int, nhưng một bộ đệm. Và một bộ đệm chỉ là một cách ưa thích nói đó là một loạt các bộ nhớ. Và thực sự, tôi gọi là một chuỗi trước khi đệm, thay vì s. Bởi vì nếu đó là một bộ đệm, như trong ý nghĩa YouTube, hoặc bất cứ lúc nào bạn đang xem một video, bạn có thể đã thấy đệm từ, dấu chấm, dấu chấm, dấu chấm. Đó là cực kỳ khó chịu. Và điều đó chỉ có nghĩa là rằng video của bạn đang cố gắng để tải về rất nhiều byte, rất nhiều byte từ một video từ internet. Nhưng đó là chậm, vì vậy nó đang cố gắng để tải về một bó của họ để điền vào một bộ đệm, một container, do đó bạn có đủ byte rằng nó có thể sau đó cho bạn thấy những video, mà không cần tạm dừng liên tục. Nhưng hóa ra, bạn có thể có một bộ đệm lớn này. Nhưng cố gắng đưa nhiều dữ liệu này trong nó, và rất những điều xấu có thể xảy ra. Vì vậy, ví dụ, hãy nhìn vào trêu ghẹo cuối cùng của một ví dụ. Đây là một chương trình khác rằng, ở cái nhìn đầu tiên, không làm bất cứ điều gì siêu hữu ích. Nó có một chức năng chính đó gọi là chức năng, f. Và chức năng, e, ở đây, có một mảng char, được gọi là c, có kích thước 12. Và sau đó nó sử dụng này chức năng mới được gọi là strncpy. Nó chỉ ra rằng, với đơn giản, dòng mã đơn giản, chỉ cần hai đường dây, chúng tôi đã thực hiện toàn bộ chương trình của tôi, và do đó, toàn bộ máy tính của tôi, và tài khoản người dùng của tôi, và cứng của tôi lái xe có khả năng dễ bị tổn thương cho bất cứ ai những người hiểu biết và đủ tốt để chạy chương trình này với một dòng lệnh nhất định đối số. Nói cách khác, nếu kẻ xấu này đặt bên trong argvargv [1] bằng cách gõ vào bàn phím rất đặc biệt crafted chuỗi, không phải abc, 123, nhưng về cơ bản, ký hiệu nhị phân đại diện cho thực thi mã, một chương trình mà họ đã viết, với chương trình này đơn giản, đó là đại diện của hàng ngàn chương trình dễ bị tổn thương tương tự như vậy, dám nói, người đó cuối cùng có thể xóa tất cả các tập tin trên ổ cứng của tôi, có được một nhấp nháy nhanh chóng để họ có thể gõ lệnh trên của riêng mình, gửi email cho tất cả các tập tin vào bản thân mình. Bất cứ điều gì tôi có thể làm, anh em có thể làm với mã này. Chúng tôi sẽ không hoàn toàn giải quyết này được nêu ra. Và trên thực tế, nó sẽ liên quan đến một hình ảnh nhỏ như thế này, mà chúng tôi sẽ sớm đi để hiểu tất cả các tốt hơn. Nhưng hôm nay, chúng ta hãy kết thúc vào ngày những gì, hy vọng, một chút nhiều hơn hiểu XKCD trò đùa, cho đến khi chúng tôi tiếp tục thời gian tới. Tất cả các quyền. Hẹn gặp các bạn vào ngày thứ Tư. [MUSIC CHƠI] SPEAKER: Và bây giờ, vùng sâu, suy nghĩ, bởi Daven Farnham. Bộ nhớ cũng giống như nhảy vào một đống lá vàng vào một buổi chiều chủ nhật. Gió thổi, tung của bạn hair-- oh, tôi nhớ những ngày when-- [Cười]