1 SPEAKER: שלום לכולם. אנחנו הולכים להתחיל. אני חושב שאנשים עדיין הולכים להיות סינון ב. אבל בעניין של זמן, ולכן אנחנו יכולים להביא לך החבר 'ה מכאן בזמן, אנחנו הולכים להתחיל. אז ברוכים הבאים לסקירת CS50 חידון 0. לאלו מכם שלא הבינו עדיין, יש לך שאלה ביום רביעי. Woo-הו. אם לא התחיל ללמוד עדיין או לא הבין שזה קיים עדיין, חידוני עבר ואת כל המידע על החידון שלך הוא על cs50.net/quizzes. יש כמה דברים די טובים על שם, חידוני עבר מהאחרון 10 שנים, כמו גם מידע על חידון ונושאים זה שיהיה מכוסה. אז בואו נתחיל. אז אתם אולי זוכרים, הראשונים היום של כיתת דוד היה מנורות אלה ב. אז בעצם, כל מה שקורה מתחת למכסת המנוע של מחשב היא נעשה בינארי. בינארי מתכוון למה שזה נשמע כמו, 0 ו -1. יש לו שני ערכים ש יכול להיות מיוצג. אז בדיוק כמו ביום הראשון של סעיף כאשר דוד הדליק את אור הנורה לייצג ב, או 1, המחשב שלנו מבין ובינארי כ0 של 1 של, או ביטול. יסודות של ינארי. כל מקום מיוצג בבסיס שני. אז אתה מוסיף 2 ל0 עד 1 עד 2 כל הדרך עד. כדי לחשב מה בינארי שלך הוא עשרוני, אתה פשוט בצע את המשוואה הזאת דבר סוג. אם יש לך 1 בכל אחד מהמקומות האלה, אתה מכפיל את זה בכל מה ש לבסס את זה ב, להוסיף אותו, ו אתה מקבל את הנקודה העשרונית. אז זה איך סופרים עד 5 בינארי. בדיוק כמו מה שאנחנו עושים על השקופית האחרונה, כך שהיית מייצג 1 עד 5. בדומה לכך, בדיוק כמו שאתה יכול להוסיף ו לחסר בעשרוני או לבסס 10, או באמת כל בסיס, ביכול להוסיף ולחסר בינארי. בדיוק מה שהיית מצפה בעת להוסיף שני עד, אם הוא שווה ליותר מ 1, אתה הנושא 1, להפוך אותו 0, ולעשות כן בדרך זו, רק כמו שהיית מצפה עם קבוע עשרוני או כל בסיס אחר. מגניב. אז כמו שאמרתי לפני, כל מה ש הולך מתחת למכסת המנוע של המחשב שלנו נעשה ב0 ו -1 של, או בינארי. אז איך אנחנו מתייחסים, לדוגמא, אותיות, או מספרים, או תווים? והתשובה לכך הוא ASCII. ASCII הוא מיפוי בין תווים שהיינו רואה בדרך כלל ב שפה אנגלית כמו של, B של, C של, מדגיש, מקפים, ו משהו כזה. וזה ממפה את זה לערך ASCII. ערך ASCII הוא רק מספר ש יכול להיות מובן על ידי המחשב שלך. ובדיוק כמו שאתה יכול לעשות בנוסף ו חיסור עם מספרים, אתה יכול לעשות שלהם עם ערכי ASCII. אז בדוגמא זו, מה יהיה זה להדפיס את? כן, כל כך פשוט חלל C מרחב החלל B ד איפה העכבר שלי? שימו לב שאתה יכול להגדיר int ב65. וכאשר אתה מדפיס את זה באמצעות C אחוזים, זה יהיה לפרש את זה כ אופי ולהדפיס את א באופן דומה, אתה יכול להכריז על זה כמו char. וכאשר אתה להדפיס אותו באמצעות אחוזים C, זה יהיה לפרש שכ אחוזים ד ובדיוק כמו שאתה יכול להוסיף מספר, אתה יכול להוסיף דמויות הן ערכי ASCII, במקרה זה. אז מצביע קטן לכולם. 5, כמחרוזת, לא למעשה שווים 5. אז איך אנחנו יכולים להמיר את מחרוזת 5 למספר השלם 5? יש לך רעיונות? כן. אז אם יש לנו 5 כמחרוזת, אנחנו יכולים להחסיר 0. וזה ייתן לנו 5. ובאופן דומה, אם יש לנו 5 כ מספר שלם, תוסיף כי למחרוזת 0. וזה נותן לנו את המחרוזת 5. מגניב. עכשיו, זוכר בחזרה להרצות אחד שבו דברנו על אלגוריתמים. אז איך אנחנו באמת רוצים מחשב לעשות דברים מעניינים? אתה יודע, רק הוספת וגרעת מספרים ודברים החוצה הדפסה הוא לא כי מרגש. בדרך כלל, אנחנו רוצים המחשב שלנו ל לבצע כמה סוג של אלגוריתם. משהו מורכב יותר קטנה מסתם חשבון פשוט. אלגוריתם הוא רק צעד אחר צעד סט של הוראות כיצד לבצע task-- מסוים בדיוק כמו מתכון. אתה אולי זוכר את היום הראשון של מעמד שבו דודנו לספור חדר של אנשים וכמה אנשים היו בחדר. ייתכן שאתה משמש לספירה אחד אחד. 1, 2, 3, 4. במקרה כזה, אלגוריתם זמן ליניארי. אבל דוד הציג אלגוריתם ל לך לספור את האנשים בחדר שבו כולם נעמדים, אתה אומר שלך מספר לאדם אחר, להוסיף ש מספר עד, ואדם אחד מתיישב. ולחזור על זה. זה סוג אחד של אלגוריתם. אנחנו יכולים לנתח איך יעיל אלגוריתם מבוסס על זה בזמן ריצה. אבל נדבר קצת עוד על כך בהמשך. אז כל האלגוריתמים גם יכולים להיות כתוב בpseudocode. Pseudocode היא רק אנגלית כמו תחביר המשמש לייצוג שפת תכנות. לדוגמא, אם אנחנו רוצים לשאול את משתמש לנחש המספר האהוב עליי, אנחנו אולי יש לי pseudocode ככזה. קבל משתמשים לנחש. אם הניחוש נכון, לספר להם הם נכונים, אחר אומרים להם הם לא נכונים. וpseudocode הוא דרך של בקלות מייצג רעיון או אלגוריתם. אז עכשיו אנחנו אולי נרצה לכתוב דווקא בשפה שהמחשב זה אולי הבנה. כדי שנוכל לכתוב pseudocode ו לפרש את זה לתוך קוד מקור. עד כה, קוד המקור חייב לדבוק לתחביר מסוים של שפת תכנות. ועד כה, בCS50, יש לנו כבר משתמש בעיקר ג. אז זה יכול להיות קוד מקור של ג. מאוחר יותר בקורס, אתה בא בלילה במגע עם תכנות אחר שפות כמו PHP. או אם גם לך לקחת שיעורים אחרים, אתה אולי לעשות Java, Python, או אפילו OCML. אבל בשפת תכנית ג, זה הוא איך אנחנו יכולים לכתוב את קוד המקור של אלגוריתם pseudocode ש אני רק שתואר קודם לכן. אז איך עושה את המחשב שלך למעשה מבין את זה? כמו שאמרתי קודם, זה רק באמת מבין אפסים ואחדים. אז איך זה להגיע מהמקור קוד למשהו שיכול להיות הבין? ובכן, יש לנו משהו נקרא מהדר. אם אתה זוכר בחזרה ברוב שלך psets, היה לך סוג כלשהו של תכנית נכתב בקובץ הנקודה ג. ולאחר מכן היית סוג איפור. אז מה הוא עושה לעשות? ניתן להקליד איפור לקמפל שלך תכנית כי someone-- מי שכתב סט עמ 'שלך; כנראה David-- יצר קובץ איפור. וזה אומר לי לעשות לדעת לרוץ שלך מהדר, צלצול נקרא, שרצון אז לקמפל קוד המקור שלך להתנגד קוד, שהוא אפסים ואחדים שהמחשב שלך מבין. אבל קצת יותר מאוחר, אנחנו נלך יותר לעומק על מהדרים. אז זוכר pset 0, where-- כן, יש לך שאלה? קהל: [לא ברור]? 1 SPEAKER: כן. אני חושב שהם באמת צריך להיות באינטרנט. כן. קהל: האם זה כמו [לא ברור]? 1 SPEAKER: זה לא. הם על cs50.net/quizzes. קהל: חידוני סלאש, לקצץ 2013, לקצץ 0, ופשוט לחץ באמצעות חידונים 2013 וחידון 0, לסקור שקופיות סעיף. 1 SPEAKER: כן, כך שאם אתם רוצים למשוך אותו למעלה ומסתכל על זה בך מחשב עצמו, זה בסדר מדי. להגיד את זה שוב. קהל: [לא ברור]. 1 SPEAKER: כן, [לא ברור] הוא משתנה דמי. אה, כן? קהל: [לא ברור]? 1 SPEAKER: לא, שביתות לא בבחינה. מצטער, השאלה שלה היה, היה שביתות בבחינה. וזה לא. אז pset 0, אתם צריכים את כל יישם משהו באמצעות שריטה. ואנחנו למדנו כמה תכנות בסיסי אבני בניין באמצעות שריטה. אז בואו נסתכל על חלק של אבני בניין אלה המרכיבים את תכנית. ראשון הוא ביטוי בוליאני. ביטויי בוליאני הם אלה ו 0 של או כל דבר שיש שני ערכים אפשריים. במקרה זה, נכון או לא נכון, או ביטול, וכן או לא. דוגמא לפשוטה, פשוט מאוד, תכנית שמשתמשת בוליאנית ביטוי עד כאן. אז על מנת שביטויים בוליאנית ל להיות שימושי, יש לנו מפעילי בוליאני. אלה הם מפעילים שניתן להשתמש בי כדי להשוות ערכים מסוימים. אז יש לנו ואם לאו שווה ל, פחות או שווה ל, גדול או שווה, ופחות מ או גדול מ. אבל מפעילים אלה הם לא מאוד שימושיים אלא אם כן אנו יכולים לשלב אותם לתוך תנאים. אז אתם אולי זוכרים מהתחלה ומp שלך קובע ש היה לי תנאים. הם, בעצם, כמו מזלגות ב ההיגיון של התכנית שלך ש מבצע תלוי אם תנאי הוא נפגש. אז אחד מהתנאים שהיו לנו משמש פעמים רבות בקורס זה הוא אם, אחר, אם, ותנאים אחר. הנה דוגמא לאופן ש אתה עשוי להשתמש בו. האם מישהו יודע את ההבדל בין רק באמצעות אם דוחות כל בדרך למטה פסוקים אם, אחר, אם, ושילוב אחר? כן? קהל: [לא ברור]. 1 SPEAKER: בדיוק. אז אם היה לי אם כל הדרך למטה זה דרך, גם אם התשואות את המצב הזה נכון, זה עדיין ממשיך בדיקת שני הבאים. ואילו, עם אחר אם-, אחר אמירה, אם אחד מחזיר אמת, אחרים לא נבדקו. כל שאלות על זה? מגניב. אז אתה משתמש אחר אם-של אחר הצהרה אם אתה יודע שזה יכול רק להיות אחד מהמקרים הללו. אז אנחנו יודעים אם x הוא פחות מ 0, זה בהחלט לא הולך להיות גדול מ -0. , אבן בניין נוספת בסמוך שלמדנו הן לולאות. יש לנו שלושה סוגים של לולאות. ללולאות, ואילו לולאות, ולעשות בזמן לולאות. ובאופן כללי, כשאתה מתיישב ל לכתוב משהו, אתה צריך להחליט איזו מהשלושה ברצונך להשתמש. אז איך אנחנו מחליטים איזה מהם? אנו משתמשים בדרך כלל ללולאה אם ​​אנחנו יודעים כמה פעמים אנחנו רוצים לחזר דרך משהו או כמה פעמים אנחנו רוצים לבצע משימה. אנו משתמשים בזמן לולאות אם אנחנו צריכים כמה מצב להיות אמיתי כדי לשמור על ריצה. ואנו משתמשים לעשות בזמן שדומה מאוד ל בעוד, אבל אנחנו רוצים את הקוד שלנו להפעלה בעת לפחות פעם אחת. אז לעשות בזמן, כל מה שהוא בלעשות את הרצון תמיד לרוץ לפחות פעם אחת. ואילו, עם הזמן, זה עשוי שלא לפעול כלל, אם המצב הוא לא מרוצה. כל שאלות עם זה? אז מבנה של לולאת for. אתם ראיתם את כל זה. אתה לאתחל אותו. יש לך איזה סוג של מצב. כך, למשל, אנו עשויים לאתחל כעבור i שווה 0. היא i פחות מ -10. ואני ++. פשוט מאוד אחד שעשינו. ללולאה בזמן, באופן דומה, יש לך כדי לקבל קצת סוג של אתחול, איזה מצב, ו איזה עדכון. אז אנחנו יכולים ליישמנו ללולאה גם כלולאה בזמן שמשתמש בזה. ובאופן דומה עם מטלות תוך לולאה, אולי יש לנו כמה אתחול, לבצע משהו, לעדכן אותו, ו לאחר מכן לבדוק את מצבו. אז עכשיו פונקציות. אנחנו שמים את הכל ביחד. אנחנו אולי רוצים לכתוב כמה סוג של פונקציה. נפוצה פונקציה שאולי כבר ראיתי הוא עיקרי. העיקרי הוא פונקציה. יש לו סוג התמורה, int. יש לו שם פונקציה, עיקרי. ויש לה טענות, argc וargv. אז עיקרי הוא רק פונקציה. פונקציות אחרות שאולי יש לי משמשות, printf printf-- הוא function-- GetInt, toupper. אבל אלה יקרו לי היו יישם עבורנו על ידי איזה ספרייה. אם אתם זוכרים, כולל ספרייה או CS50.h זה אני סטנדרטי / ספריית O. כן, שאלה? קהל: האם עיקרי רק גלום בג? האם זה פשוט סוג של [לא ברור]? SPEAKER 1: השאלה היא אם עיקרי הוא גלום בג. וכן, את כל הפונקציות יש להם תפקיד מרכזי. זה סוג של צורך למחשב לדעת מאיפה להתחיל מפעיל את הקוד. קהל: כדי שלא [לא ברור]? SPEAKER 1: מס ' יש עוד שאלות? מגניב. אז בדיוק כמו שאתה יכול להשתמש בפונקציה זה נכתב בשבילך, אתה גם יכול לכתוב פונקציה משלך. זוהי פונקציה שאולי מישהו כתב כדי לחשב את הנפח של q, למשל. יש סוג החזרה כאן, במקרה זה int, שם פונקצית q ושלנו רשימה של פרמטרים. ושים לב שאתה צריך לכתוב את הנתונים סוג של הפרמטר שאתה רוצה להשתמש או אחר הפונקציה לא לדעת איזה סוג של פרמטר שאני צריך לקבל. אז, במקרה זה, אנחנו רוצים מספר שלם כקלט שלנו. אז למה אנחנו ייתכן שנרצה להשתמש בפונקציות? קודם כל, נהדר לארגון. הם עוזרים לשבור את הקוד שלך לתוך יותר מאורגן נתחים ולעשות זה קל יותר לקריאה. פישוט. זה טוב לעיצוב. כשאתה קורא את קטע קוד ותפקידו העיקרי הוא באמת, באמת ארוך, זה יכול להיות קשה יותר סיבה על מה שקורה ב. אז אם אתה לשבור אותו לתוך פונקציות, זה יכול להיות קל יותר לקריאה. ולעשות שימוש חוזר ב- יכולת. אם יש לך נתח של קוד זה להיות בשם או לרוץ מספר פעמים, במקום לשכתב הקוד ש10 פעמים בפונקציה העיקרית שלך, אתה עלול רוצה להשתמש בו שוב. ולאחר מכן בכל פעם שאתה צריך להשתמש בו פיסת הקוד, קוראת לפונקציה. אז עכשיו אם נזכור לחזור להתחלה, אנחנו גם דיברנו על כמה מושגים, אחד מהם הוא השחלה. אשכול הוא הרעיון של מספר רב של רצפים של קוד ביצוע באותו הזמן. אז תחשוב חזרה ליום אחד שבו היה לי דוד אתם סופרים את מספר אנשים בחדר. בעיקרו של דבר, מה קורה בהוא כולכם החבר 'ה היו פועל אשכולות נפרדים. ואת אותם חוטים היו באים יחד כדי לקבל קצת סוג של תשובה. באופן דומה, בגרד, כאשר יש לך שדונים מרובים, אתה עלול יש לי חתול וכלב. והם היו להיות בו זמנית פועל סקריפטים שלהם. כי היא דוגמא לשחלה. והרעיון האחר שהיה הציגו בהתחלה היה אירועים. ואירועים הם חלקים כאשר מספר רב של הקוד שלך לתקשר אחד עם השני. בגרד, זה היה בעת השימוש שליטת שידור וכש לקבל בלוקים. וגם, בבעיה 4 הגדר, ראינו קטן, כמו גם קצת של אירועים. אתם אולי משמשים ספריית Gevent. ולא היה פונקציה waitForClick שבו אתה מחכה למשתמש ללחוץ. ואת לחץ שלך, במקרה זה, יהיה האירוע ומחכה לקליק הוא שלך מטפל באירועים. וגם, לאורך כל ריצת psets שלך ועובד על psets שלך, לך אולי באים במגע עם חלק מפקודות אלה. זה מה שהקלדת לתוכך חלון מסוף או מה שחלון שמופיע בעריכה גרם ל, בעצם, לנווט את המחשב. כך למשל, LS מפרט תכולת ספרייה. הפוך ספרייה יוצרת תיקייה חדשה. CD, שינוי בספרייה. RM, להסיר, מוחק קובץ או כמה ספרייה. ולאחר מכן להסיר את הספרייה מסיר ספרייה. קהל: [לא ברור]? SPEAKER 1: כן, בטוח. מצטער, השאלה הייתה אם אתה הייתי מציע לשים את זה בגיליון לרמות. זה יכול לעזור. אם יש לך חדר, אתה יכול לשים על זה. זה גם בדרך כלל רק טוב מספיק לזכור כי כאשר אתה משתמש בו אולי כדאי לך פשוט יש לה בעל פה. שיעשה את החיים שלך הרבה יותר קלים. האם אני עונה על השאלה שלך? אז עכשיו, דברנו קצת בקצרה על ספריות. אבל שני אלה העיקריים שאנחנו כבר באמצעות עד כה בקורס I / O סטנדרטי וcs50. איזה סוג של דברים כלולים בI / O הסטנדרטי הספרייה? כן, עד כה השתמשנו printf. בcs50, אנחנו השתמשנו GetInt וGetString. ומחרוזת סוג הנתונים גם קורה שיוכרז בספריית cs50 זה. נדבר קצת יותר לעומק על איך ספריות לעבוד וכיצד הם אינטראקציה עם שאר הקוד שלך. אבל אלה שני העיקריים ש יש לבוא במגע עם כל כך הרבה ב כמובן. סוגים. אלה הם טובים לזוכרים כמה כל סוג מיוצג על ידי או איך בתים רבים שכל אחד מן הסוג requires-- int, 4 בתים; char, byte 1. Float הוא 4 בתים. מה הוא כפול? קהל: [לא ברור]. 1 SPEAKER: כן, כך לצוף אבל להכפיל את הגודל. מה לגבי זמן? קהל: [לא ברור]. 1 SPEAKER: אישור. מהו זמן? קהל: [לא ברור]. 1 SPEAKER: כן, להכפיל int. כן. קהל: [לא ברור]. 1 SPEAKER: ארוך [לא ברור]. ולאחר מכן עוד ארוך הוא כפול ש. קהל: לא, לא. ארוך הוא פשוט int. זה תלוי בארכיטקטורה לפני [לא ברור] ויש לי int באותו הגודל. [לא ברור]. וארוך אז: רמקול 1 int הוא אותו הדבר. ולאחר מכן עוד ארוך הוא כפול int. מגניב. ואז, מה הוא הסוג האחרון? קהל: פוינטר. 1 SPEAKER: כן, כך נודע לנו קצת על מצביעים. ולא משנה מה הוא מצביע מצביע to-- זה יכול להיות כוכב char או int star-- זה תמיד 4 בתים עבור מצביע. שאלות על זה? כן? קהל: [לא ברור]? SPEAKER 1: אז ארוך וint הם אותו הדבר במכשיר cs50 זה. קהל: המכשיר לחלוטין להחלפה. 1 SPEAKER: כן. אז ארוך ארוך הוא כפול int. קהל: זה 32 קצת? 1 SPEAKER: 32 קצת, כן. קהל: אז [לא ברור]? 1 SPEAKER: כן, אם זה לא אומרים במפורש, ש צריך להניח 32 קצת. קהל: זה היה אומר משהו כמו בהנחה ארכיטקטורה כמו המכשיר. ל64 קצת, הדברים היחידים ש השינוי הוא משתוקק ומצביעים. שניהם [לא ברור]. 1 SPEAKER: כן? קהל: שאלה. אז באחד מהחידונים בפועל, זה שואל על int חתום. אז איך היה שייקבע מint [לא ברור]? SPEAKER 1: לא חתום בהוא גם 4 בתים. אבל מה שונה חתם int וint חתום? קהל: [לא ברור]. 1 SPEAKER: ימני. אחד יכול לייצג את הערכים שליליים. אבל איך הוא עושה את זה? קהל: [לא ברור]. SPEAKER 1: כן, זה חוסך 1 קצת לייצג את הסימן. חתם אחד יש קצת ש מייצג את הסימן. ולא חתומים רק הוא כל התוצאות החיוביות. קהל: אישור. אז אתה אומר שכפול הוא פעמיים בגודל של float? 1 SPEAKER: חדר זוגי הוא פעמיים בגודל של float, כן. קהל: איך עושה מצביע לזמן ארוך [לא ברור]? 1 SPEAKER: אז השאלה היא איך עושה את המצביע לlong-- ארוך איך הוא שרק ארבעה בתים כאשר ארוך ארוך הבתים 8 שלה. אז זוכר מה הוא מצביע, במהות, בערך מאוד בסיס. קהל: [לא ברור]. 1 SPEAKER: כן, כך מצביע רק מיקום בזיכרון. אז זה לא משנה כמה מקום מצביע שמצביע. הוא צריך רק 4 בתים כדי לעקוב אחר של מיקום זה זיכרון. יש עוד שאלות? מגניב. אז הדבר האחרון שיש לי הוא פלט סטנדרטי. אתה צריך להשתמש בם בתדירות גבוהה מספיק שאתה יכול לזכור. אבל זה כאשר אנו משתמשים printf, למשל. ויש לנו מצייני מיקום אלה ש נקראו קודי פורמט. אז char אחוזים ג, אחוזים i לint, ואנחנו גם יכולים להשתמש בד אחוזים. זה אותו הדבר. אבל, בדרך כלל, באנו CS50 מנסה להשתמש i אחוזים. f אחוזים למצוף. ld אחוזים לאורך זמן ארוך ו אחוזים של למחרוזת. בדומה לכך, אנו כבר משתמשים כמה של רצפי בריחה אלה. לדוגמא, קו נטוי n לשורה חדשה. זה רק כאשר אתה עיצוב הקוד שלך לf הדפסה. כן? קהל: מהו ד אחוזים ל? 1 SPEAKER: אז השאלה זה מה שהוא ד אחוזים ל? ד אחוזים הוא לints. ד אחוזים ואחוזים אני הם אותו הדבר. קהל: מה ההבדל בין n הקו הנטוי וr הקו הנטוי? 1 SPEAKER: אז השאלה היא מה הבדל בין n והתגובה חריפה r תגובה חריפה? אני חושב r הקו הנטוי is-- קהל: אז r הקו הנטוי רק מרמז חוזר לתחילת השורה בלי באמת הולך קו חדש. אז אם אתה מדפיס r קו נטוי ואתה לחזור לתחילת השורה אז אתה מדפיס יותר דברים, אתה לדרוס הדברים שכבר על [לא ברור]. ואילו, n בעצם הולך לחדש שורה והולכת ל[ לא ברור]. SPEAKER 1: ובכן, כל שאלות אחרות? בסדר. אני הולך להעביר אותה ל דן שימשיך. [מחיאות כפות] דן: כל רייטי. אז אני אדבר על רחב אחר מגוון של רעיונות מהכיתה, כי הם בערך נציג של שבוע שני ו תחילת השבוע שלושה מתחילה את עם ליהוק, וזה רק דרך של טיפול ערך מסוג מסוים כ ערך מסוג אחר. אז אנחנו יכולים לעשות את זה עם תווים ל ints, צף לints, ו משתוקק ארוך להכפיל. כל הדברים הללו יכולים לשמש כדרכים לטיפול בכמה ערך מספרי char מינוס כמו כמה אחר ערך מספרי. אז יש כמה בעיות עם זה, של כמובן, שמגיע כאשר אתה מטיל דברים כמו לצוף ints. אז זה קצת מוזר. יש לנו לצוף שהוא 1.31. אנחנו הכפלנו אותו ב 10,000. ואז אנחנו להדפיס אותו כint. מה עושה פלט זה? פי 10,000 1.31. אז 13,000, הוא שהניחוש? קהל: אני חושב שזה 10,000. דן: אז אני הכפלתו על ידי 10,000 לפני שאני מטיל אותו. קהל: אה. האם לא יהיה אחד 9 וכמה 0 מספרים? דן: אולי יש לך כמה ספרות מוזרות. כל כך צודק, זה פי 1.3 10,000. אז זה 13,000. וweird-- נוסף זה קהל: 13,100. דן: 13,100. תודה לך, רוב. וweirdness-- נוסף זה זה 9,9-- פשוט כי הליהוק הזה בסופו של עיגול כלפי מטה שבו זה לא צריך להיות. כן. קהל: הליהוק קורה אחרי כל דבר אחר? דן: אז בגלל שיש לי את זה בדפוס, זה עושה הכפל הזה לפני שהוא עושה הליהוק הזה. קהל: [לא ברור]. דן: אני חושב שזה יהיה להפיל ראשון, כן, שיהיה 10,000. כל דבר אחר? מגניב. אז זה 13,099. למה זה קורה? חוסר דיוק. צף אינם מושלמים. הם יכולים לייצג רק מספרים ל מספר מסוים של דמויות משמעותיות. אז אם אנחנו להדפיס 8 תאני sig על לצוף זה, אנחנו מקבלים סוג של מספר מחפש מכוער. וזה בגלל ש1.31 לא יכולים במדויק להיות מיוצג על ידי פשוט סמכויות של שתיים במכונה. אז זה סופו של דבר לוקח את הכי קרוב מניח, אשר בסופו להיות קצת נמוך. הגיוני? אישור. עכשיו, עבר הן דרך של שונה עושה הצהרות מותנות שבו כל אכפת לנו הוא משתנה אחד. אז בדוגמא זו בפרט, אנחנו מקבל מספר שלם מהמשתמש. ואז אנחנו מסתכלים על מה הוא מספר שלם ש. יש להניח, שזה מספר בין אחת לארבע. זה מה שאנחנו מבקשים. אז אתה עושה את מתג של השם המשתנה. אז אתה מגדיר את המקרים של אפשרי ערכים זה יכול להיות. אז במקרה אחד, אומר שזה נמוך. ואז אתה שובר לצאת של מצב המתג כך אתה לא להמשיך. בcase-- הבא כך מקרה שני ומקרה לוש-- אם זה מקרה שני זה פשוט יורד למטה כדי את השורה הראשונה של קוד שהיא רואה כעם אותיות שלוש עד שרואה את הפסקה. אז הסיבה שאתה מקבל מקרה אחד ל רק נמוך הדפסה היא כי אני יש לי הפסקה זה כאן. אם אני, למשל, התעלמתי break-- זה אם זרקתי breakaway-- זה זה יהיה להדפיס נמוך, ואז זה היה להדפיס אמצע, ואז זה יהיה לשבור. אז הפסקות הן חלק חשוב של לעבור תנאים ו הם צריכים להיות שם. כל המקרים שאינם נקבעו באופן מפורש מטופלות על ידי ברירת המחדל מקרה במתג וצריך להיות יצוק. קהל: אז 1, 2, 3, ו4 יהיו n? דן: ערכים שn יכול להיות. כן. כן? קהל: לכן, כאשר יש לך כי [לא ברור]? דן: היית להדפיס נמוך, ולאחר מכן זה יהיה להדפיס אמצע, ו אז זה יהיה לשבור. קהל: למה זה להדפיס אמצע אם [לא ברור]? דן: אז כל דבר תחת מקרה לפני הפסקה נופלת תחת. אז מקרה הדפסה אחת היא מקרה מתחת אחד כפי שהוא בהדפסה הבאה. כן? קהל: [לא ברור]? דן: אז המספר הזה הוא רק בפרט ערך שמשתנה זה יכול לקחת, נכון? האם זה הגיוני? כן. קהל: [לא ברור]? דן: כן, מקרה שני היה להדפיס אמצע ואז לשבור. קהל: [לא ברור]? דן: אני חושב שכל? מה סוגי נתונים אחרים אתה יכול לעבור? קהל: אתה יכול לעבור על פני כל סוגי הנתונים. אבל זה רק אומר משהו על תווים וints ודברים כאלה, כי אם אתה עובר על מצביע זה לא ממש הגיוני, מיתוג על עומסים, אם זה אפילו בוא אתה עושה את זה, בגלל נקודה צפה בדיוק, אתה לא היית באמת רוצה לעשות את זה בכל מקרה. אז פחות או יותר, רק ints ו תווים ודברים כאלה. דן: כן, זה כאשר יש לך מפורש ערכים שאתה יודע, אני חושב, יכול להיות כי בורר הוא באמת שימושי. טוב? אישור. היקף הוא הטווח שהוכרז משתנה מרחיב. אז בנתח הקטן הזה של קוד שיש לי, זה יהיה מלא בשגיאות. והסיבה לכך היא שהכרזתי int זה אני במסגרת זו ללולאה. ולאחר מכן אני מנסה להפנות ש אני מחוץ לכי להיקף לולאה. אז בעצם, אתה יכול לחשוב על היקף כמו כל דבר שאתה מצהיר עם בתוך קבוצה של סוגריים מסולסלים רק קיים בתוך סוגריים המסולסלים אלה. ואם אתה מנסה להשתמש במשתנה ש מחוץ לסוגריים המסולסלים האלה, אתם מקבל הודעת שגיאה מהמהדר. כן? קהל: אז זה אחד לא עובד? דן: זה לא עובד, כן. מחרוזות. מחרוזת char *. הם בדיוק אותו הדבר. הם פשוט מצביעים לתווים. וכל חוטים שיש לך צריכים בסופו עם קו נטוי אפס, וזה רק אמנת ג. זה נקרא שליחות קטלנית NULL. וNULL-- ההון N, הון U, הון L, הון L-- זה לא אותו הדבר כמו שליחות קטלנית NULL. זה הוא מצביע. זוהי דמות. הם שונים במהותם. זוכר את זה. זה יהיה על החידון, כנראה. אני לא ראיתי את החידון. כן? קהל: אז NULL הוא, למשל, המצביע? דן: כן. קהל: מה [לא ברור] עושה? דן: אם, לומר, malloc נקרא כאשר אתה אין לי מספיק זיכרון כדי לקבל מה גודל שאתה מבקש, malloc יחזיר NULL. זה, בעצם, בכל פעם שפונקציה היא אמור לחזור מצביע, אתה צריך לבדוק נגד NULL כי NULL הוא good-- די זה, פחות או יותר, את ערך האשפה. זה אפס ככל מצביעים ללכת. כל פעם שאתה קורא לפונקציה, המחזיר את מצביע. אתה הולך רוצה לבדוק כדי להיות בטוח שהמצביע שאינו NULL בגלל NULL הוא נפוץ מאוד. זה סוג של חזרה אשפה. אז אם משהו לא הלך ימינה, רק לחזור NULL במקום. קהל: [לא ברור]? דן: כן, וזה זה. קהל: [לא ברור]? דן: איות זה כמו זה. זה שליחות קטלנית NULL. זה אותיות קטנות N-U-L-L אם אתה איות זה. קהל: ואני פשוט הלכתי בחזרה ובדק את זה. ואם אתה מנסה לשים נקודה צפה ערך למתג, זה יהיה לצעוק עליך אומר, הצהרה דורשת ביטוי מסוג מספר שלם. דן: יש לך ללכת. אבל כן, מה הייתה השאלה שוב? קהל: [לא ברור]? דן: אז הון N, הון U, הון L, L הון הוא דבר ג בפועל. זה מצביע NULL ויהיה להיות מטופלים רק ככזה. אתה לעולם לא לנסות ולאיית אופי NULL ותראה את כל דרך אחרת מאשר זו. כן? קהל: אז חוזר לchar מקסימום או משהו בהערות, היית זה לגלם את אותו התפקיד כ[ לא ברור]? קהל: אז אתה מתכוון חוזר מקסימום char מgetchar, או מה שזה לא? קהל: כן. קהל: כן, כל כך הכללי טווח לכל הדברים האלה הם ערכי זקיף. אז כאילו הוא חוזר מקסימום int מGetInt ומקסימום char מgetchar, זה אמור להיות כמו, בסדר, אם הדברים האלה חוזרים אלינו, משהו השתבש. עבור מצביעים, אנחנו רק במקרה יש לי ערך זקיף זה שכולם מסכים עם. וזה הדבר שתחזור כאשר הדברים משתבשים. אז מקסימום char הוא מה שאנו משתמשים כדי לייצג משהו כמו NULL או getchar. קהל: אז אם אתה בודק getchar, אתה יכול פשוט לשים NULL? האם זה עושה את הבדל? דן: אתה לא יכול פשוט לבדוק NULL. היית צריך לבדוק מקסימום char כי ערך החזרה מהפונקציה הוא אופי לא מצביע. כן? קהל: שאלה זו שואלת לאורך המחרוזת. האם זה כולל את אופי NULL? דן: מס ' וזה בעצם איך אורך מחרוזת יודע להפסיק כי הוא עובר המערך שלך של דמויות עד הוא רואה את דמות NULL. ואז זה כמו, כל נכון, אני סיימתי. קהל: [לא ברור] חמש? דן: שלום יהיה חמש. כן. אז מערכים הם רציפים בלוקים של זיכרון. יש להם גישה מיידית באומרו שמו של המערך ולאחר מכן, במתולתל פלטה, מה מדד שאתה רוצה ללכת ל, הם צמודים מאפס באמצעות האורך של המערך מינוס 1. והם הוכרזו על ידי הסוג של דבר שאתה אחסון ב מערך, את שמו של המערך, ולאחר מכן מה הגודל הוא של מערך ש. אז זה מערך תווים של אורך שש שיש לו ערכים אלה. כן? קהל: [לא ברור]? דן: כן. קהל: [לא ברור]? דן: אם יש לך מה שקורה לתוך המערך עשה כבר. אז אתה יכול לציין זאת במקום כ, למשל, char, מה שמו שלך מערך הוא, סוגריים ריקים שווים מתולתל לייצב פסיק L H פסיק E פסיק פסיק L O פסיק אופי NULL וסד מתולתל. שגם יעבוד כהצהרה. קהל: [לא ברור]? דן: אז אתה צריך שיהיה לי הגודל כבר עשה. קהל: [לא ברור]? דן: כן. כל רייטי. טיעוני שורת הפקודה הם דרך של מקבל קלט מהמשתמש כ טיעונים לעיקריים. ראשי לוקח שני טיעונים. מספר הטיעונים שהוא להיות עבר לאורך שורת הפקודה ו וקטור מחרוזת או מערך מחרוזות של כל הטענות. אז אם אני, למשל, נקרא פונקציה כמו נקודה מתוך מרחב 1, 2 חלל, שלוש, argc יהיה 4. וargv 0 יהיו נקודה החוצה. Argv1 יהיה 1. argv2 יהיה 2 argv3 יהיה 3, במקרה מיוחד זה. כן? קהל: [לא ברור]? דן: האלמנט האחרון במערך כי המערך הוא argc אורך בתוספת אחד מARGB, האלמנט האחרון הוא מצביע NULL. זה argc בתוספת 1. אז במקרה שאני רק אמרתי, זה יהיה argv 0 הוא נקודה החוצה. argv 1 הוא 1 argv2 הוא 2 argv 3 הוא 3. 4 argv, שהוא אחד גדול מ argc יהיה NULL. וזה מצביע NULL. כן. וזה בגלל שמחרוזת היא כוכב char הוא מצביע. אז זה חייב להיות אותו הסוג. כן? קהל: שתי שאלות. אז אחת, מה ההבדל בין GetString זה ואחר מסוג אחד במנוע המשתמש? ושני, הוא זה מאוחסן בתוך הזיכרון האחרון שלך? אז כמו, היית GetString להיות [לא ברור]? דן: איפה זה מאוחסן? אני לא יודע איפה הוא מאוחסן. קהל: אז, בעצם, אתה יודע איך כל לתפקד אתה קורא זה טיעונים מאוחסנים במחסנית? אז argc וargv הם טיעונים לעיקריים והם בערימה, או באמת בדיוק מעל מה שאתה חושב כ תחילת המחסנית. מה היה חלק האחר של השאלה? קהל: אז מה [לא ברור]? דן: כן, זה רק בדרך שונה לקבל קלט מהמשתמש. מעט יותר יעיל וזה אחד זה handier לתסריטים, כי אתה רק יכול לעבור טיעונים לעיקריים שלך פונקציה ולא אצטרך לחכות עבור משתמשים אם אין לך כל משתמשים. קהל: וכן, תקבל מחרוזות יהיה [לא ברור]. זה יהיה לאחסן את הדברים שאתה צריך. דן: כן? קהל: [לא ברור]? דן: כן, argv 0 תמיד כולל נקודה לקצץ בקריאה לפונקציה. כן? קהל: [לא ברור]? דן: כן, כל אחד מהטיעונים הם הסתיים בתו NULL כי הם הן מחרוזות. קהל: [לא ברור]? דן: כן, argc argv הוא מצביע NULL. קהל: [לא ברור]? דן: אה, כן. כן, מצטער. קהל: אז [לא ברור]? דן: אז השאלה היא אם היה לך נקודת שורת הפקודה לקצץ נקודה 1 מ, 2, היית מספר שורת הפקודה טיעונים יהיו שניים או האם זה יהיה שלושה? קהל: אני חושב שזה לא ממש משנה. אני נוטה לומר, הו, אתה לא עברת כל טיעוני שורת הפקודה בעת, כמובן, שאתה קראת לפונקציה. אז אני נוטה שלא לכלול קולי פונקציה משורת הפקודה טיעונים למרות שזה כלול בargv. דן: אבל אם זה היה על test-- yeah-- וגם אם אתה אומר משהו כמו argc שווה 3, אתה במעמד בטוח. כן? קהל: [לא ברור]? דן: אני חושב שאם במקום לקרוא את זה בסוגריים argv argc ומחרוזת אבל שמרתי אותם הסוגים ורק בשם להם משהו שונה כמו וb, היה זה עדיין עובד? וזה עדיין עובד, היית פשוט- במקום להשתמש argc-- אתה מעוניין להשתמש וb. כן? קהל: [לא ברור]? דן: אז השאלה היא GetString היא הולך לחנות זיכרון בערימה בגלל GetString הוא char *. הוא מאחסן זיכרון בערימה כי זה קורא עכשיו malloc בתוך בפועל יישום GetString. אישור, ממשיך הלאה. אבטחה. אז כדי להיות בטוח באמת, אתה מסתמך על שום אחד ואתה מאפשר שום גישה אחת לכל המידע שלך, וזו הסיבה ש כולם בונים מכונות שלהם, מערכות ההפעלה שלהם, את כולם תוכניות מהתחלה, וכמובן לא מתחבר לכל מכונות אחרות באמצעות האינטרנט. אז מחשבים הם חסרי ביטחון. הם באמת. אנחנו צריכים לסמוך על אנשים אחרים. ואת הרעיון של ביטחון הוא שאתה מנסה להגביל את כמות אמון שאתה צריך. ואחד האמצעים אתה עושה את זה הוא באמצעות הצפנה. קריפטוגרפיה היא, במהותו, יש לנו סודות. לפעמים אנחנו צריכים לעבור את הסודות שלנו לאורך דרך, למשל, באינטרנט או דברים אחרים. ואנחנו לא רוצים שאנשים לדעת את הסודות האלה. אז אנו מצפינים את הסודות שלנו לדרך שאנחנו מקווים שאף אחד לא יכול להבין. אז אנחנו used-- באמצעות מהלך זה class-- דברים כמו צופן קיסר ו [לא ברור], אשר שניהם מאוד, מאוד דרכים בטוחות של הצפנת דברים. הם קל להבין את מה שהם הם ומה הם הסודות שלך. העולם האמיתי משתמש בהרבה יותר סכימות הצפנה מסובכות. ואנחנו לא תקבלו לתוך הרבה יותר מזה. ניפוי שגיאות. GDB הוא הטוב ביותר. אני הולך להדגיש את זה שוב. השתמש GDB כל הזמן בכל זמן יש לך בעיה. הפקודות שימושיות בGDB הן לשבור, שבו אתה עובר בין קו מספר, שם פונקציה, בעצם שבו בקוד שלך שאתה רוצה להפסיק, ולהיות מסוגל לקחת את השליטה. ההדפסה לוקחת משתנה ומדפיסה כל מה שמשתנה זה הוא שב נקודה בביצוע שלך. הבא נע הביצוע שלך לאורך צעד אחד. וצעד ​​צעדים בתוך פונקציה בביצוע שלך. דברים אחרים מנוהלים, וכך אתה בעצם להפעיל הקוד שלך. המשך לוקח את כל הצעדים דרושים כדי להגיע לנקודת האיזון הבאה. ויש הרבה, הרבה אחרים. תראה אותם. הם נהדרים. כן? קהל: [לא ברור]? דן: כן, וזה הבאגים. אז הבאגים היא תכנית ה מאפשר לך לאתר באגים בתכנית שלך. זה לא תכנית שמוצאת באגים עבור אתה, למרות שזה יהיה נהדר. ואחרון בשבילי הוא חיפוש. אז הסוגים של חיפוש שדיברנו על בכיתה זו היא חיפוש ליניארי, וזה רק כי אתה מסתכל דרך כל אחד אלמנט של מרחב החיפוש, אחד אלמנט בכל פעם, עד שתמצא את מה ש אתה מחפש או עד שתגיע הסוף של שטח החיפוש שלך שבו מצביע שאתה אומר שאתה לא יכול למצוא האלמנט שאתה מחפש. וזה לוקח זמן, במקרה הטוב בלתי פוסק, אשר הוא 0 של 1 וליניארי הגרוע ביותר זמן, שהוא 0 של n. חיפוש בינארי, אשר צריך אלמנטים שפלים. אתה הולך לאמצע של האלמנטים שלך, לראות אם האלמנט שאתה מחפש הוא גדול יותר או קטן יותר מהאלמנט שאתה באמצע. זה שזה גדול יותר, אתה אומר שהחלק התחתון החיפוש שלך חלל הוא שלך מיקום נוכחי, באמצע, ותפעיל מחדש את התהליך. אם זה קטן יותר, אתה מסתכל אומר שthe-- כן, מה קורה? קהל: [לא ברור]? דן: כן. כל סוג של מין שכבר לימד ב הכיתה היא משחק הוגן עבור הבדיקה. [שחוק] דן: והעובדה שלא היה לך לעשות את זה עבור קבוצת בעיה, שזה הוגן משחק לבדיקה. קהל: אנחנו יכולים ללכת על זה איך to-- דן: זה כבר לא יהיה יותר מ. SPEAKER 2: הקוד בפועל עבור [לא ברור] הוא על study.cs50.net. אז אם אתה מסתכל על הבעיה בפועל בדף מין מיזוג של study.cs50.net, יש קוד ליישום למזג סוג. אז אתה לא צריך ליישם זאת בעצמך הלילה. אבל לוודא שאתה מבין את זה ולא לא רק שיינון. קהל: [לא ברור]? SPEAKER 2: דף סוג המיזוג על study.cs50.net, יש בפועל בעיה שאם אתה לוחץ דרך בעיה, ממש בסוף יש פתרון, המהווה את המיזוג יישום סוג. אבל לוודא שאתה מבין את זה ולא רק שיינון או העתקה אותו. קהל: וחוקי לחלוטין בעיה לבחינה תהיה משהו כמו הנה רשימה. מה רשימה זו נראית כמו אחרי צעד אחד מסוג בחירות או סוג הכנסה או משהו כזה. איטרציה מלאה אחת של הרשימה. אז גם אם אתה לא בסופו של דבר צורך ל קוד לזה, אתה צריך להבין את זה מספיק כדי לדעת איך זה הולך לשינוי מערך זה. דן: זהו זה בשבילי. [מחיאות כפות] לוקאס: היי לכולם. השם שלי הוא לוקאס. אני הולך לדבר על רקורסיה, כל מיני שלמדנו, ו קצת מכל המצביעים. בסדר? אז קודם כל, רקורסיה. מה זה אומר להגיד ש פונקציה רקורסיבית היא? קהל: השיחות עצמו. לוקאס: אישור, קורא לעצמו, כן. אז כמו התמונה הזאת, למשל. זה כמו התמונה בתוך של תמונה וכן הלאה. כך למשל, אתה יכול have-- כדן שדבר על החיפוש בינארי. דרך אחת שבי החיפוש בינארי הוא רקורסיבית היא העובדה שאתה מנסה למצוא מספר. אז אתה הולך לאמצע. ואז אתה בודק אם המספרים שם בשמאל ובימין. ואז אם אתה מוצא את המספר הוא הולך להיות בצד השמאל, שזה אותו הדבר דבר עושה את החיפוש שוב, אבל רק בצד השמאל של הרשימה. אז ככה זה נשמע כמו שזה רקורסיבית. אז בגלל זה אתם צריכים רקורסיבית פתרון לסוג מיזוג. אוקיי, אז הנה דוגמא. אז בואו נגיד שאני רוצה לבחור כל המספרים מ -1 עד n. אני יכול להבין שהסכום של n מספר הוא n בתוספת n מינוס 1 עד 1. אבל אז, אם אני מסתכל על n מינוס 1 ועוד n מינוס 2 פלוס 1, כי אותו הדבר דבר מספרי סיכום עד n מינוס 1. אז אני יכול להגיד את סכום סכום השווה שווה n בתוספת הסכום של n מינוס 1. האם זה הגיוני? והייתי גם משהו אחר נקרא מקרה הבסיס, אשר הוא ש הסכום של המספרים עד לאפס יהיה אפס. אז ברגע שאני מגיע למספר אפס, אני מפסיק לספור. האם זה הגיוני? אז הנה דוגמא לאופן ש אני יכול ליישם את זה. אז יש לי פונקציה זו בכמה. זה לוקח n מספר שלם. אז הנה אני בודק קודם אם n הוא פחות או שווה לאפס. אז אם זה פחות או שווה לאפס, אני לחזור אפס, שהוא מקרה הבסיס שלנו. אחרת, אני יכול רק לחזור n בתוספת הסכום של המספרים מ אחד למינוס n אחד. הגיוני? אישור. אז הנה מה שזה נראה. יש לך סכום של 2 שווים 2 בתוספת הסכום של 1. וחלק מ1 הוא 1 ועוד סכום של 0, אשר הוא 0. הגיוני? אז אם אנחנו מסתכל על הערימה שלך תכנית, זה מה שזה נראה. ראשית, יש לנו את הפונקציה העיקרית. ולאחר מכן את הפונקציה העיקרית נקרא סכום 2. ולאחר מכן הסכום 2 הולך להגיד, אה, סכום 2 שווים 2 בתוספת הסכום של אחד. אז אני מוסיף סכום של 1 עד הערימה. והסכום של 1 הולך לקרוא סכום של 0, שהוא גם הולך להוסיף לערימה. ולאחר מכן כל אחד מאלה אלה ש על גבי זו יש לחזור לפני האחרים יכולים להמשיך. כך למשל, כאן, סכום של 0, ראשון, הוא הולך לחזור 0. ולאחר מכן לבחור סכום של 1. לאחר מכן הסכום של 1 הולך לחזור 1 לסכום של 2. ולבסוף, הסכום של 2 הולך לחזור 3 לעיקריים. האם זה הגיוני? זה באמת חשוב להבין כיצד המחסנית עובדת ולנסות לראות אם זה הגיוני. אוקיי, אז מיון. אז למה מיון חשוב, קודם כל? מה אכפת לנו? כל אחד? תן לי דוגמא? כן? קהל: [לא ברור]. לוקאס: כן, על אישור. אז אתה יכול לחפש בצורה יעילה יותר. זו דרך טובה. כך, למשל, יש לנו הרבה דברים, למעשה, בחיינו ש מסודרים. לדוגמא, מילונים. זה מאוד חשוב להיות כל מילים באיזשהו סדר ש יכול לגשת בקלות. אז זה מה שהוא אומר. אתה יכול לחפש בצורה יעילה יותר. תחשוב על כמה קשה יהיה לקבל מילון שבו המילים הן ב בסדר אקראי. אתה צריך להסתכל על, פחות או יותר, כל מילה ומילה עד שתמצאו את מילה שאתה מחפש. אם אתה גם משתמש בפייסבוק, כאשר אתה מסתכל על החברים שלך, אתה הולך לראות שפייסבוק הכניס אותך חבר קרוב של על גבי אלה כי אתה לא מדבר לכל כך הרבה. אם אתה רוצה ללכת את כל הדרך עד לתחתית רשימת החברים שלך, אתה הולך לראות אנשים שאתה כנראה אפילו לא זכור כי אתם חברים עם. וזה משום שמיני פייסבוק החברים שלך מבוסס על איך הקרבה שלך אליהם. אז ארגון הנתונים. גם פוקימון. אז אתה רואה שכל הפוקימונים יש לי מספרים. וזה כמו קל דרך של גישה לנתונים. קהל: גישה פוקימון. לוקאס: כן. קהל: [לא ברור]. לוקאס: כן. אוקיי, אז מיון בחירה. מיון בחירה הולך לבחור הערך לא ממוינים הקטן ביותר של רשימה כל זמן בכל איטרציה. זה כמו סוג של מהסוג שאתה עושה בראש שלך כאשר אתה מנסה למיין את רשימה ביד. בעיקרון, כל מה שאתה צריך לעשות זה אתה מסתכל למספר הקטן ביותר. אתה שם אותו ברשימה הממוינת. ואז אתה מחפש הבא המספר הקטן ביותר. ואז אתה ממשיך לעשות את ושכן הלאה. אז מיון בחירה הוא בעצם אתה בחר בכל פעם שהקטנה ביותר ערך לא ממוינים. שים בסוף מסודרים חלק מהרשימה. ולהמשיך לעשות את זה. אז בואו לראות במהירות את מה ש זה נראה כמו. אז הנה מסודרים ורשימה לא ממוינת. אז למסודר של רשימה, זה בתחילה ריק. ולאחר מכן אני הולך לבחור המספר הקטן ביותר כאן, שהוא 2. אז אני מקבל את המספר 2 ושמתי בחלק הקדמי של הרשימה. ואז אני מסתכל לצד הקטן ביותר אלמנט, שהוא 3. אז שמתי את זה בסוף של הרשימה הממוינת. ואז אני ממשיך לעשות את זה. אני מוצא את 4 ולשים אותו בסוף. מצא את 5 ולשים אותו בסוף. ונראה כיצד כל אותן הפעמים ש אני אומר לשים אותו בסוף הוא, בעצם, החלפת שני ערכים. בסדר? ולאחר מכן עבר אחד, אתה פשוט יש לי אלמנט אחד יותר. אז זה כבר מסודרים. אוקיי, אז סוג ההכנסה. סוג ההכנסה שאתה הולך יש לי גם דבר זה של שמסודר ו רשימה לא ממוינת. הדבר היחיד הוא שכל פעם ש אתה מוסיף אלמנט למסודר רשימה, אתה פשוט לבחור את האלמנט ש הוא מול הרשימה לא ממוינת. ואז אתה הולך למצוא את מה ש עמדה שהוא צריכה להיות במיון חלק מהרשימה. בואו לראות מה זה כל כך זה הגיוני יותר. אז בהתחלה, למשל, אני מנסה להכניס את המספר שלושה ב חלק ממוין של הרשימה. אז הרשימה אין שום דבר. אז אני פשוט יכול לשים את המספר 3. עכשיו, אני רוצה להוסיף המספר 5 ל החלק ממוין של הרשימה. אז אני מסתכל על המספר 5. אני שם לב שזה גדול מ -3. אז אני יודע שזה צריך להיות אחרי 3. אז שמתי את 3 ו -5. אז אני רוצה להכניס את המספר 2. אני שם לב שהמספר 2 הוא למעשה תחזיק מעמד אז גם 3 ו -5. אז אני באמת צריך לשים אותו כל דרך בתחילתה של הרשימה. אז אני צריך, סוג של, להעביר את כל אלמנטים ברשימה הממוינת כך שאני יכול להפוך את המקום למספר 2. ואז אני רואה את המספר 6. אני רואה שזה צריך להיות אחרי 5. אז שמתי אותו שם. ולבסוף, אני מסתכל על המספר 4. ואני שם לב שהוא צריך להיות בין 3 ל 5. ואז אני שם אותו שם ומשמרת כל האלמנטים האחרים. הגיוני? מיין בועה. אז מיון בועות הוא בעצם מה שאתה הולך do-- אנחנו קוראים לזה בועה סוג בגלל שאתה עובר list-- זה בעצם יותר טוב אם אני רק מראה אתה אוהב את זה- ואתה הולך להשוות מספרים סמוכים. ואתה הולך להחליפם עמדות אם הם לא בסדר הנכון. אז בעצם, מה שקורה ל לקרות הוא כאן, למשל, יש לך 8 ו -6. אתה יודע שכדי ממוין יהיה למעשה להיות 6 ו -5, נכון? אז אתה הולך להחליף את הצווים. ואז אני רואה 8 ו -4 כאן. ואני עושה את אותו דבר. אני להחליף שוב. ולבסוף, 2 ו -8. אני גם להחליף אותם. זה נקרא בועת מיין כי אחרי כל אחד מחזרות אלה, למעשה, המספר הגדול ביותר ברשימה מקבל את כל בדרך לסוף הרשימה. האם זה הגיוני? כי זה שומר החלפתו ולהעביר אותו לצד ימין. אוקיי, אז זה הוא החזרה השניה. זה יהיה אותו הדבר. אני אעשה החלפה אחד ו אז האחרון. אני שאין החלפות והרשימה ממוינת. אז במיון בועות, אנו בעצם לשמור עובר על הרשימה והחלפה דברים עד שאני שם לב שאני לא עשיתי כל עסקות החלף עושה איטרציה ש, ש משמעות הדבר היא שהרשימה כבר מסודרים. הגיוני? בואו נדבר קצת על זמן ריצה. אז אתם זוכרים גדולים O, אומגה, ותטא? כן? אישור, מה הוא O הגדול, קודם כל? קהל: [לא ברור]. לוקאס: כן, זה נקרא מקרה הגרוע ביותר זמן ריצה, שרק אומר שזה כמה אתה מצפה תכנית לקחת לרוץ. כמו, במונחי of-- בn case-- זה. מספר האלמנטים ב רשימה במקרה הגרוע ביותר. כמו, במקרה הגרוע ביותר האפשרי. אז למיון בועות, למשל, יש לנו O הגדול של כיכר n. למה יש לנו את זה? למה היא בועה מיין כיכר n O גדולה? קהל: [לא ברור]. לוקאס: כן, אז במקרה הגרוע ביותר יהיה שאני אצטרך לעשות חזרות n. אז כל אחד מהחזרות הולך להביא את האלמנט הגדול ביותר עד הסוף של הרשימה. אז במקרה הגרוע ביותר הוא שיש לי כדי לעשות את זה דבר n פעמים. ועבור כל אחד מאותם זמנים, יש לי ל לעשות חילופי n כי יש לי כדי להשוות כל שני אלמנטים. אז זה למה זה n בריבוע כי זה n פעמים n. לאחר מכן, מיון בחירה הוא גם n מרובע כי, לכל איטרציה, יש לי ל מסתכל על כל אלמנט ברשימה. ולאחר מכן למצוא את הקטן ביותר, מה שאומר שיש לי ל להסתכל דרך אלמנטי n. ואני צריך לעשות את זה פעמים n כי אני חייב לבחור את כל אלמנטי n. סוג הכנסה הוא גם n מרובע כי במקרה הגרוע ביותר יהיה להיות, אחד, אני צריך להכניס מספרי n, נכון? אז אני כבר יודע שאני הולך יש חזרות n. אבל לכל אחד מהמספרים האלה, אם היה לי להסתכל על כל המספרים ב הרשימה הממוינת ולשים אותו כל הדרך בחלק הקדמי, שיהיה n מרובע כי זה יהיה n פעמים n שוב. הגיוני? מה לגבי אומגה? קהל: [לא ברור]. לוקאס: זה מקרה הטוב. אז זה כאילו, בהרבה פעמים ל מיון, התרחיש הטוב ביותר הוא כאשר הרשימה כבר מסודרים. אז לא באמת יש לך לעשות שום דבר. מיין בועה יש הטוב ביותר תרחיש מקרה של n. האם אתם יודעים למה? קהל: [לא ברור]. לוקאס: כן, אם לך לעקוב אחר אם הייתה לי מנת נתונים כל עסקות החלף או לא, אם יש לך משהו כמו מוגדר נכון אם הייתה איטרציה, אם רשימה כבר ממוינת, בעצם, מה שהולך לקרות הוא שאני הולך אנסה להחליף כל שני אלמנטים סמוכים. אני הולך לראות את זה אין החלפות. ואני פשוט לחזור מייד. אז זה אומר שאני פשוט חייב עובר על רשימת פעם אחת. אז זה n כי אני נראה בn אלמנטים. למה בחירת סוג n מרובע? כן, גם אם הרשימה ממוינת, ל כל איטרציה של מיון בחירה, אני צריך לבחור את אלמנט המינימום. אז זה אומר שיש לי אותי להסתכל בכל האלמנטים בממוינים רשימה ולמצוא את המינימום עבור כל איטרציה. האם זה הגיוני? וחרב הכנסה היא n כי ב מקרה שאני מנסה להכניס את מספרים ואת כל המספרים, כש אנסה להכניס אותם, אני רואה שהם נמצא במיקום הנכון. אני לא צריך ללכת לבדוק את כל אחר מספרים ברשימה לא ממוינת. אז בגלל זה זה יהיה n. הגיוני? ומה תטא? קהל: [לא ברור]. לוקאס: מה, מצטער? תגיד את זה שוב. קהל: [לא ברור]. לוקאס: בדיוק. אז אתה יכול לראות שבחירה רק מאוחסן במיזוג יש סוג thetas. וזה בגלל שיש לך רק תטא אם שני O ביג והאומגה הם אותו הדבר. אישור. ולבסוף, למזג סוג שהוא בn יומן. ולאחר מכן, כפי שדן אמר, מיזוג סוג הוא סוג של כמו באותו אופן ש אתה עושה את החיפוש בינארי. כך שאתה מקבל את הרשימה. ואתה הולך לחתוך בחצי. ואז אתה חותך אותם בחצי קטנים יותר. ואז אתה למזג אותם. אתם זוכרים את זה, נכון? אישור, כפי שהוא אמר. אישור, מצביעים. אז מה הוא מצביע? קהל: [לא ברור]. לוקאס: כתובת. אישור. אני יודע שדוד מציג חבורה של קטעי וידאו של בינקי ודברים מצביעים אחד את השני. אבל אני אוהב לחשוב על מצביעים רק ככתובת. אז זה משתנה כי הוא הולך כדי לאחסן את כתובת. אז זה רק משתנה המיוחד הזה שאורכו ארבעה בתים. זכור, מצביע שלכל דבר הוא תמיד ארבעה בתים ארוכים ל32 סיביות שלנו מכונה כל כך במקרה של המכשיר. ורק יש לו את המיקום של משתנה בתוכו. אוקיי, אז יש את הזיכרון הזה, בעצם. אז כל בלוק של זיכרון למעשה יש תווית, המהווה את כתובתו של זיכרון slotty. אז זה אומר שאני יכול להיות הצבעה מצביע כל אחת מהכתובות הללו. אז הסיבה לכך שאנו משתמשים במצביעים היא אם אני צריך לזכור את המיקום שמשתנה מסוים הוא זיכרון. ואתם זוכרים שאחד מאותם מקרים היו אם יש לי פונקציה אם יש לי בעצם רוצה ש החלפה עבור ריאל, אני באמת צריך לשלוח מצביע. לא משתנה. האם אתם זוכרים את זה? Between-- ההבדל מה הוא שם? קורא על ידי ערך וקוראים על ידי התייחסות, נכון? אישור, כן. אז קורא על ידי ערך. כאשר אתה פשוט לשלוח משתנה ל לתפקד אתה פשוט שולח ערך. אז אתה בעצם שולח עותק של המשתנה. והתכנית שלך לא אכפת על אם אותו משתנה בעצם יוצר עותק. וקורא על ידי התייחסות אומרת ש אני בעצם שליחת עותק של מצביע למשתנה ש. אז זה אומר שאני שולח מיקומו של משתנה ש. אז לחוש שיש לי את מיקומו של משתנה, כאשר אני קורא את הפונקציה עם מצביעים, אני מסוגל למעשה לשנות את הנתונים שהיו בראשי. הגיוני? למרות, המצביע הוא עותק, מצביע עדיין יש לו את הכתובת האמיתית של משתנה שאני רוצה לשנות. הגיוני? אז יצירת מצביעים. זכור, המצביע תמיד יש לי הסוג שהוא מצביע וללאחר מכן כוכב. ולאחר מכן אתה מכניס את השם. אז לזכור כי בכל פעם שיש לך כל מה שכוכב, זה כמו מצביע שכל מה שמשתנה הקלד שהיה לך. אז הנה בכוכב, למשל, זה מצביע ומספר שלם. ולאחר מכן כוכב char הוא מצביע כוכב char וכן הלאה. כן? קהל: מה אם יש לנו מצביע לn לככב x. אני יודע שיוצר מצביע לx. האם זה גם להכריז x מספר שלם? לוקאס: אוקיי, אז כשאתה אומר x כוכב n, אתה לא יוצר את מצביע ל x משתנה. אתה יוצר מצביע בשם x. קהל: [לא ברור]. לוקאס: אז כשאני אומר x כוכב n, אני אומר, היי, בזיכרון, אני הולך לקבל אחת משלוש תיבות אלה. ואני הולך להגיד את זה כי הולך להיות x, שהוא הולך להיות מצביע. ומשהו מעניין על מצביעים הוא שאנו אומרים שיש להם 4 בתים עבור מכונה 32 סיביות. והסיבה לכך היא משום ש 4 בתים 32 סיביות. ומכונות שהם 64 סיביות למעשה יש לי כתובות מצביעים כי הם ארוכים 64 סיביות. אז זה רק אומר שהגודל של כתובות במכונה היא שונות. אז הפניה וביטול הפניה. ישנם שני מפעילים ש אתם צריכים לזכור. הראשון הוא אמפרסנד. השני הוא כוכב. אל תתבלבלו על ידי זה כוכב וזה כוכב בגלל לזכור כי, ב מקרה זה, יש לך כוכב n. זה כמו כל דבר ביחד. אין כוכב מרחב n. אז זה אומר שזה הסוג. זכור, שכאשר יש לך הכוכב משתנה, אתה מדבר על הסוג. כאשר יש לך רק כוכב ולאחר מכן שם המשתנה, זה אומר ש אתה ביטול הפניה למבנה המצביע, ש משמעות הדבר היא שאתה מסתכל על מצביע, למצוא את הכתובת זה מצביע, הולך לכתובת זו, ומסתכל על כל פעם ש יש לך שם. אז אני אומר לסטודנטים שלי שכאשר יש לך כוכב, אתה צריך לחשוב שזה הקיצור של תוכן של. אז אם יש לך מצביע ולך לעשות מצביע כוכב, זה תוכן של המצביע. אז אתה הולך לכל מה שהוא מצביע על ומסתכל על התוכן הקבוע. והאמפרסנד הוא זהה דבר ככתובת של. אז אם יש לי משתנה a-- כמו, בואו אומר שעשיתי int שווה 3-- אם אני רוצה למצוא את הכתובת של ש משתנה זיכרון, אני יכול פשוט לעשות אמפרסנד. אז זה כתובת של. הגיוני? אז הנה דוגמא. זה חסר ג ב וint int. אז int שווה 3 אמצעים ש אני הולך ללכת לזיכרון. ואני הולך למצוא חריץ ולשים את המספר 3 כאן. ולאחר מכן int b שווה 4. אני הולך לעשות את אותו הדבר. עבור לזיכרון והכניס את מספר 4 באחת מהתיבות. וint שווה 5. מצא את קופסא אחרת ולשים את מספר 5. אז מה הקו הזה עושה את? pa כוכב n שווה אמפרסנד. אז קודם כל, n pa כוכבים. מה הוא עושה? קהל: [לא ברור]. לוקאס: כן, אז n pa כוכב, ראשון, מצהיר מצביע נקרא הרשות הפלסטינית. ואז זה הקצאת הערך של מצביע שכדי להיות הכתובת של. אז אמפרסנד. ואז, אם אני עושה את PB כוכב, מה PB כוכב? אה, סליחה. זה גם חסר. PB כוכב n. אני מתכוון מחשב כוכב. אני כל כך מצטער. זה אותו הדבר. אבל עכשיו אני טוב ar יצירת מצביע לB ולאחר מכן מצביע לג. כן? קהל: [לא ברור]? לוקאס: כן. אז אם אתה הולך לזיכרון ושאתה הולך ל התיבה שהיא ציין לרשות, אתה באמת הולך לראות את כתובת של. בסדר? כן? קהל: [לא ברור]? לוקאס: כן, מצביע הוא כתובת. לעולם אל תשכח את זה. זה כמו חשוב ביותר חלק על מצביעים. יש אחסון וכתובת לכמה משתנה. כל דבר אחר? יש עוד שאלות? אישור. אז מצביעים ומערכים. זכור כי כאשר אני עושה int מערך 3, בעצם, מה שאני עושה הוא אני, סוג של, שהכריז במצביע. אז מערך הוא כמו סוג של מצביע במקום מסוים בזיכרון שבו אני הוקצה לו שלושה חריצים למספרים שלמים. האם זה הגיוני? לכן, כאשר אני עושה int מערך 3, מה שאני עושה, בעצם, הוא יצירת שלוש חריצים בזיכרון. אז אני פשוט מוצא את שלושה חריצים בזיכרון. אז אם אני עושה, אז, מערך כוכבים, זה בעצם אומר את התוכן של מערך, מה שאומר שאני מוחק את המצביע, אני הולך לשם, שהיה מצביע ל, ואני שם את המספר אחד. ולאחר מכן, אם אני עושה את מערך כוכבים בתוספת 1, זה אותו הדבר כמו לעשות מערך בסוגריים אחד, שרק אומר שאני הולך ל המקום שהיא מצביעה על. ולאחר מכן עושה בתוספת 1 לי לשנות תנוחה אחת. אז אני הולך לעמדה זו, למעשה, ולשים את המספר שתיים. ואז, סוף סוף, כשאני עושה מערך בתוספת 2, אני הולך למקום שבי ההצבעה של המערך ב. ולאחר מכן אני עובר לגושי זיכרון. ואז אני שם את המספר שלוש כאן. כן? קהל: מערך אז כוכב הוא פשוט אומר הנקודה הראשונה. ואתה יכול להוסיף 1, רק בגלל ש אנחנו רק באמת התייחסות שהכתובת הראשונה. לוקאס: כן. למה אנחנו, למשל, אומרים מערך 0, מערך 1, ומערך 2? אני אומר, למה אתה עושה 0, 1, 2, 3 במקום 1, 2, 3? אחת הסיבות הוא, אחד, מחשב מתכנתים מעדיפים להתחיל לספור מ -0. שני הוא כי כאשר אתה עושה מערך 0, זה אותו הדבר כמו לעשות מערך בתוספת 0, מה שאומר שאני הולך ל עמדה ש, ואני לא לדלג על כל גושי זיכרון. אז אני לא להזיז את כל בלוקי זיכרון. כן? קהל: [לא ברור]? לוקאס: אז היא שואלת מה היא ההבדל בין לעשות זה או עושה malloc. אחד ההבדלים הוא ש int מערך 3 הוא יצירת מערך על המחסנית. וכשאני עושה malloc, זה יוצר על הערימה. האם זה הגיוני? אז איך malloc באמת עובד? אז למה אנחנו צריכים אפילו להשתמש malloc? סוג מהדר שלך של דמויות מתוך כל המשתנים שהוכרזו. והוא יוצר מרחב לכל שלהם בערימה. אז כל המשתנים שלך הולכים להיות במקום כלשהו בערימה. אז הנה הוא משתני הסביבה. אז בעצם, מקום למשתנים אלה בזיכרון מוקצה ב לקמפל זמן. אז זה אומר שיש לו המחשב שלך לדעת את כל המשתנים הללו לפני כן. היא לא צריכה לדעת מה ערך אתה הולך לשים אותם. אבל הוא צריך לדעת איך הרבה זיכרון שאתה צריך. אבל עכשיו נניח ש, למשל, אתה יוצר מערך או לוקח מחרוזת שאתה לוקח מהמשתמש. אתה לא יודע כמה זמן את המחרוזת הוא הולך להיות, למשל. אז אתה לא יודע בדיוק כמה אבני זיכרון שאתה מקצה, נכון? אז זה לא ממש הגיוני עבור שלך לומר את 100 תווים. ואז מה אם המשתמש כותב 150? אתה הולך להיות דפוק. אז בעצם, אתה לא יכול להיות בטוח באופן הרבה זיכרון אתה צריך להקצות כאשר אתה מהדר את התכנית. אתה רק יודע שעל זמן ריצה. אז בגלל זה יש לך את הערימה. אז הערימה הולכת להיות זיכרון כי אתה הקצאה במהלך משך ריצת התכנית. אז בעצם, כשאתה עושה malloc, מה שאתה עושה הוא הקצאת זיכרון ב זמן ריצה, מה שאומר שאתה מחליט ממש באותו רגע שאתה צריך להיות זיכרון ש. אז זה כשאתה הקצאה אותו. האם זה הגיוני? אז לזכור, יש ערימת משתנים שנוצרים בזמן הידור. ואז יש לו את הערימה משתנים שנוצרים כמו שאתה הולך עם malloc, למשל. קהל: [לא ברור]? לוקאס: אז GetString הוא הולך לקרוא malloc. תן לי לדבר על malloc, ו אני אסביר GetString. אז malloc הוא אותו הדבר כהקצאת זיכרון. אז זה הולך להקצות זיכרון על הערימה. וזה הולך לחזור מצביע שבו הזיכרון שהוקצה ב. לכן, כאשר אתה do-- כאן לexample-- מצביע כוכב n. ואז מצביע שווה malloc גודל של סנטימטר פעמים 10. אני יוצר מצביע. ולאחר מכן אני הקצאת מצביע של הערך של המצביע שmalloc הוא נותן לי. malloc אז אני שואל אתה יכול להקצות מקום ל10 מספרים שלמים. זה מה שזה אומר. וmalloc נותן לי גב מצביע למקום ש. הגיוני? אישור. אני וGetString הוא, בעצם, עושה קורא לmalloc, כך שתוכל להקצות זיכרון במהלך ריצה. זכור תמיד לבדוק null בגלל malloc הולך לחזור null אם הוא לא יכול להקצות זיכרון. נניח שאתה שואל למגוחך כמות הזיכרון. המחשב שלך הוא לא הולך להיות תוכל להקצות כל כך הרבה. אז malloc הוא רק הולך לחזור null. אז תמיד לזכור לבדוק אם מצביע שיש לך מmalloc הוא null או לא, כי, אם כן, אתה עלול להיות ביטול הפניה למבנה מצביע ו גורם תקלות צד. ולבסוף, אל תשכחו הזיכרון הפנוי שלך. Malloc הוא יצירת זיכרון בערימה. ואתה צריך לשחרר את הזיכרון לפני שהתכנית מסתיימת. אישור, זה כל מה שעבורי. מצטער, רוב. תודה. [מחיאות כפות] לוקאס: כל שאלות האחרונות לפני רוב מגיע? לא? כן? קהל: אני לא ראיתי מקוון זה אחד. האם העלית אותו עדיין? לוקאס: אני חושב שדייב הוא העלאתו בקרוב. DAVE: זה יפורסם. לוקאס: זה יהיה באינטרנט. קהל: זה תלוי. לוקאס: זה תלוי? אישור. כן? קהל: [לא ברור]? לוקאס: כן, אתה צריך לשחרר את כל זיכרון, ששם בערימה. קהל: [לא ברור]? לוקאס: כן. בכל פעם שיש לך malloc תרבות, צריך להיות לך תרבות חופשית לאחר הפסקת שימוש משתנה ש. אז malloc וחופשי הם תמיד ביחד. החברים הכי טובים שלהם. כן. רוב? ROB: אני אלך במהירות. וגם הווידאו יהיה לשים את. יש לי המיקרופון ב. אוקיי, אז שבוע חמישה דברים. דבר הראשון שיש לנו הוא הערימה. אז לזכור שיש רק ערימה אחת מסגרת לקריאה לפונקציה פעילה. אנחנו תראו את זה בשנייה. וגם לזכור את מה שמתרחש בפועל בכל מסגרת ערימה הולך להיות המשתנים המקומיים של הפונקציות שלנו, הטיעונים שהם עברו לשלנו פונקציות, יחד עם בני זוג דברים אחרים שאתה לא באמת צריך לדאוג. אז הנה תכנית לדוגמה שבו, הודעה, הראשי printfing התמורה ערך של foo 4. foo הוא רק הולך להחזיר את ערך של בר 4 פסיק 6. ובר הולך להגדיר כמה מקומי n משתנה שווה ל 4 פעמים 6. ולאחר מכן לחזור n. אז בואו נסתכל על הערימה לאורך איטרציה בפועל של תכנית זו. אז יש תחתית הערימה שלנו. זכור כי הערימה גדלה. אז בתחתית הערימה שלנו, אנחנו יש לי מסגרת מחסנית לעיקרית. כאשר התכנית מתחילה, עיקרי הוא תמיד יהיה ב תחתית הערימה שלנו. ומה יש בתוכו שלנו מחסנית מסגרת לעיקרית? אז למרות שאין מקומי משתנים עיקריים ל, כמו שאמרתי קודם, אנו argc וRGV שתופסים מקום בתוך מסגרת ערימה העיקרית. אז עיקרי כעת הוא הולך קורא foo הפונקציה. וזה אומר foo הולך לקבל מסגרתו של המחסנית. אז עכשיו אנחנו בתוך של foo הפונקציה. ומה צריך ללכת ב מסגרת הערימה של foo? ובכן, יש foo n טיעון. וn שווה ל 4 מאז שזה מה ש עיקרי עובר כטענתו של foo. אז עכשיו foo הולך לקרוא בר. מה בר הולכת להיות בתוך של מסגרת המחסנית "שלה? יש לו x שווה ל 4 y שווה לשש. זה לא כל מה שאנחנו הולכים יש לי במסגרת הערימה כי בר יש גם n משתנה מקומי. וn אנחנו הולכים להגדיר שווים ל24. אז עכשיו בר הולך לחזור n. אז הבר חוזר 24 ל foo מסגרת מחסנית. ובגלל שבר כעת חוזר, ש משמעות הדבר היא שאנחנו מפצחים את מסגרת המחסנית לבר מהערימה. אז כל הזיכרון שבר היה באמצעות כעת את המחסנית. עכשיו, foo הוא גם הולך לחזור 24 לעיקריים. אז עכשיו foo שחוזר, הזיכרון foo שמשתמש ב'שלה מסגרת ערימה גם נעלמה. ועכשיו, עיקרי הוא הולך לקרוא printf. אז printf הוא רק פונקציה אחרת. כאשר אנו קוראים printf, זה הולך להיות מסגרת מחסנית נוספת לprintf קריאה לפונקציה. מה שאנחנו עוברים printf? זה מה שהולך במסגרת המחסנית שלו. לכל הפחות, אנחנו עוברים אחוזים שאני מהלך סרק n ו הטיעון 24. אולי יש לו יותר בזה מסגרת מחסנית אם printf קורה להיות באמצעות כמה משתנים מקומיים. אנחנו לא יודעים. אבל כל זה הולך בprintf של מחסנית מסגרת. זה הולך לבצע את printf. אז printf עשה. הוא יחזור. לבסוף, עיקרי נעשה. ראשי יחזרו. ואז התכנית שלנו נעשה. כן? קהל: האם אתה רואה [לא ברור] טענות [לא ברור] פרמטרים? ROB: אז יש הבדל דק בין טיעונים ופרמטרים. ובאמת, בלדבר נפוץ, אנשים נוטים רק כדי לערבב אותם כל הזמן. אבל פרמטרים הם פורמליים שמו של הדברים. אז argc וargv הם פרמטרים לעיקריים. טענות הן מה שאתה בעצם לעבור כבפרמטרים אלה. אז יש כשאני קורא foo של 4, 4 הוא הטיעון שאני עובר ב. וn הפרמטר, בתוך foo, לוקח על עצם את הערך 4 מאז 4 היה הוויכוח. קהל: [לא ברור]? ROB: n הוא משתנה מקומי לאסור. n הוא עדיין מקומי לfoo, אבל זה פרמטר לfoo. זה לא משתנה מקומי. כן? קהל: [לא ברור]? ROB: בר foo הוא רק קורא ו חוזר כל מה שמחזיר הבר. קהל: [לא ברור]? ROB: כן, רק כדי לראות מספר רב של מחסנית מסגרות. כן? קהל: מדוע foo נקרא לפני printf? ROB: מדוע נקרא foo לפני printf? אז יש לי יכולים, במקום, עשה משהו כמו int x שווה foo של 4 ולאחר מכן הודפס x. אבל במקום זה, אני בשילוב הפונקציה קורא לויכוח printf. אבל שים לב שאנחנו לא ממש יכולים להפעיל את הקריאה לprintf עד ש להבין מה הוא foo של 4. אז אנחנו הולכים להערכה זו. ורק פעם אחת שזה נעשה הולך לחזור ולהעריך את זה. כן? קהל: מאחר ששני בר [לא ברור] ערך, למה אנחנו לא צריכים [לא ברורים]? ROB: הם לחלוטין צריכים להיות int. שלא נתפס על עובר מרובה. אז זה צריך להיות בר int וint foo מאז שני אלה חוזרים מספרים שלמים. Void הוא רק אם הם לא הולכים לחזור ערכים בפועל. כן? קהל: אם היה לך שורה מעל התמורה, [לא ברור]? ROB: קו מעל התמורה? קהל: כן. כמו אם עשו printf ו[ לא ברור], היה זה להדפיס פעמיים? ROB: אז בתוך foo? אם היו לנו printf כאן? קהל: כן. ROB: אז אם לא הייתה לנו זכות printf כאן, זה יהיה להדפיס פעם אחת. מכיוון שאנו קוראים foo פעם אחת נכון כאן, אז אנחנו פגעו printf. אז אנחנו קוראים לברים. ולאחר מכן foo יחזור. וזהו זה. אנו היחידים שאי פעם תיתקלו printf פעם אחת. כן? קהל: [לא ברור] printf קורא foo בגלל שאנחנו ראשון קורא printf ואז אנחנו עוברים הטיעונים. ROB: אז בתאוריה, אינו printf קורא foo? אז לא. רק כדי שג הולך לבצע את הדברים האלה הוא, לפני שאנחנו יכולים לקרוא לפונקציה, כל הטענות לפונקציה צריכה להיות מוערך לחלוטין. אז הוא זה הוערך לחלוטין? כן, זה רק מחרוזת. זה רק ערך. אז אנחנו צריכים לחלוטין להעריך את זה. ברגע שזה נעשה, עכשיו כל טענותיה מוערכות. ועכשיו אנחנו יכולים לעשות קורא לprintf. כן? קהל: שאלה אחת. אם יש לך פונקצית void, חייב יש לך פסיק תמורה? ROB: אתה לא פסיק תמורה אם יש לך פונקצית void. אישור. אז עכשיו כמה דברים ערימה. אז הערימה היא איך אנחנו הולכים להתמודד עם ניהול זיכרון דינמי. וזה ישירות בניגוד ל ערימה שהיינו קורא אוטומטי ניהול זיכרון. אז על הערימה, אף פעם לא באמת יש לך כדי להתמודד עם כמה משתנים המקומיים נדחפים והכניס את כל מסגרות אלה ערימה ואת כל הדברים האלה. אתה לא צריך לדאוג בקשר לזה. זה אוטומטי. אז הערימה היא ידנית. ו[ לא ברור] מגיע מפונקציות אלה malloc וחופשי. אז הנה תכנית אחרת. כל מה שאנחנו עושים הוא mallocing מספר שלם. אנחנו לאחסן אותו בx כוכב. כמובן, אנחנו צריכים לבדוק כדי לראות אם x הוא null. ואז אנחנו הולכים רק כדי להגדיר את מה ש x מצביע ל50. הדפסה מה x מצביע, x הדפסה, וx אז חופשי. אז איך זה בעצם הולך להיראות אם אנחנו מסתכלים על הערימה והערימה שלנו? אז נתחיל שוב. תחתית הערימה שלנו כמו קודם. זכור כי לערום ישירות מתנגד לערימה? אז אנחנו הולכים ליש לי החלק עליון של הערימה שלנו שם למעלה. אז החלק התחתון של הערימה שלנו, יש לנו מסגרת המחסנית שלנו לעיקרי. יש לו את המרחב לargc, argv, ואנחנו עכשיו יש לי x משתנה מקומי, ש הוא כוכב int. אז אנחנו הולכים ללחזר באמצעות תכנית זו. דבר הראשון שיש לנו הוא קריאה לmalloc. אז אנחנו עושים את שיחה לmalloc. Malloc הוא פונקציה. זה הולך כדי לקבל מסגרת מחסנית. מה שאנחנו עוברים לmalloc? זה הולך להיכנס פנימה של מסגרת המחסנית. אנחנו עוברים גודל של n, שהוא 4. כך שהוא עבר לmalloc. מה malloc עושה? זה תופס אותנו קצת מרחב בערימה. אז אנחנו הולכים לערימה. ואנחנו הולכים לתפוס 4 בתים מהערימה. אז בואו פשוט לתת ש כתובת שרירותית. 0x123 רק להעמיד פנים שהוא כתובת שנמצאה בערימה. אז מה הוא בעצם חלק פנימי של ש אזור של זיכרון בכתובת Ox123? אשפה. אז יש לנו לא מאוחסן כל דבר בו. אז עד כמה שאנחנו יודעים, זה יכול להיות כל דבר. אתה לא צריך להניח שזה אפס. זה כנראה לא אפס. חוזר אז עכשיו malloc. ומה אנחנו עושים כשחוזרים malloc? אנו קובעים מה הוא חוזר. אנו קובעים x שווה למה ש הוא חוזר. אז מה זה חוזר? זה חוזר 0x123 מאז שהוא כתובת של בלוק זיכרון ש רק שהוקצה בערימה. אז לחזור 0x123 x עכשיו הולך להיות מוגדרים שווה ל0x123 ש, ציורי, אנו לעתים קרובות לצייר כמו x שיש בפועל חץ מצביע על בלוק ש. אבל x הוא רק אחסון כתובת זו. אז עכשיו אנחנו צריכים לבדוק אם x הוא null. זה לא ריק. אנו מעמידים פנים שmalloc שהצליח. אז עכשיו כוכב x שווה 50. אז כוכב זוכר זה אומר ללכת לכתובת זו. אז 0x123 אנחנו הולכים ללכת לכתובת זו. אז זה מביא אותנו לשם. מה שאנחנו עושים בכתובת ש? אנחנו אחסון 50. אז אחרי הקו הזה, זה מה ש דברים הולכים להיראות. אז עכשיו זה כבר לא אשפה שם למעלה. עכשיו אנחנו יודעים ש50 הוא שב כתובת מסוימת כי אנו קובעים אותו לזה. בסדר? אז עכשיו אנחנו הולכים להדפיס f. אז קודם כל אנחנו הולכים להדפיס x כוכב. אז מה הוא x כוכב? שוב, x כוכב פירושו ללכת ל דבר שx מצביע. אז x הוא אחסון 0x123 עבור של. אנו מקבלים 50. אז להדפיס f ש. וזה אומר שזה הולך להדפיס 50. ולאחר מכן שחוזר. ולאחר מכן יש לנו printf השני. אנחנו עכשיו p אחוזים. אם לא ראה את זה, זה עד כמה אתה מדפיס מצביע. אז יש לנו אני אחוזים, אחוזים f, וכל אלה שכבר. אז p אחוזים, להדפיס מצביע. אז x הוא מצביע. אז אם אנחנו הולכים להדפיס x עצמו, אנחנו מדפיסים מה הוא בעצם בתוך x, שהוא 0x123 אז הראשון f ההדפסה הולכת להדפיס 50. F ההדפסה השנייה הולכת להדפיס 0x123 כן? קהל: האם אתה משתמש באחוזים x להדפיס מצביע? ROB: אז אתה משתמש אחוזים x להדפיס מצביע? אז אתה יכול אבל x אחוזים הוא פשוט, בדרך כלל, לכמו אם יש לך כמה מספר שלם ושרצונך להדפיס זה כמו הקסדצימלי. זה בדיוק איך אתה עושה את זה. ואילו, היית ד אחוזים להדפיס כעשרוני. זה היו אנחנו מקבלים אחוזים ד. אני הוא רק מספר שלם. p אחוזים הוא באופן ספציפי עבור מצביעים. אז x הוא מצביע. אנחנו רוצים להשתמש בעמ אחוזים. אבל x אחוזים יכול לעבוד. כן? קהל: [לא ברור]? ROB: כן. לפחות לזה call-- אז לא כללתי אותו בכאן. אבל שני טיעונים אלה הם בהכרח בתוך מסגרת מחסנית זה יחד עם כל משתנים מקומיים printf קורה להיות באמצעות. ואז השיחה הבאה לprintf עכשיו בתוך printf מסגרת ערימה היא n הקו הנטוי p אחוזים וכל מה ש ערך של x הוא, שהוא 0x123. כן? קהל: [לא ברור]? ROB: זה יהיה להדפיס משהו שנראה כמו זה. קהל: [לא ברור]. ROB: אז הוא מדפיס את זה בצורת כתובת. זה נראה כמו כתובת. כן? קהל: [לא ברור]? ROB: למה מה? קהל: [לא ברור]? ROB: מדוע מצביע זה הוא 4 בתים? אז יש כל חבורה של 0 של מול זו. אז זה באמת 0x0000000123. במערכת 64 סיביות, לא יהיו חבורה שלמה של יותר אפסים. כן? קהל: [לא ברור]. ROB: אז printf הראשון הולך print-- קהל: [לא ברור]. ROB: כן, זה הולך להדפיס מה x מצביע. כוכבים אומר מה זה דבר המצביע על. לתפוס אותו. אז מה זה מצביע? 50. לתפוס אותו. זה מה שאנחנו הולכים להדפיס. ואילו, את הבאה, אנחנו רק הדפסת x עצמו. מה יש בתוכו של f? 0x123. אישור. ואז, סוף סוף, יש לנו חינם. מה אנחנו עוברים כדי לשחרר? אנחנו עוברים x. זמן שאני בעצם מוצג זה במסגרת המחסנית. אז אנחנו עוברים את הערך 0x123 לשחרר. אז עכשיו חופשי יודע, בסדר, אני צריך ללכת עד לערימה וחופשי מזיכרון, ש. זה כבר לא משתמש במה הוא ב0x123 כתובת. כל כך חופשי עומד לשחרר כי מהערימה. עכשיו הערימה שלנו היא ריקה שוב. אין לנו דליפות זיכרון. עכשיו חופשי יחזור. שים לב כי x הוא עדיין 0x123. אבל שעכשיו זה לא זיכרון בתוקף. אנחנו צריכים x dereference כבר לא. כן? קהל: האם לחזור 0 מיותר? ROB: האם returen 0 מיותר? כן. אנחנו פשוט לשים את זה שם, כי יש לנו תמורה אחד לאוויר. אז זה כאילו, כן, מאפשר לי כולל את התשואה 0. כן? קהל: [לא ברור]? ROB: אז אחרי x החופשי, מה יקרה אם אנחנו מנסים dereference המצביע? זה אפשרי, כי שום דבר לא ישתבש. זה אפשרי, כי אנחנו עדיין מקבלים 50. זה אפשרי, גם, כי הזיכרון שהוא כיום בשימוש עבור משהו אחר. אז זה התנהגות בלתי מוגדרת. ולא מוגדר אומר משהו יכול לקרות. כן? קהל: [לא ברור]? ROB: לא, כך שאם אתה מקצה x למשהו אחר. אז אם כאן שאמרנו x שווה משהו malloc else-- event-- גודל malloc אז שגוש מקורי של זיכרון לא משוחרר. ויש לנו באופן רשמי איבדתי את זה. כלומר דליפת זיכרון. איבדנו כל ההפניות לבלוק של זיכרון. אז אין שום דרך שנוכל אי פעם לשחרר אותו. אוקיי, אז לאחר מכן להחזיר 0 אמצעים לעשות. כל הגלישה תקין, כך הערימה. מה הרעיון כאן? אז לזכור, ערימה יורדת. הערימה הולכת עד. אז זה היה הדוגמא מהרצאה, אני חושב, שבו עיקרי הוא רק הולך קורא foo פונקציה זו, אשר הולך לקרוא לעצמה באופן רקורסיבי שוב ו שוב. אז מחסנית מסגרות הולכים עובד בדיוק אותו הדבר. אז אנחנו הולכים להתחיל עם עיקריים כמסגרת ערימה התחתונה. אז הראשי הולך לקרוא foo, ש הוא הולך לקבל מסגרת מחסנית. אז foo הולך לקרוא foo שוב, שהוא הולך לקבל מסגרת ערימה אחרת. ואז שוב, ושוב, ושוב, ושוב, עד שלבסוף, גמר לערימה. אז ככה אנחנו מקבלים הצפת מחסנית. ובשלב זה, אתה צינוק באשמה. או שהיית באמת seg תקלה לפני שלב זה, אבל כן. קהל: האם ליבה לזרוק אותו דבר כמו באשמת צינוק? ROB: אז תראה פילוח ליבת אשמה זרקה. אתה מקבל מזבלה ליבה כאשר אתה צינוק באשמה. וזה כמו מזבלה של כל תוכן של הזיכרון הנוכחי שלך כל כך כי אתה יכול לנסות ולזהות למה אתה SEG פגם. כן? קהל: [לא ברור]? ROB: אז אמצעי אשמת פילוח יש הצפת מחסנית. אז לא בהכרח. אשמת פילוח אומרת שאתה זיכרון נוגע ללב בדרך אתה לא צריך להיות. אז דרך אחת שזה יקרה היא, כאשר אתה הצפת המחסנית, אנחנו מתחילים נוגעים ללב זיכרון באופן שאנחנו לא צריכים להיות. כן? קהל: [לא ברור]? ROB: אז בתוך לולאה אינסופית. כמו, זה כמו אינסופי רקורסיבית לולאה ולכן אנחנו מקבלים עוד ערימה למסגר בכל פעם. אבל רק בתוך רגיל אינסופי תוך one-- טוב, בואו אפילו לא להדפיס f-- לעשות משהו. לא משנה מה. אנחנו לא הולכים להיות מקבלים מסגרת ערימה אחרת. אנחנו רק הולכים לשמור לולאות על הוראה יחידה זה. הערימה לא גדלה. זה את העובדה שכל אחד רקורסיבית שיחה היא נותנת לנו מסגרת מחסנית. זו הסיבה שאנחנו מקבלים הצפת מחסנית. כן? קהל: אז אם אתה אמר לקבל את תוך לולאה ולאחר מכן [לא ברור]? ROB: אז אם בתוך לולאת ה while היה printf, אתה עדיין היית אשמה לא צינוק. אני פשוט לא רוצה לבלבל דברים. זה היית לולאה. היית מקבל ערימה אחת מסגרת לprintf. אז printf יחזור. אז היית לולאה שוב. היית מקבל ערימה אחת מסגרת לprintf. זה יחזור. מסגרת ערימה אחת. אז אתה לא מקבל את זה אינסופי נערם מסגרות מחסנית. קהל: [לא ברור]? ROB: כן. אז הצפת מחסנית זה קורה כי אף אחד מאלה שיחות לfoo חוזרות. אז אם אנחנו חוזרים, ואז היינו מתחיל לאבד את מסגרות מחסנית. ואז לא היינו הצפת מחסנית. וזה למה אתה צריך מקרה בסיס עבור הפונקציות אישיות שלך. כן? קהל: האם הגודל והפוטנציאל מחסנית לערימה את אותו הדבר עבור כל התוכניות? ROB: בהערכה גסה. האם גודל הפוטנציאל של המחסנית ו הערימה זהה עבור כל התוכניות? בערך. יש קצת אקראי ל שבו מתחילה ערימה ו שבו הערימה מתחילה. אם במקרה יש לי המון משתנים ודברים גלובליים, אתה עלול לקחת מן קצת מרחב לערימה שלך. במערכת 64 סיביות, אתה כמעט יש לי זיכרון אינסופי. יש פשוט כל כך הרבה. בין 32 סיביות ו64 סיביות, ש הבדל משמעותי. אתה הולך לקבל הרבה יותר מחסנית וחלל ערימה על 64 סיביות מערכת כי יש רק עוד כתובות שהם יכולים להשתמש. אבל במערכת בודדת, זה יהיה להיות בערך את אותה הכמות של מחסנית ומרחב ערימה. בסדר. אז הדבר האחרון הוא אוסף. אז אתה צריך לדעת את התהליך הזה. ישנם ארבעה שלבים גדולים. אז הראשון צריך יהיה קל לזכור. טרום עיבוד. יש לו את הקידומת מראש בזה. אז זה מגיע לפני כל דבר אחר. מה שצריך לזכור הוא החשיש. אז חשיש מגדיר וחשיש כולל בכל אלה. כל אלה הם מראש המעבד הנחיות. אלה הם הדברים ש טרום מעבד דואג. אז מה עושה לפני מעבד לעשות? זה דבר ממש מטומטם. כל זה מסוגל הם כל אלה עותק, ולחתוך, ולהדביק פעולות. אז חשיש כולל h נקודת i0 הסטנדרטי. מה זה עושה? זה תופס h נקודת i0 הסטנדרטי קובץ ולהדביק אותו לתוך החלק העליון בכל מקום שהוא אומר חשיש כולל h נקודת i0 הסטנדרטי. וכל חשיש להגדיר שיש לנו ראה, מה שעושה את זה? שלה העתקת הערך שהחשיש הגדיר מוגדר וכהדבקה ש בכל מקום שבו אתה משתמש הערך. אז בעיבוד המוקדם פשוט עושה באמת פעולות מבוססות טקסט פשוט. זה לא עושה כלום חכם. אז כל דבר אחר הוא יותר מסובך. אז עכשיו העיבוד מוקדם שהוא לעשות, אנחנו בעצם לקמפל. אז מה עושה קומפילציה אומרת? עכשיו אנחנו הולכים מקוד ג לקוד הרכבה. כן? קהל: [לא ברור]? ROB: כן, תפסנו את זה. אז קומפילציה. אנחנו הולכים מג להרכבה. אז זה שינוי שפה בפועל. קומפילציה עצמו אומר שהולכת מ שפה ברמה גבוהה יותר כדי שפה ברמה נמוכה יותר. וג הוא שפה ברמה גבוהה בהשוואה להרכבה. מהו הרכבה? ההוראות שלה, כי הם, די הרבה, עשה למעבד שלך. אבל המחשב עדיין עושה לא מבין הרכבה. זה מבין רק אפסים ואחדים. אז השלב הבא הוא הרכבה, ש מביא אותנו מהוראות אלה ש המעבד שלך מבין ולמעשה מתרגם אותם, כדי אלה ואפסים. אז C להרכבה לינארי. אבל אין לי הפעלה עדיין. אז תחשוב על ספריית cs50. יש לנו בתנאי שאתה עם בינארי ל ספריית cs50 זה, שבו יש GetString וGetInt וכל זה. אבל cs50 library-- ובitself-- הוא אינו ניתן לביצוע. זה לא חייב פונקציה העיקרית. זה פשוט חבורה של ינארי שאתה יכול להשתמש. אז הקישור הוא איך אנחנו מביאים יחד את כל של קבצים בינאריים השונים אלה להפעלה בפועל. אחד שאתה יכול להקליד הנקודה לקצץ את נקודה. אז זה כמו הקובץ ש כתב, - מה התכנית שלך is-- נקודת ג Ceaser. אבל עכשיו זה כבר הידור עד לינארי. אז o נקודת Ceaser. וזה cs50 ספריות בינארי. והם להיות משולבים להפעלה אחד. כן? קהל: [לא ברור]? ROB: כולל אז קודם כל, לזכור, החשיש כולל הוא למעשה צעד מראש מעבד. אבל זה נפרד. אם אינך משתמש בכל פונקציות ש נמצא מחוץ לקובץ היחיד שלך אז, לא, אתה לא צריך לקשר כל דבר מאז שיש לך הכל. שאמרו, printf הוא להיות מקושר ב. אם אי פעם להשתמש printf, זה משהו ש שצריך להיות קשור ב בגלל שלא היה לך לכתוב את זה. ואכן, printf הוא באופן אוטומטי צמוד ב. אתה יודע איך בשורת הפקודה או בעת אתה מקליד לעשות, אתה רואה שיש לו cs50 l מקף, שבו יש קישור בספריית cs50? Printf, ודברים כאלה, הוא הולכים כדי להיות מקושר באופן אוטומטי. שאלות אחרות על כל דבר? קהל: [לא ברור]? ROB: קישור? יש לנו חבורה של שלמה קבצים בינאריים שונים. זוהי הדוגמא הקנונית שאנו משתמשים הוא ספריית cs50. יש לנו המלוקט וניתנו לך בינארי לספריית cs50 זה. ברצונך להשתמש GetString בתכנית שלך. אז אתה הולך ולהשתמש GetString. אבל ללא הקוד בינארי שלי ל GetString, כאשר אתה מהדר את הקוד שלך למטה, אתה לא ממש יכול לרוץ שלך תכנית כי GetString המחרוזת היא עדיין אינו מוגדר לחלוטין. זה רק כאשר אתה מקשר בינארי שלי המכיל GetString שעכשיו, כל נכון, אני באמת יכול לבצע GetString. הקובץ שלי הוא מלא. ואני יכול להפעיל את זה. כן? קהל: האם השירשור להמיר בינארי להפעלה? אז גם אם אין לך אחר ספריות, לא יהיה זה עדיין תהיה צורך לתרגם [לא ברור]? ROB: אז הפעלה עדיין בינארי. זה פשוט שילוב של כל חבורה של קבצים בינאריים. קהל: תודה רב לך. ROB: אין בעיה. יש עוד שאלות? אחרת, כולנו מוכן. בסדר. תודה. [מחיאות כפות] קהל: תודה לך. ROB: כן.