[השמעת מוסיקה] דוד י מלאן: בסדר. זה CS50. וזה הוא ההתחלה של שבוע 5. וכמו שאתה אולי שמת לב, חלק מהחומר הוא מקבל קצת יותר מורכב, צפוף יותר הקטן. וזה קל מאוד, במיוחד אם אתה כבר ברגל לכמה זמן, למנסה לשרבט ביותר כל דבר שאנחנו עושים, אנחנו אומרים בכיתה. אבל מבין, שאינו אולי הגישה הפדגוגית האידיאלית ללמידה של חומר מסוג זה, וחומר באופן כללי יותר. וכך אנו שמחים להודיע ​​Gheng של CS50 ש גונג החל להכין סט הקנוני של הערות לקורס, התקווה והוא ש, אחד, אלה לא רק לשמש כ התייחסות ומשאבים לבחינת חומר והולך בחזרה דרך חומר שאולי יש לי ברחתי לך בסיבוב הראשון, אבל גם כדי שהראש שלך יכול להיות יותר עד מאשר למטה, כאשר הוא מגיע זמן להרצות, כך שאולי אתה עוסק יותר מהורהר, כ בניגוד ליותר scribbly. עם זאת אמר, מה שאתה תמצא על אתר האינטרנט הוא מסמכים מסוג זה. והודעה, בצד שמאל למעלה, יש לא רק תוכן, אבל גם קודי זמן ש אקפוץ לך באופן מיידי לחלק המתאים בוידאו המקוון. ומה צ'אנג כאן עשה הוא, במהותו, שתועד מה שקרה בזה הרצאה מסוימת. ורבים מההרצאות כבר כעת באינטרנט עם כתובת אתר זו. ואנחנו נמשיך לפרסם את השארית מאותם עד סוף השבוע, אז אל לנצל את המשאב הזה. אז בלי עיכובים נוספים, התחלנו לקלף השכבה שהייתה מחרוזת לכמה זמן. ומה שאנחנו לא אומרים מחרוזת למעשה הוא בשבוע שעבר? כוכב אז char. וכוכב char, גם, מה לא שבאמת מתכוונים? ובכן, כל הזמן הזה, אם יש לנו כבר קורא לפונקציה, כמו getString, ואחסון התמורה שנקרא ערך של getString ב variable-- זה נקרא סוג של string-- אנחנו כבר כותבים שורת קוד שם למעלה מעל. וזה רק כשאני רואה את שלי כתב יד מוגדל כאן אני מבין עד כמה אכזרי זה. עם זאת, הבה נניח כי, בצד ימין הוא, בכל זאת, סביר תיאור של מה ש היה הולך על כל זה זמן עם getString. getString, כמובן, מקבל מחרוזת. אבל מה זה באמת אומר? זה אומר שהוא מקבל נתח של זיכרון ממערכת ההפעלה על ידי קריאה לפונקציה, נקרא malloc. אבל יותר על כך בהמשך. ואז זה מאכלס נתח זה של זיכרון עם האותיות למשתמש יש הקליד ב, ואחריו, כמובן, אופי null, או קו נטוי אפס ממש בסוף. בינתיים, בצד השמאל של הסיפור הזה, כל הזמן הזה, אנחנו כבר הכריזו משתנים, כמו של. ומשתנה זה מה שעכשיו יתחיל לקרוא מצביע. זה לא תיבה ובתוכה אנחנו שמים את המחרוזת, ךייבן, כשלעצמה, אלא שאנחנו מכניסים לכיכר ש תיבה בצד השמאל מה בדיוק? כן? קהל: הכתובת של איפה זה נמצא בזיכרון. דוד י מלאן: בדיוק. את הכתובת שבי ךייבן ממוקם בזיכרון. ולא שבו כל ךייבן ממוקם, כשלעצמו, אבל באופן ספציפי את כתובת של מה? כן? קהל: דמות ראשונה. דוד י מלאן: התו הראשון בךייבן, אשר, במקרה זה, הציע שהיה באופן שרירותי ולא מציאותי 1, OX1, שרק אומר מספר הקסדצימלי של 1. אבל זה כנראה הולך להיות מספר הרבה יותר גדול שאולי אנו מפנים את עם 0x כקידומת, המייצג את אופי הקסדצימלי. ובגלל שאנחנו לא צריכים לדעת איפה שאר הדמויות של ךייבן הם, בגלל מה שעיצוב פשוט החלטה שהתקבלה לפני שנים רבות? כן? קהל: מהלך סרק 0. דוד י מלאן: כן, בדיוק. הקו הנטוי 0 מאפשר לך, אם כי ב זמן ליניארי, לעבור את המחרוזת, ללכת משמאל לימין, עם ללולאה, או בזמן ש לולאה, או משהו כזה כי, ולקבוע, הו, כאן זה הסוף של מחרוזת המסוימת הזה. אז רק עם הכתובת ב תחילת מחרוזת, אנחנו יכולים לגשת למכלול זה, משום שכל הזמן הזה, מחרוזת רק הייתה כוכב char. אז זה בהחלט בסדר להמשיך להשתמש ספריית CS50 והפשטה זו, אם אפשר לומר כך, אבל אנחנו מתחיל לראות בדיוק מה שקורה מתחת כל הזמן הזה. אז אתה אולי זוכר דוגמא זו, מדי, מעת האחרונה, להשוות 0, שלא ממש להשוות. אבל התחלנו לפתור את זה. אבל כפי שאולי רענון, אולי אני מעניינת את מישהו בפיל ורוד היום, גם שנעשה על ידי צ'אנג? מה דעתך על שאתה בחזית? [לא ברור]. בואו למעלה. ובינתיים, שאתה בא, בוא לשקול לרגע מה הקוד הזה עושה בעצם. זה שהכריז שני משתנים עד עליון, של ולא, וקורא getString. זה לא תכנית מאוד ידידותי למשתמש, כי זה לא אומר לך מה לעשות. אבל בואו רק נניח שאנחנו התמקדות בחלק העסיסי. ואז אנחנו עושים, אם זה שווה שווה t, זה צריך לומר printf, שהקלדת את אותו הדבר. שלום. מה שמך? נל: נל. דוד י מלאן: נל, נחמד לפגוש אותך. אז האתגר שלך ב יד לפיל הזה הוא ראשון לצייר לנו תמונה של מה להיות מיוצג בשני הראשונים אלה קווים. אז T S ויכול להיות מיוצג כיצד על המסך? ואתה יכול פשוט לצייר אותו עם האצבע שלך על מסך גדול זה. אז יש שני חצאים ל כל צד של משוואה ש. אז יש ים בצד השמאל, ו אז getString בצד הימין. ואז יש t בצד השמאל, ולאחר מכן getString בצד הימין. אז איך אנחנו יכולים להתחיל ציור תמונה ש מייצג את מה שקורה כאן בזיכרון, היית אומר? ותן לי לתת לך להסביר מה שאתה עושה כמו שאתה הולך. ג'נל: אישור. ובכן, ראשון, זה יהיה שואל כדי שתוכל לקבל את מחרוזת הקלט. וזה יהיה store-- הו, מצטער. דוד י מלאן: אישור. טוב. וזה נקרא מה? אה, אוקיי. להמשיך. אני לא התכוונתי להפריע. ג'נל: מצטער. אז זה היית קלטו לתוך כתובת לא of-- בטוח. אני לא יכול בדיוק זוכר את המספר, אבל אני מאמין שזה התחיל עם 0. דוד י מלאן: זה בסדר, כי אני עשיתי את המספרים עד, כך שאין תשובה נכונה. ג'נל: החל מהקשת 0. דוד י מלאן: אוקיי, אז אלמנט 0. בטח. נל: ואז אם היה סתם שתי letter-- דוד י מלאן: אישור, אחזור אליך. ג'נל: אז אלמנט 0, ו אז אלמנט 1 או אלמנט 2. דוד י מלאן: ושפיסה התמונה אתה מצייר עכשיו? הקריאה לgetString? או ההכרזה על ים? ג'נל: ההכרזה של ים, אני מאמין. אה, getString, כי זה היה להיות שהוזן לתוך כל [? אזור. ?] דוד י מלאן: טוב. בדיוק. למרות שיעילות זה מחזיר מערך, כזכור, כשנחזור מחרוזת, שביכולתנו מדד למחרוזת שבאמצעות 01 ו2. מבחינה טכנית, אלה הם כנראה מיוצג על ידי כתובות אישיות, אבל זה בסדר. אז נניח, אם אני יכול פשוט מהיר קדימה למקום שבו הפסקנו הפעם האחרונה, אם אחד המחרוזות היו g דואר ב, קו נטוי 0, ובכך מייצג את גייב של קלט, איך ייתכן שאנו מייצגים ים עכשיו? אם זה זיכרון זה הוחזר על ידי getString? נל: האם זה יהיה מיוצג על ידי קשת? דוד י מלאן: על ידי קשת? ובכן, לא. בואו רק נאמר, באופן ציורי, תן לי רק קדימה ומציע ש, אם זה ים, זה הוא ערך ההחזרה של getString. ואתה כבר נמשך זה כ0, 1, 2, ש הוא סביר לחלוטין, כי אנחנו יכול מדד למחרוזת, ככזה. אבל רק כדי להיות בקנה אחד עם הפעם האחרונה, תן לי ללכת קדימה ושרירותי מציע שזה היא כתובת 1, זו כתובת 2, זו היא כתובת 3, וכן הלאה. וכך, רק כדי להיות סופר ברור, מה קורה ללכת בים כתוצאה מכך השורה הראשונה של קוד, היית אומר? ג'נל: כתובת 1? דוד י מלאן: בדיוק. אז לטפל 0x1. ובינתיים, תן לי ללכת קדימה ו לשכפל הרבה ממה שעשית ולהוסיף t שלי כאן. אם הייתי מקליד בגייב שוב, בפעם שנייה, כאשר תתבקשו לעשות זאת עם getString, שבו, כמובן, הוא גייב הולך? ובכן, presumably-- ג'נל: כמו כאן? דוד י מלאן: כן. ג'נל: או שזה גם נמצא באותו התיבות? דוד י מלאן: הרשה לי להציע, כן, , כך בדיוק בקופסות נוספות אלה. אבל מה מפתח עכשיו הוא שגם למרות שאני שציירתי אלה די קרובים together-- 0x1, זה הוא 0x2-- במציאות, זה עכשיו יכול להיות כתובת 0x10, למשל, ו0x11, ו0x12, וכן הלאה. וכך, אם זה המקרה, מה קורה בסופו של כאן בt? ג'נל: 0x10? דוד י מלאן: בדיוק. אז 0x10. ואז עכשיו, השאלה אחרונה. יש לך, ללא ספק, היה צריך לעבוד הכי קשה לפיל עד כה. עד עכשיו, אם אני מושך את הקוד שוב, כשאני עושה, בשורה שלוש, אם ים שווה שווה t, מה אני בעצם השוויתי שיש לנו נמשך לכאן? ג'נל: שתי כתובות? דוד י מלאן: בדיוק. אז אני אומר הוא S שווה שווה לא? במילים אחרות, הוא 1 שווה שווה ל10? וכמובן, תשובה ברורה כרגע היא, לא. וכך תכנית זו היא סופו של דבר הולך להדפיס מה, היית אומר? נל: האם זה יהיה, שהקלדת את אותו הדבר? דוד י מלאן: אז אם ים הוא 1 ולא הוא 10? ג'נל: הקלדת דברים שונים. דוד י מלאן: בדיוק. שהקלדת דברים שונים. בסדר. אז מחיאות כפות, אם היינו יכולים, כאן. [מחיאות כפות] זה היה כואב. אני יודע. יפה עשה. אז עכשיו בואו תראו אם אנחנו לא יכולים להפריד את מה שהתיקון היה. וכמובן, כאשר אנו קבועים זה- שבו אני עכשיו יהיה לייצג בgreen-- עשינו כמה שיפורים כאן. ראשית, בדיוק כמו שפיות לבדוק, אני ראשון אני בודק אם ים שווה null ולא שווה null. ורק שיהיה ברור, כאשר אולי ים או לא להיות null בקוד כזה? כאשר ים או לא להיות אולי null. כן? קהל: [לא ברור]. דוד י מלאן: בדיוק. אם המחרוזת שהמשתמש הקלידה בדרך ארוכה מדי כדי שיתאים לזיכרון, או כמה מקרה פינה מוזר כמו ש, getString, כפי שנראה, פשוטו כמשמעו היום, בתיעוד שלה, אומר שזה יחזיר null כ ערך זקיף מיוחד, או סתם סוג של סמל מיוחד זה אומר שמשהו השתבש. אז אנחנו רוצים לבדוק כי, משום שמתברר null שהוא ערך מאוד מסוכן. לעתים קרובות, אם אתה מנסה לעשות משהו עם null מעורב function-- העברתו כקלט, לinstance-- פונקציה ש אולי יהיה מאוד לקרוס ו, עם זה, לקחת את כל התכנית שלך. אז שורה שלישית זה כרגע היא רק שפיות לבדוק, בדיקת שגיאות, אם תרצה. זה הרגל טוב עכשיו לנו להיכנס לכל עת שאנו אנסה להשתמש בערך יכול, באופן פוטנציאלי, להיות null. עכשיו, בשורה הרביעית כאן, "אם strcmp (ים, t)," גם, מה שמתכוון? ובכן, אנחנו אמרתי שזה היה מאוד בתמציתיות פונקציה בשם להשוואת מחרוזת. ומטרתו בחיים היא כדי להשוות הטיעון הראשון שלה נגדה שני, אבל לא במונחים של הכתובות שלהם, כפי שעשינו שלא במתכוון רגע לפני עם הקוד האדום, אבל ולא להשוות בין שני אלה מחרוזות באינטואיטיבי מבחינה אנושית דרך על ידי השוואה זו, כנגד זה, נגד זה, נגד זה, ו אז עוצר אם וכאשר אחד או שתיהן, האצבעות שלי להיטי קו נטוי 0. strcmp כך שנות מישהו יישמו לפני ליישם עבורנו את הפונקציונליות שקיוויתי שהיו מקבל רק על ידי השוואה בין שני ערכים פשוטים. עכשיו בכנות, אני שומר ציור כל אלה מספרים השונים. אבל המציאות היא, שהייתי מה שהופך את אלה עד כל הזמן. ואז תן לי רק קדימה ולשרבט את אלה כדי להבהיר נקודה ש, בסופו של הדבר של היום ולנוע קדימה, אנחנו לא באמת הולכים אכפת מה כתובות דברים הם למעשה בזיכרון. אז אני לא הולך לצייר אלה סוגים של מספרים כל כך הרבה יותר, אני רק מופשט זה משם קצת יותר ידידותי עם רק חיצים. במילים אחרות, אם ים הוא מצביע, טוב, בואו פשוט לצייר אותו, פשוטו כמשמעו, כמצביע, חץ מצביע מעצמו למשהו אחר, ולא לדאוג יותר מדי עוד על הפרטים הקטנים של כתובות אלה אשר, שוב, המצאתי בכל מקרה. אבל נראה כתובות אלה, לפעמים, כאשר באגים קוד. עכשיו בינתיים, תכנית זו עד כאן תיקונים, כמובן, בעיה שעל ידי השוואה אלה שתי מחרוזות. אבל נתקלנו בבעיה אחרת. זה היה מהעותק לתכנת פעם האחרונה, לפיו, אני מנסה לנצל רק התו הראשון במחרוזת. אבל מה היה הסימפטום ראינו פעם כאשר האחרונה משתמש הקליד בערך, כמו גייב באותיות קטנה, לים, אז אנחנו מוקצים של אל t, כמו בשורה השלישית יש, ולאחר מכן ניסיתי לנצל סוגר t 0? מה הייתה ההשפעה של שינוי סוגר t 0 כאן? קהל: זה השתנה ים. דוד י מלאן: כן, גם אני שיניתי את של,. כי מה שבאמת קורה? ובכן, תן לי לראות אם אני יכול לנקות את התמונה הזאת, כדלקמן. אם ים הוא, שוב, המילה גרם, , B, E, קו נטוי, 0, ושל אנחנו נמשיך ציור כמו קופסא כאן, אך לא יותר כתובות. בואו נפסיק לעשות את דברים. בואו רק לצייר תמונה כדי לפשט את העולם. כאשר אני מצהיר t עם t מחרוזת, שיוצר נתח זה של זיכרון. כיכר קורה להיות 32 ביטים ברוב המחשבים. למעשה, אם אתה אי פעם שמעת על מחשב שיש לו ארכיטקטורה 32 סיביות, באמת מפואר, לדבר, שרק משמעות הדבר היא שהוא משתמש כתובות 32 סיביות. וכטכני בצד, אם תהית אי פעם מדוע מחשבים ישנים, אם אתה באמת ניסיתי מרק אותם עם הרבה זיכרון RAM, רק יכול להיות לכל היותר של ארבע ג'יגה בייט של זיכרון RAM, גם זה בגלל ש, פשוטו כמשמעו, יכול המחשב הישן רק לספור גבוה ככל 4 מיליארדים, 4 מליארד בייטים, כי זה היה באמצעות 32 סיביות מספרים לכתובות. אבל בכל מקרה, בזה דוגמא, של סיפור הרבה יותר פשוט. t הוא רק מצביע אחר, או באמת כוכב char, aka מחרוזת. ואיך אני רוצה לעדכן את התמונה הזאת עכשיו עם שהשורה שנייה של קוד, אחרי הנקודה,, נקודת נקודה? כשאני עושה את t המחרוזת שווה נקודה ופסיק של, איך התמונה הזאת תשתנה? כן? קהל: [לא ברור]. דוד י מלאן: כן. בדיוק. אני פשוט לשים את חץ מ תיבה לא לאותה הכתובת, אותו המכתב הראשון בנתן. או מבחינה טכנית, אם זה בחור היה עדיין ב0x1, זה כאילו שהיה לי 0x1 כאן ו0x1 כאן. אבל שוב, למי אכפת על הכתובות? זה פשוט הרעיון שעכשיו חשוב. אז זה מה שקורה כאן. אז כמובן, אם אתה עושה את סוגר t 0, שהוא סימון מערך, של course-- ולמען אמת, זה נראה כאילו יש מערך לכאן, אבל עכשיו יש דבר המוזר הזה. יודע ששפת תכנות, C, מציע לכם בתכונה זו, לפיו, גם אם לא הוא מצביע, או s הנו מצביע, אתה עדיין יכול להשתמש בזה מוכר, סוגר מרובע נוח הסימון ללכת לאלמנט הראשון, או האלמנט השני, או כל אלמנט שהמצביע שמצביע לכי, ככל הנראה, אותו הוא, כמו במקרה זה, מצביע על כמה מערך. אז איך אנחנו יכולים לתקן את זה? למען האמת, זה המקום שבו יש לי קצת מוחץ במבט ראשון. אבל כאן היא גרסה חדשה ומשופרת. אז קודם כל, אני מקבל להיפטר מספריית CS50, רק כדי לחשוף שזה אכן כוכב char, רק מילה נרדפת. ולא הוא גם כוכב char. אבל מה קורה ב צד ימני של קו ש כאשר t מוקצה ערך? מהו malloc? מה זה strlen? מה הוא sizeof (char)? למה לעזאזל עושה את זה שורת מבט כל כך מורכב? מה הוא עושה ברמה גבוהה? מה זה אחסון בt? כן? קהל: זה הקצאה כמות מסוימת של שטח זיכרון. זה לאחסון, אני מניח, אותיות [לא ברור]. דוד י מלאן: מושלם. מושלם. זה הקצאה מסוימת כמות שטח זיכרון לאחסון, ככל הנראה, מכתבי עתיד. ובפרט, malloc לכן חוזר מה? קהל: חוזר [לא ברור]? דוד י מלאן: בדיוק. חוזר את הכתובת של זיכרון ש, אשר היא דרך מפוארת לומר, מחזיר את הכתובת של הבית הראשון של זיכרון ש. הנטל הוא עליי לזכור כמה זיכרון אני ממש שהוקצה או ביקש malloc ל. עכשיו כמה זה? ובכן, למרות שיש הרבה סוגריים כאן, malloc לוקח רק טיעון אחד. ואני מפרט strlen של ים, כדי לתת לי לי בתים רבים כפי שיש בים, אבל להוסיף אחד. למה? כן? קהל: הקו הנטוי 0. דוד י מלאן: בדיוק. אנחנו חייבים לעשות קצת ניהול משק בית. אז בגלל שיש קו נטוי 0, היינו טובים יותר לזכור את זה. אחרת, אנחנו הולכים כדי ליצור מחרוזת ש אין ששליחות קטלנית מיוחדת. בינתיים, רק כדי להיות סופר אנאלי, יש לי sizeof (char), רק למקרה שמישהו מפעיל קוד לא על מכשיר CS50, אבל אולי במחשב אחר לגמרי שבו תווים בייט אחד, על ידי אמנה, אך שני בתים, או משהו יותר גדול מזה. זה רק כדי להיות סופר, סופר התנגד לטעויות. למרות, במציאות, זה כנראה הולך להיות 1. עכשיו, בינתיים, אני הולך קדימה ולהעתיק את מחרוזת, סוגר לא שווה אני סוגר T S. ואני לדחות לשבוע שעבר קוד מקור כדי לראות מה קורה. אבל ממסעדה המפתח, ו סיבה שאני מכניס את הקוד כעת בירוק, משום שהשורה האחרון, סוגר t 0 שווה toupper, יש ההשפעה של ניצול שמחרוזת? t ו / או של? שהשורה האחרונה של קוד. רק חולצות, משום מה קרה הפעם, אם אני מעט לבטל את הצעד האחרון, מה שקרה הוא, כשאני קורא malloc, אני בעצם לקבל נתח של זיכרון כי הוא באותו הגודל כמו המקורי, כי זה החשבון שעשיתי. אני אחסון בt כתובת של נתח זה של זיכרון. למרות שזה נראה נחמד ויפה, נחמד וריק, המציאות היא שיש, מה יהיה לנו להמשיך לקרוא, ערכי זבל בפה. נתח זה של זיכרון אולי מאוד גם היה בשימוש לפני, כמה שניות, לפני כמה דקות. אז בהחלט יכולים להיות שיש מספרים או אותיות לשם, רק במקרה. אבל הם אינם תקפים, עד ש עצמי לאכלס נתח זה של זיכרון עם תווים בפועל, כפי ש לעשות שבלולאת for יש. בסדר? אז עכשיו, שיאו של שלוש דוגמאות האלה שנשברו לכאורה הפעם האחרונה, דוגמא החלפה זו, פונקציה זו עבד במובן שהחליף וb. אבל זה לא עבד באיזה מובן אחר? כן? קהל: [לא ברור]. דוד י מלאן: בדיוק. אם הייתי קורא לפונקציה זו מanother-- למשל, מפונקציה כמו עיקרי, שבו יש לי משתנה, x, y, כפי ש עשה בשבוע שעבר, אותו קוד, ואני עובר בx, y כדי להחליף, ואז להתקשר Swap-- זה, כמובן, היא הגרסה הנכונה זה מה שאנחנו עומדים see-- זה לא עבד. אז מה הוא את התיקון? ובכן, כל כך פשוט להיות ברור, תן לי ללכת קדימה and-- לתת לי שנייה אחת כאן, ותראה אם אני יכול להראות לך את האחרון, ש יהיה in-- בואו נראה אם ​​אני יכול למצוא אישור fast-- אמיתי זה, [לא ברור]. אישור, זה מה שיש. אז להתעלם מהפקודות אני רק הקלדה. אני רוצה את זה כדי לאחזר ב הרגע האחרון ירושלים מעת האחרונה, ש הוא התקשר עכשיו אין החלפה. אז לא להחליף מקום שבו הפסקנו בפעם האחרונה, לפיו, אני אותחל x 1 וy 2. אז אני קורא להחלפה, עובר ב1 ו -2. ולאחר מכן בפונקציה זו עבד במובן מסוים, אבל אין לה קבע השפעה על x, y. אז השאלה שעל הפרק היא, איך עכשיו האם אנו באמת לתקן את הבעיה הזו? מהו הפתרון בהישג היד? ובכן, בswap.c, שהיא חדשה היום, שם לב כמה הבדלים. x, y זהה. אבל מה הוא באופן ברור שונה על שורת 25? מה חדש שם, אם אתה זוכר מה זה נראה כמו לפני שנייה? קהל: [לא ברור]. דוד י מלאן: כן. אז סימן החיבור הוא יצירה חדשה של תחביר לא רק בתכנית זו, אבל גם באופן כללי יותר בCS50. נכון להיום, אני לא חושב ש אנחנו כבר ראינו דוגמאות או ממש דיבר עליהם בכל פרט, אחר מאשר, אולי, מנע בסעיף, אמפרסנד כמו זה. ובכן, מתברר אמפרסנד הוא אחד של החלקים האחרונים של תחביר החדש אנחנו הולכים ללמוד. כל פירוש הדבר הוא כתובת של כמה משתנה. באיזה כתובת אין x לחיות? אבל מה כתובת אין y לחיות? כי אם בעיה בסיסית לפני היה שx, y הועברו עכשיו כעותקים, מה שאנחנו באמת רוצים לעשות הוא מספק החלפה עם כמו אוצר המפה שמובילה למקום שבי x, y למעשה נמצא בזכרון RAM, כך ש החלפה יכולה לעקוב אחר המפה ש וללכת לכל מקום בו x או y מסמן את המקום ולשנות את הערכים בפועל 1 ו -2 יש. אז החלפה צריכה להשתנות מעט מדי. ובמבט ראשון, כוח זה נראה קצת דומה לכוכב char. ואכן זה הוא. אז הוא מצביע לאיזה סוג של נתונים, המבוסס על חלק מודגש זה? אז זה int. אז הוא כבר לא int, זה הכתובת של int. ובאופן דומה, ב עכשיו הולך להיות הכתובת של int. לכן, כאשר אני מכנה היום החלפה מהראשים, אני לא הולך לתת לי החלפת 1 ו -2. אני הולך לתת לו כמו שור ומשהו ושור ומשהו, שתי כתובות שיובילו החלפה למקומות שלהם בפועל בזיכרון של המחשב שלי. אז עכשיו, יישום שנותר לי צריך לשנות טיפה. מה שונה ברור עכשיו בשלוש שורות קוד הללו? יש כוכבים הארורים האלה כל המקום, בסדר? אז מה קורה כאן? כן? קהל: זה ברור [לא ברור]. דוד י מלאן: בדיוק. אז בcontext-- זה וזה לא היה החלטת העיצוב הטובה ביותר, יש להודות, שנים לפני. בהקשר, שבו זה רק שיש לך כוכב, ואין לך סוג הנתונים, כמו int, מייד בצד השמאל, במקום שיש לך סימן שוויון, באופן ברור, בהקשר זה, כשאתה אומר לככב, זה אומר ללכת ל כתובת שהוא ב. בצע את מפת אוצר, אם אפשר לומר כך. ובינתיים, בשורה 37, זה אומר את אותו הדבר. עבור לכתובה, ולשים את מה שיש? לא משנה מה הוא ב מיקום שב מציין. במילים אחרות, ללכת לb. קבל ערך ש. עבור ול, לשוויון לחתום, אופרטור ההשמה, לשים ערך שיש. באופן דומה, טמפ int הוא רק int. שום דבר לא צריך להשתנות על טמפ '. זה פשוט זכוכית חילוף מאננברג לקצת חלב או מיץ תפוזים. אבל אני צריך לומר, ללכת לב. עבור ליעד וש לשים את הערך בטמפ שם. אז מה שקורה לאחר מכן? כשאני בעצם קורא להחליף הפעם, אם מגש ראשון זה כאן מייצג ראשי, מגש שני זה מייצג החלפה, כאשר אני עובר x האמפרסנד וy האמפרסנד מהראשים להחלפה, רק שיהיה ברור, מה היא קבלת מסגרת מחסנית זה? כן? קהל: [לא ברור]. דוד י מלאן: בדיוק. הכתובת של x ואת הכתובת של y. ואתה יכול לחשוב על אלה כמו כתובות דואר. רחוב אוקספורד 33 ו35 רחוב אוקספורד, ואתה רוצה להעביר את שני בניינים כי הם במקומות אלו. זה סוג של רעיון מגוחך, אבל זה כל מה שאנחנו מתכוונים בכתובת. איפה בעולם יכול אתה מוצא שני ints אלה? איפה בעולם אתה יכול למצוא שני הבניינים האלה? אז אם סוף סוף, אחרי כל מה שאני הפעם להיכנס לקוד המקור של היום ולקמפל ./swap החלפה והריצה, סוף סוף, ל פעם הראשונה שאנחנו בעצם רואים ש הערכים שלי יש אכן כבר החליף בהצלחה. ועכשיו, אנחנו יכולים אפילו לקחת פתק של ב, למשל, gdb זה. אז תן לי להיכנס לאותו הקובץ. תן לי ללכת קדימה ולהפעיל gdb של ./swap. ועכשיו, בהחלפה, אני הולך ללכת קדימה ולהגדיר נקודת הפסקה בראשים. ועכשיו אני הולך קדימה ולהפעיל את התכנית. ועכשיו אנחנו רואים את הקוד שלי עצר בקו זה. אם אני הולך קדימה והדפסה x, מה אני צריך לראות כאן? זו שאלה. אומר שוב? קהל: [לא ברור]. דוד י מלאן: אז מספרים אקראיים, אולי. אולי אני מקבל מזל, וזה נחמד ופשוט, כמו 0. אבל אולי זה חלק מהמספר אקראי. במקרה זה, יש לי מזל. זה קורה רק כדי להיות 0. אבל זה אכן מזל, כי לא עד ש הקלד הבא ולאחר מכן x ההדפסה יש ש שורת קוד, שורת 19, הוצאה להורג. בינתיים, אם אני מקליד הבא שוב, ו עכשיו להדפיס את y, אני הולך לראות 2. עכשיו, אם אני מקליד הבא, זה הולך לקבל קצת מבלבל, כי עכשיו, printf עומד להופיע על המסך, כפי שהוא עשה. x הוא 1. בואו נעשה את זה שוב. ועכשיו, הנה שבו תתחיל להיות מעניין. לפני שאני קורא להחלפה או אפילו צעד לתוך זה, בואו ניקח הצצה קטנה. x הוא, שוב, 1. Y הוא, כמובן, את שפיות מהירה לבדוק, 2, ולכן לא קשה שם. אבל מה הוא x אמפרסנד? תשובה, זה סוג של מגניב מבט. אבל כוכב int בסוגריים הוא רק דרכו של התוצר המקומי הגולמי של אומר את זה היא כתובת. זה לא int, זה מצביע ל int, או הידוע גם כתובת. מה זה הדבר המטורף הזה? אנחנו אף פעם לא ראינו משהו כמו שדי לפני. אז זה הכתובת במחשב שלי לזכרו של שבו x קורה לחיות. זה שור ומשהו. וזה, בכנות, למה אני כבר התחלתי לצייר חצים, במקום מספרים, בגלל שבאמת אכפת לו שint שלך הוא במסוים כתובת זה שגדול. אבל bffff0c4, כל אלה הם אכן ספרות הקסדצימלי, שהם 0 דרך f. אז אנחנו לא הולכים להתעכב יותר ארוך על מה הדברים האלה. אבל אם אני מדפיס את y, כמובן, אני רואה 2. אבל y האמפרסנד, אני רואה את הכתובת הזו. והודעה, לסקרן, כמה רחוק הם x, y? אתה יכול להתעלם ביותר של הכתובת. ארבעה בתים. וזה עולה בקנה אחד עם שלנו מוקדם יותר טוען שעד כמה גדול הוא int? ארבעה בתים. אז זה נראה כמו ההזדנבות של כל דבר יפה, כמו שאתה יכול לקוות, בזיכרון. אז עכשיו, בואו פשוט להריץ קדימה בסופו של הסיפור הזה. בואו נלך קדימה והקלידו צעד, לצלול לתוך פונקצית החלפה. עכשיו שימו לב, אם אני מקליד, זה זהה לכתובתו של x. אם אני מקליד ב, זה זהה לכתובתו של y. אז מה כדאי לי לראות אם אני אומרים, גש לכתובת? אז להדפיס לככב. אז כוכב פירושו ללכת לשם, בהקשר זה. אמפרסנד אומר מה הכתובת של. אז כוכב אמצעי 1. וכוכב הדפסה ב נותן לי 2. והרשה לי להניח, לרגע, כי לפחות את הקוד ש ממשיך לבצע עכשיו יכול להיות מנומק באמצעות בדרך זו. אבל אנחנו לבקר את הרעיון הזה לפני זמן רב. אז גרסה זו של החלפה נכון עכשיו ומאפשר לי שלנו להחליף סוג נתונים המסוים הזה. אז כל שאלות אז על החלפה? על כוכב? על כתובת של? ואתה תראה, עם בעיה להגדיר 4, סוג של, אבל בעיה להגדיר 5, בהחלט, איך אלה הדברים שימושיים ולקבל הרבה יותר בנוח איתם, כתוצאה. שום דבר בכלל? בסדר. אז malloc שוב הוא,, פונקציה זו שרק מקצה זיכרון, זיכרון הקצאה. ולמה זה שימושי? ובכן, כל הזמן הזה, אתה כבר משתמש malloc. אם אתה מחשיב עכשיו איך getString עבודות, מן הסתם, זה היה שואל מישהו לנתח של זיכרון, בכל עת המשתמש מקליד מחרוזת ב, כי אנחנו בהחלט לא ידע, כצוות CS50, עד כמה גדול המיתרים הללו שבני אדם הולכים להקליד יכול להיות. אז בואו, בפעם הראשונה, מתחילים לקלף בחזרה איך עובד ספריית CS50, בדרך של כמה דוגמאות שיוביל אותנו לשם. אז אם אני פותח את gedit ולפתוח scanf 0, אנחנו הולכים לראות את הקוד הבא. Scanf 0, זמין באתר האינטרנט ל היום, יש מספר קטן יחסית של שורות קוד כאן, 14 דרך 20. ובואו נראה מה הוא עושה. היא מצהירה int x נקרא,. זה אומר מספר כמו משהו, בבקשה. ועכשיו זה אומר, אני% scanf, וx. אז יש כל מיני דברים חדשים שיש. אבל scanf, אתה יכול סוג של חושב נכון להיפוכו של printf. printf, כמובן, הדפסים למסך. סוג scanf של סריקות מהמשתמש של מקלדת משהו שהוא או היא הוקלדה. היא i% בדיוק כמו printf. משמעות הדבר היא לצפות משתמש להקליד int. ועכשיו, למה אתה חושב שאני יכול להיות שעובר scanf & x? אם המטרה בחיים של scanf הוא לקבל משהו מהמשתמש, מהי המשמעות של העברתו, וx, עכשיו? כן? קהל: [לא ברור]. דוד י מלאן: בדיוק. לא משנה מה אני, האדם, להקליד, הקלט שלי הוא הולך להיות נשמר במיקום זה. זה לא מספיק, זוכר, רק לעבור בx, משום שראינו כבר, כל פעם שאתה עובר רק משתנה גלם, כמו int, לתפקיד אחר, בטוח, זה יכול לשנות את זה משתנה, אבל לא באופן קבוע. זה לא יכול להיות השפעה על ראשי. זה יכול לשנות רק העותק המקומי שלה. אבל אם, במקום זאת, אתה לא תן לי את int בפועל, אבל אתה נותן לי כיוונים ל int ש, אני עכשיו, להיות scanf, בוודאי, אני יכול לעקוב אחר ש לטפל ולשים מספר שם אז יש לך גישה אליו גם כן. לכן, כאשר אני מפעיל תכנית זו, בואו נראה. הפוך scanf 0 לוכסן נקודה, scanf 0. ואם אני עכשיו להקליד מספר כמו 50, תודה על 50. אם אני עכשיו להקליד מספר כמו 1 שלילי, ל1 השלילי. עכשיו אני מקליד מספר כמו 1.5, HM. מדוע התכנית שלי מתעלמת ממני? ובכן, בגלל שפשוט, אמרתי לי זה לצפות int בלבד. בסדר. אז זה גרסה אחת של זה. בואו ניקח את דברים ברמה גבוהה ו מציע שזה לא טוב. וכאן טמון דוגמא פשוטה מאוד איך אנחנו יכולים להתחיל כתיבת קוד שאנשים אחרים יכולים לנצל או להתפשר על ידי עושה דברים רעים. אז שורה 16, כל כך דומה ברוחו ללפני, אבל אני לא הכריז עליו int זה זמן. אני מכריז כוכב char זה, aka מחרוזת. אבל מה זה באמת אומר? אז אם אני לא לציין address-- ו אני קורא לזה באופן שרירותי, חיץ, אבל אני יכול לקרוא לזה זה, להיות simple-- ואז אני עושה את זה, אסביר לי, אם אתה יכול, על בסיס הקודם היגיון, מה הוא עושה scanf בשורה 18, אם% s לעבור וחיץ, אשר היא כתובת? מה הוא scanf, אם תחיל את בדיוק באותו היגיון כמו גרסה 0, הולך לנסות לעשות כאן, כאשר משהו משתמש מקליד? כן? קהל: [לא ברור]. דוד י מלאן: בדיוק. Scanf, על ידי ההיגיון קודם לכן, הוא הולך לקחת את המחרוזת שמוקלד האנושית in-- זה עכשיו מחרוזת, זה לא מספר, ככל הנראה, אם הוא או היא cooperates-- וזה הולך לנסות לשים את זה מחרוזת בזיכרון בכל מה כתובת חיץ מציין. וזה נהדר, כי חיץ נועד אכן להיות כתובת. אבל אני טוען שתכנית זו היא מרכבה ב דרך מאוד רצינית, כי מה הוא הערך חיץ כברירת מחדל? מה יש לי אותחל ל? מה נתח של זיכרון? יש לי לא, נכון? אז למרות שאני כבר הוקצה כוכב char זה נקרא כבר לא של, זה נקרא במקום, buffer-- כך בואו נצייר את שמו של משתנה עכשיו כbuffer-- אם יש לי לא נקרא getString או malloc כאן, שלמעשה אומר ש חיץ הוא רק חלק ערך זבל. עכשיו מה זה אומר? זה אומר שיש לי אמר לי scanf לצפות מחרוזת מהמשתמש. ואתם יודעים מה? לא משנה מה הדבר הזה מצביע to-- ואני מצייר סימן שאלה, אבל במציאות, זה הולך להיות משהו כמו OX1, 2, 3, נכון? זה חלק מהערך מזויף שרק במקרה היה שם לפני. אז במילים אחרות, זה כאילו חיץ הוא רק מצביע על משהו בזיכרון. אין לי מושג מה. אז אם אני מקליד בגייב עכשיו, זה הולך כדי לנסות לשים g--b-e / 0 שם. אבל מי יודע מה זה? ובעבר, כל זמן שניסינו לגעת זיכרון שאינו שייך לנו, מה קרה? או כמעט בכל פעם. אשמת פילוח, נכון? החץ הזה, אין לי מושג איפה זה הצבעה. זה רק חלק ערך אקראי. וכמובן, אם אתה מפרש ערך אקראי ככתובת, אתה הולך ללכת ל כמה יעד אקראי. אז אכן אולי גייב התרסקות התכנית שלי במקרה הזה כאן. אז מה אנחנו יכולים לעשות את זה כמעט כמו רע? חשוב על זה שלישי ו הדוגמא האחרונה של scanf. גרסה זו היא טובה יותר באיזה מובן? אם אתה חש בנוח עם בעיה קודמת, זה טוב יותר. למה? קהל: [לא ברור]. דוד י מלאן: טוב. אז המקרה הזה של קו 16 הוא טוב יותר, במובן שאנחנו באופן מפורש הקצאת חלק זיכרון. אנחנו לא באמצעות malloc, אנחנו משתמשים בשבוע 2 גישה של רק הגדרה של מערך. ושאמרנו בעבר כי מחרוזת הוא פשוט מערך של תווים, אז זה לגיטימי לחלוטין. אבל זה, כמובן, כ שים לב שאתה, גודל קבוע, 16. אז תכנית זו היא בטוח לחלוטין, אם אני מקליד במחרוזות תווים אחת, שני אופי מחרוזות, 15 מחרוזות תווים. אבל ברגע שאני מתחיל להקליד 16, 17, 18, 1,000 מחרוזות תווים, שבו היא המחרוזת שהולכת בסופו? זה הולך בסופו של חלקו כאן. אבל אז מי יודע מה עוד הוא מעבר לגבולות של מערך המסוים הזה? זה כאילו שיש לי הכריז 16 תיבות כאן. אז במקום להוציא את כל 16, אנחנו רק להעמיד פנים שאני נמשך 16. אבל אם אני לאחר מכן נסה לקרוא מחרוזת זה עוד הרבה זמן, כמו 50 תווים, אני הולך להתחיל לשים , b, c, d, x, y, z. וזה הוא ככל הנראה כמה מקטע זיכרון אחר כי, שוב, עלול לגרום התכנית שלי לקרוס, כי אני כבר לא ביקשתי כל דבר יותר מסתם 16 בתים. אז למי אכפת? ובכן, הנה ספריית CS50. וביותר לכך הוא פשוט כמו הוראות למעלה. ספריית CS50, כל הזמן הזה, יש לו את הקו הזה בשורה 52. ראינו typedef, או תוכל לראות typedef בpset 4, שרק יוצר מילה נרדפת לפי הכוכבים char יכולים להיות יותר פשוט מכונה מחרוזת. אז זה אחד כמה גלגלים עזר אנחנו השתמשנו בחשאי מתחת למכסת המנוע. בינתיים, הנה הפונקציה, getchar. עכשיו כנראה, אין גוף אליו. ולמעשה, אם אני שומר גלילה, אני לא ממש לראות את כל יישומים של פונקציות אלה. כבדיקת שפיות, למה זה? קהל: [לא ברור]. דוד י מלאן: כן. אז זה בקובץ הכותרת. וקבצי כותרת מכילים אב טיפוס, ועוד כמה דברים אחרים, כך נראה, כמו typedefs. אבל בCS50.c, שיש לנו אף פעם לא נתתי לך על הסף, אבל כבר במכשיר CS50 כל הפעם, עמוק בתוך התיקיות שלה, שם לב שיש כל חבורה של פונקציות בכאן. למעשה, בואו לגלול למטה. בואו נתעלם רובם, לעת עתה. אבל לגלול למטה כדי getInt ולראות איך getInt עובד. אז הנה getInt. ואם אי פעם באמת היה אכפת לך איך להגיע int עובד, כאן הוא התיעוד שלה. ובין הדברים זה אומר שזה אומר לך מה הטווחים של ערכים שהיא יכולה לחזור. זה בעצם שלילי של 2 מליארד ל2 חיוביים מיליארדים, פלוס מינוס. ומתברר, כל זה זמן, למרות שאנחנו אף פעם לא היה לך לבדוק את זה, אם משהו משתבש, מתברר שכל הפעם, יש getInt כבר חוזר מיוחד קבוע, לא ריק, אלא int_max, שהוא האמנה רק של מתכנת. זה אומר שכאן הוא ערך מיוחד. הקפד לבדוק את זה, רק במקרה שמשהו משתבש. אבל אנחנו אף פעם לא הפרענו לי עם כי עד כה, כי שוב, זה נועד לפשט. אבל איך getInt מיושם? ובכן, אחד, זה לא לוקח ארגומנטים. אנחנו יודעים את זה. זה מחזיר int. אנחנו יודעים את זה. אז איך זה עובד מתחת למכסת המנוע? אז יש כנראה אינסופי לולאה, לפחות את המראה של אחד. שים לב שאנו משתמשים getString. אז זה מעניין. getInt קוראת הפונקציה שלנו, getString. ועכשיו למה זה עלול להיות המקרה? למה אני מתגונן כאן בשורה 165? מה יכול לקרות בקנה 164, רק שיהיה ברור? זה את אותה תשובה כמו קודם. יכול להיות רק מתוך זיכרון. משהו משתבש עם getString, אנחנו חייבים להיות מסוגלים להתמודד עם זה. והסיבה שאני לא אחזיר null הוא כי, מבחינה טכנית, null הוא מצביע. getInt יש לחזור int. אז יש לי באופן שרירותי החליט, בעצם, כי 2 מיליארדים, פחות או יותר, הוא הולך להיות ערך מיוחד שאני אף פעם לא יכול למעשה לקבל מהמשתמש. זה רק ערך אחד אני הולך לבזבז לייצג קוד שגיאה. אז עכשיו, דברים לקבל קצת מפואר. וזה לא ממש את אותו התפקיד כמו קודם, אבל זה דומה מאוד. אז שם לב, אני מצהיר כאן, בקו 172, שני n int וג char. ואז אני משתמש בשורה פאנקי זה, sscanf, שמתברר אינו סורק מחרוזת מהמקלדת. זה עומד מחרוזת קיימות ש המשתמש כבר הקליד ב. אז אני כבר נקראתי getString, ש משמעות הדבר היא שיש לי מחרוזת בזיכרון. sscanf הוא מה שהיית לקרוא לפונקצית ניתוח. זה נראה במחרוזת יש לי הקליד ב, תו אחרי תו, ועושה משהו מועיל. המחרוזת שמאוחסן בקו. ואני יודע שרק על ידי הולך לגבות כאן ואומר, אוי, אישור, אני קראתי לזה לא של הזמן הזה, אבל קו. ועכשיו זה קצת שונה. אבל זה למעשה אומר, מסיבות אנחנו מעט ננפנף בידות שלנו בימינו, שאנחנו בודקים ל לראות אם משתמש הקליד ב וint ואולי דמות אחרת. אם משתמש הקליד בint, זה הולך להיות מאוחסן בn, כי אני לעבור את זה על ידי כתובת, טריק חדש שראינו היום. אם המשתמש גם הקלדה ב123x כמו, x ש הוא הולך בסופו של מכתב בתו ג. עכשיו מתברר sscanf ש יגיד לי, בתבונה, כמה משתנים היה sscanf בהצלחה מסוגלת למלא. אז לפי ההיגיון הזה, אם הפונקציה אני מיישם הוא getInt, אבל אני בודק, פוטנציאל, עבור המשתמש להקלדה בint ואחריו משהו אחר, מה אני רוצה sscanf של ערך החזרה באמת להיות? אם המטרה היא להגיע רק int מהמשתמש? אז אם sscanf חוזר 2, מה זה אומר? משתמש הקליד ב משהו כמו, פשוטו כמשמעו, 123x, וזה רק שטויות. זה מצב שגיאה, ו אני רוצה לבדוק את זה. אז אם משתמש מקליד את זה, על ידי ההיגיון הזה, מה עושה sscanf לחזור, היית אומר? אז זה הולך לחזור 2, כי 123 הוא הולכים לכאן, וx הולך בסופו של כאן. אבל אני לא רוצה x כדי לקבל מולא. אני רוצה sscanf להצליח רק ב המילוי הראשון של המשתנים שלה. ואז בגלל זה אני רוצה sscanf לחזור 1. ואם זה קצת מעל הראש לרגע, זה בסדר לגמרי. מבין זאת, כי אחד ערכים של getInt וgetString הוא שאנחנו עושים לעזאזל של הרבה בדיקת שגיאות כמו זה כל כך כי, נכון להיום, אתה יכול פחות או יותר הקלד כל דבר במקלדת שלך, ואנחנו נתפוס אותו. ואנחנו בהחלט, צוות, בהחלט לא להיות המקור של באג בך תכנית, בגלל שאנחנו בהתגוננות בדיקה לכל הטיפשים דברים שהמשתמש עשוי לעשות, כמו הקלדת מחרוזת, כאשר אתה באמת רוצה int. אז לnow-- אנחנו נבוא בחזרה לזה לפני long-- אבל כל הזמן הזה, יש לי getString וgetInt היה מתחת למכסת המנוע באמצעות זה רעיון בסיסי של כתובות זיכרון. אז עכשיו, בואו נעשה את הדברים קצת יותר ידידותי למשתמש. כזכור, מהינקי האחרון time-- אם העכבר שלי יהיה cooperate-- כך היו לנו קוד, זה ש בכנות, הוא די שטותי. קוד זה אינו משיג דבר שימושי, אבל זה היה הדוגמא פרופסור שParlante משמש כדי לייצג מה קורה ב התכנית הכרוכה בזיכרון. אז בואו לספר זה סיפור בקצרה סופר. שתי שורות הראשונות אלה, ב אנגלית, אין מה, היית אומר? רק באופן סביר אנושי, אבל מעט מונחים טכניים, לקחת דקירה. קהל: [לא ברור]. דוד י מלאן: אישור, אתה הקמת כתובות לx שלך ומשתני y. לא ממש, כי x, y אינו משתנים במובן המסורתי. x ו y הם כתובות או ישמור את כתובת. אז בואו ננסה את זה עוד פעם אחת. התחלה לא רעה, אם כי. כן? קהל: [לא ברור]. דוד י מלאן: טוב. אני חושב שזה קצת יותר נקי. הכרזת שני מצביעים, שני מספרים שלמים. ואנחנו קוראים להם x, y. או אם היינו לצייר זה כתמונה, שוב, זוכר בפשטות שכל אנחנו עושים עם זה שורה הראשונה הוא ציור תיבה כמו זו, עם קצת ערך זבל בזה, וקורא לזה X, ולאחר מכן קופסא אחרת כמו זה, עם קצת ערך זבל בזה, קורא לזה y. אנחנו כבר הכריזו שני מצביעים שסופו של דבר ישמור את הכתובת של int. אז זה כל מה שיש. לכן, כאשר בינקי עשה את זה, חימר רק נראה כך. וניק פשוט סוג של עטוף חצים, כאילו הם לא מצביעים לשום מקום בפרט, כי הם פשוט ערכי זבל. הם לא אותחלו במפורש בכל מקום בפרט. עכשיו השורה הבאה של קוד, כזכור, היה זה. אז באופן סביר ידידותי למשתמש, אבל אנגלית הטכנית במידה מה, מה היא שורת קוד הזאת עושה? כן? קהל: [לא ברור]. דוד י מלאן: מושלם. זה הקצאת הנתח של זיכרון זה בגודל של int. וזה חצי מהתשובה. אתה ענה נכון מחצית מהביטוי. מה שקורה ב צד השמאלי של סימן השוויון? כן? קהל: ומקצה זה לx משתנה? דוד י מלאן: ומקצה זה לx משתנה. אז כדי לסכם, מקצה צד ימני מספיק זיכרון כדי לאחסן int. אבל באופן ספציפי malloc מחזיר את הכתובת של נתח זה של זיכרון, שיש לך רק הציע מקבל מאוחסן בx. אז מה ניק עשה בפעם קודמת עם בינקי הוא הוא גרר את המצביע שיצא, החימר, להצביע עכשיו בנתח לבן של זיכרון כי הוא שווה לגודל של int. ואכן, שאמורה לייצג ארבעה בתים. עכשיו, השורה הבאה של קוד עשיתי את זה, x הכוכב מקבל 42. אז 42 הוא פשוטים על צד ימני, משמעות חיים. צד שמאלי, x כוכב פירושו מה? גם שאולי יש לי gone-- זה בסדר. אישור. קהל: בעיקרון, ללכת ל[ לא ברור] דוד י מלאן: טוב. קהל: [לא ברור]. דוד י מלאן: בדיוק. צד שמאל פירושו ללכת לx. x הוא כתובת. זה כמו רחוב 33 אוקספורד, או OX1. וx כוכב פירושו ללכת לזה לטפל ולשים את מה שיש? 42. אז אכן, זה בדיוק מה שניק עשה. הוא התחיל עם על ידי, בעצם, מבחינה נפשית הפנה אצבע מאשימה x, בעקבות החץ לקופסא הלבנה על יד ימין צד, ולשים את המספר 42 שם. אבל אז יש דברים קצת מסוכן, נכון? בינקי של עומד לאבד את ראשו. y הכוכב שווה 13, מזל רע, פירושו מה? אז אמצעי y כוכב ללכת לכתובת בy. אבל מה היא הכתובת בy? בסדר, זה ערך זבל, נכון? ציירתי אותו כסימן שאלה. ניק משך אותו כחץ מכורבל. וברגע שאתה מנסה לעשות y כוכב, אומר ללכת לשם, אבל יש לא לגיטימי כתובת, זה חלק מיקום מזויף, התכנית הולכת לקרוס. וראשו של בינקי הוא הולך לעוף מכאן, כפי שהוא עשה. אז בסופו של הדבר, תכנית זו היה רק ​​פגם החוצה שטוח. זו הייתה תכנית מרכבה. וזה צריך להיות קבוע. והדרך היחידה, באמת, כדי לתקן את זה יהיה, למשל, את הקו הזה, שאנחנו אפילו לא הגענו ל, כי התכנית התרסקה מוקדם מדי. אבל אם היינו לתקן את זה, מה ש אפקט עושה עושה לי x שווה y? ובכן, זה בעצם מצביע y ב מה ערך של x הוא מצביע ב. אז בסיפורו של ניק, או סיפורו של בינקי, שניהם x, y היה מצביע על הנתח הלבן של זיכרון, כך שלבסוף, כאשר אתה אל לככב y שווה 13 שוב, אתה בסופו של דבר לשים 13 ב המיקום המתאים. אז כל הקווים האלה הם בצורה מושלמת לגיטימי, פרט לזו אחת, כשזה קרה לפני ש למעשה הוקצה y ערך כלשהו. עכשיו לשמחתי, שאתה לא יודע יש לי למצוא היגיון בתוך כל מסוגים אלה של בעיות בעצמך. תן לי ללכת קדימה ולפתוח עד חלון מסוף כאן ולפתוח, רק לרגע, תכנית סופר קצרה ש גם הוא סוג של טעם. זה מכוער. זה לא להשיג שום דבר שימושי. אבל זה להדגים סוגיות של זיכרון, אז בואו נסתכל. ראשי, סופר פשוט. זה כנראה קורא פונקציה, f, ולאחר מכן מחזירה 0. זה קצת קשה לבלגן הזה. אז ראשי הוא די טוב, עד כה. אז f היא בעייתית. ופשוט לא לשים הרבה מאמץ ליום זה כאן, לשמור את הפוקוס על הקוד. יש f שני קווים. ובואו נראה מה עכשיו קורה. אז מצד האחד here-- ותנו לי לעשות זה עולה בקנה אחד עם הקודם example-- מצד האחד, הצד השמאלי הוא עושה את מה ש, באנגלית? זה is-- קהל: יצירת מצביע. דוד י מלאן: יצירת מצביע לint וקוראים לזה x. אז זה יוצר את אחת קופסות האלה אני כל הזמן ציור על מסך המגע. ועכשיו, ביד ימין צד, malloc, כמובן, מקצה נתח של זיכרון. ורק שיהיה ברור, איך הרבה זיכרון זה כנראה הקצאה, אם אתה רק לעשות סוג של המתמטיקה כאן? אז זה 40 בתים. ואני יודע שרק בגלל שאני יודע int, על מכשיר CS50, לפחות, הוא ארבעה בתים. אז 10 פעמים 4 הוא 40. אז זה אחסון x, כתובת של את הראשון של 40 ints ש הוקצו שטח בחזרה, לגבות, לגבות, לגב. וזה מה שחשוב על malloc. זה לא לוקח קצת זיכרון כאן, קצת פה, קצת פה. זה נותן לך חתיכה אחת של זיכרון, בסמיכות, מההפעלה מערכת. עכשיו מה לגבי זה, x סוגר 10 שווה 0? שורה שרירותית של קוד. זה לא להשיג שום דבר שימושי. אבל זה מעניין, כי סוגר x 10--? כן? קהל: [לא ברור]? דוד י מלאן: סוגר x 10 לא צריכים להיות null. פירוט null מגיע רק למשחק עם מחרוזות, בסוף המחרוזת. אבל מחשבה טובה. כמה גדול הוא מערך זה, אפילו אם כי אני כבר הוקצה 40 בתים? זה 0 עד תשע, נכון? זה 10 ints, סך הכל. 40 בתים, אבל 10 ints, אינדקס 0 דרך 0. אז מה הוא שסוגר x 10? זה בעצם חלק ערך זבל לא ידוע. זה זיכרון שלא שייך לי. אני לא צריך להיות נגיעה ש בתים מספר 41, 42, 43, 44. אני הולך מעט רחוק מדי. ואכן, אם אני מפעיל את זה תכנית, ייתכן מאוד לקרוס. אבל לפעמים, יהיה לנו מזל. וכך, רק כדי להפגין זה- ולמען אמת, אתה אף פעם לא יודע לפני שאתה אל it-- בואו נריץ את זה. זה לא לקרוס למעשה. אבל אם אני משנה את זה, עבור למשל, להיות כמו 1,000, כדי להפוך את זה באמת מכוון, בואו לראות אם אנחנו יכולים לקבל את זה כדי לקרוס הפעם. בסדר, זה לא לקרוס. מה דעתך על 100,000? בואו לעצבו מחדש, ועכשיו להפעיל מחדש את זה. אישור. אוף. בסדר. אז כנראה, שוב, אלה מקטעי זיכרון, אם אפשר לומר כך, הם גדולים באופן סביר, כדי שנוכל מזל שוב ושוב. אבל סופו של דבר, ברגע שאתה מקבל מגוחך ובאמת ללכת רחוק על המסך, אתה נוגע בזיכרון, כי באמת, ממש לא שייך לך. אבל בכנות, אלה מיני חרקים הולכים להיות קשה יותר ויותר כדי להבין בעצמך. אך לשמחתם, כמתכנתים, יש לנו כלים המאפשרים לנו לעשות את זה בשבילנו. אז זה, אולי, אחד של התוכניות המכוערות ביותר, אפילו מכוער יותר מהתפוקה של gdb. אבל תמיד יש לו קו או שניים שהם סופר שימושיים. Valgrind היא תכנית שמסייעת לי אתה לא באגים בתכנית, כשלעצמה, אבל למצוא זיכרון הקשורות בעיות, במיוחד. זה באופן אוטומטי להפעיל הקוד שלך ל אתה ולחפש לפחות שני דברים. אחת, עשית משהו מקרי כמו מגע זיכרון שלא שייך לך? זה יעזור לך למצוא אותם מקרים. ושני, זה יעזור לי אתה מוצא משהו שנקרא דליפות זיכרון, שיש לנו לגמרי התעלם, בתמימות, לכמה זמן ואושר. אבל מתברר, כל הפעם, בכל פעם ש שנקראת getString ב כל כך הרבה התוכניות שלנו, אתה שואל הפעלה מערכת לזיכרון, אבל יש לך זיכרון אי פעם לתת לו בחזרה, unalloc עושה, או חופשי, כפי שהוא נקרא. לא, כי יש לנו לא ביקשתי ממך לעשות זאת. אבל כל הזמן הזה, התוכניות אתה כבר כותב בC כבר דולף זיכרון, מבקש ההפעלה מערכת ליותר ויותר זיכרון עבור מחרוזות ומה לא, אך מעולם לא החזיר אותו. ועכשיו זה קצת של פשטנות, אבל אם יש לך אי פעם להריץ את Mac שלך או המחשב שלך די זמן, פתיחת חלק הרבה תוכניות, אולי לסגור תוכניות, ואף על פי ש מחשב לא התרסק, זה מתחיל להיות כל כך הרבה יותר איטי, כאילו שזה באמת באמצעות הרבה זיכרון או משאבים, למרות ש, אם אתה אפילו לא לגעת במקלדת, שיכול be-- אבל לא יכולתי always-- להיות שהתוכניות שאתה מפעיל יש להם דליפות זיכרון. והם כל זמן שואלים את מערכת ההפעלה ליותר ו יותר זיכרון, אבל שוכח על זה, לא ממש משתמש בו, אבל לכן לוקח זיכרון משם מתוכניות אחרות שאולי תרצו את זה. אז זה הסבר נפוץ. עכשיו הנה שבי Valgrind של פלט הוא לגמרי זוועתי פחות אלה יותר ונוח יותר כאחד. אבל המעניין דברים נכון עד כאן. זה אומר לי לכתוב לא חוקי של גודל ארבעה קורה בתכנית זו, בפרט, בשורה 21 של memory.c. אם אני הולך לשורה 21, HM, יש אכן הוא כתיבה לא חוקית בגודל ארבעה. למה גודל ארבעה? ובכן, number-- זה וזה יכול להיות anything-- הוא int. אז זה ארבעה בתים. אז אני שם את ארבעה בתים שבו הם לא שייכים. זה מה שValgrind הוא למעשה אומר לי. יתר על כן, גם זה יהיה תגיד לי, כפי שנראה, כפי שאתה מפעיל את זה בpset עתיד, אם ו כשאתה כבר דלף זיכרון, שאכן יש לי, כי אני כבר בשם malloc, אבל יש לי לא ממש בשם, במקרה זה, ללא תשלום, שסופו של דבר יראו הוא היפוכו של malloc. אז עכשיו, אני חושב, דוגמא אחרונה. אז זה אחד מהם קצת יותר מסתורי, אבל זה אולי הסיבה הגדולה ביותר ל להיות זהיר עם זיכרון, ותוכניות הסיבה שרבות ו / או שרתי אינטרנט, אפילו עד עצם היום הזה, הם השתלטו על הרעים איפשהו באינטרנט שאיכשהו משלוח מנות מזויפות לשרת שלך מנסה להתפשר החשבונות שלך, או לקחת את הנתונים שלך, או סתם בדרך כלל להשתלט על מכונה. גלישת מאגר, כ שם מרמז, אמצעים גדות לא int, אבל חיץ. וחיץ הוא רק דרך מפוארת לומר שזה חבורה של זיכרון. ואכן, אני נקרא מחרוזת לפני חיץ, במקומו של. מכיוון שאם זה חיץ, כמו במובן של YouTube, או בכל זמן שאתה צופה בוידאו, שאולי ראה את מילת החציצה, הנקודה, נקודה, נקודה. זה מעצבן מאוד. וזה רק אומר ש שנגן הווידאו שלך מנסה להוריד הרבה של בתים, הרבה בתים מוידאו מהאינטרנט. אבל זה איטי, כך שהוא מנסה להוריד חבורה שלהם כדי למלא את מאגר, מיכל, כך ש יש לך מספיק בתים שלאחר מכן יכול להראות לך וידאו, בלי לעצור כל הזמן. אבל מתברר, שאתה יכול יש לי חיץ לזה גדול. אבל תנסה לשים את כמות הנתונים זו ב זה, ומאוד דברים רעים יכולים לקרות. כך למשל, בואו נסתכל על טיזר האחרון של ירושלים. זוהי תכנית אחרת כי, במבט ראשון, לא עושה שום דבר סופר שימושי. יש לו תפקיד ראשי שקורא פונקציה ש, f. ופונקציה ש, f, עד כאן, יש לי מערך תווים, הנקרא ג, בגודל 12. ואז זה מנצל את זה פונקציה חדשה בשם strncpy. מתברר כי, עם זה פשוט, קו פשוט של קוד, רק שתי שורות, עשינו כל התכנית שלי, ולכן, כל המחשב שלי, והחשבון שלי למשתמש, ושלי קשה לנהוג שעלול להיות פגיע לאף אחד מי יודע, והוא טוב מספיק כדי להפעיל תכנית זו עם שורת הפקודה מסוימת טיעון. במילים אחרות, אם האיש הרע הזה מעמיד על ידי הקלדה בתוך argvargv [1] במקלדת מאוד בעלת מבנה מיוחד מחרוזת, לא abc, 123, אבל במהותו, סימנים בינארי שמייצגים הפעלה קוד, תכנית שהוא או היא כתבה, עם תוכנה פשוטה זו, שהיא נציג של אלפי תוכניות כי הם דומים פגיעים, מעזים לומר, הוא או היא סופו של דבר יכולה למחוק את כל הקבצים בכונן הקשיח שלי, לקבל מהבהב הפקודה, כך הוא או היא יכולה להקליד פקודות בכוחות עצמם, דוא"ל את כל הקבצים לעצמי. כל דבר שאני יכול לעשות, הוא או שהיא יכולה לעשות עם הקוד הזה. אנחנו לא ממש לפתור את זה עדיין. ולמעשה, זה הולך כרוך קצת תמונה כמו זה, שבו אנו בקרוב נבוא כדי להבין מה טוב. אבל היום, בואו יסתיימו ב מה, אני מקווה, מעט יותר בדיחה xkcd מובנת, עד שנתחדש בפעם הבאה. בסדר. לראות אותך ביום רביעי. [השמעת מוסיקה] דובר: ועכשיו, עמוק מחשבות, על ידי ךייבן Farnham. זיכרון הוא כמו לקפוץ לתוך ערימת עלים זהובים ביום ראשון אחר הצהריים. רוח נושבת, משליך שלך hair-- הו, אני מתגעגע לימים when-- [שחוק]