[השמעת מוסיקה] דוד י מלאן: בסדר. זה CS50, וזה הוא סוף השבוע ארבע. והיום אחד מהנושאים היא זו של זיהוי פלילי דיגיטלי, אמנות מחל מידע. ואכן, אף על פי ש אתה באמצע עכשיו שלום בשלוש ובריחה, בשבוע הבא, הדגש יהיה על דווקא תחום זה. אז באחד התפקידים הכי מגניב שאי פעם היה לי היה בחזרה בבית הספר לתואר שני, כשעבדתי עבור המקומי מידלסקס קאונטי התובע המחוזי של משרד, זיהוי פלילי עושה עבודה. אז בעצם, מסצ'וסטס משטרת המדינה, בהזדמנות, כאשר עובד על מקרים היית להביא דברים כמו כוננים קשיחים ודיסקטים ו כרטיסי זיכרון וכדומה. והם היו למסור אותם אליי והמורה הרוחני שלי, והמטרה שלנו הייתה למצוא ראיות, אם היה, באמצעי התקשורת אלה. הצצות עכשיו, שאולי ראו העולם הזה של זיהוי פלילי בתקשורת, הטלוויזיה והסרטים. אבל העבודה שהייתה לי, ו מניח שעולם, הוא לא בדיוק כמו שהיית רואה את זה. בואו נסתכל על מה ש יש לך כנראה ראה. [וידאו השמעה] "או-קיי. עכשיו, בואו לקבל מבט טוב עליך. [השמעת מוסיקה] -Hold זה. הפעל את זה בחזרה. -Wait דקות. ללכת ימינה. ואכן. להקפיא את זה. -Full מסך. "או-קיי. להקפיא את זה. -Tighten על ש, יהיה לך? -Vector שב בחור בגלגל האחורי. -Zoom בממש כאן במקום הזה. -עם הציוד הנכון, תמונה יכולה להיות מוגדלת וחדדה. 'מה זה? "כבר תכנית שיפור. "אתה יכול ברור שעד כל? 'אני לא יודע. בואו לשפר אותו. -Enhance סעיף A6. אני משופר הפרט, and-- 'אני חושב שיש מספיק כדי לשפר. לשחרר אותו למסך שלי. 'אני משופר ההשתקפות בעיניה. 'תן מנוהל זו דרך שיפור וידאו. -Edgar, אתה יכול לשפר את זה? -Hang ב. "יש לי עובד על השתקפות זו. ההשתקפות של מישהו של ואכן. -Reflection. ואכן זה השתקפות של פניו של האיש. השתקפות -The! ואכן השתקפות. -Zoom במראה. אתה יכול לראות את השתקפות. "אתה יכול לשפר את התמונה מכאן? "אתה יכול לשפר אותו? "אתה יכול לשפר אותו? "בסדר." "החנות לשפר את זה? "אתה יכול לשפר אותו? -Hold בשני. אני לשפר. -Zoom בדלת. -Times 10. -Zoom. הזז ב. -More. -Wait, לעצור. -Stop. -Pause זה. -Rotate 75 מעלות סביב האנכי, בבקשה. -Stop. חזור לחלק על הדלת שוב. -Got משפר תמונה שיכול מפה סיבית? -אולי אנו יכולים להשתמש סינג Pradeep שיטה לראות בחלונות. -The תוכנה היא מדינה של האמנות. -The ערך עצמי כבוי. -עם תקין שילוב של algorithms-- התאורה נלקחה של -הוא אלגוריתמים לשלב הבא, ואני יכול להשתמש בם כדי לשפר את התצלום הזה. -Lock ובלהגדיל את ציר z. -Enhance. שפר. -Enhance. -Freeze ולשפר. [END הפעלת וידאו] דוד י מלאן: אז אלה הם כל המילים, אבל הם לא היו שימוש במשפטים בצורה נכונה. ואכן בעתיד, כל עת, אנא, אתה שומע מישהו אומר את המילה, "לשפר", צחקוק רק קצת. כי כשאתה מנסה לשפר, למשל, זה מה שקורה. אז הנה תמונה מדהימה. זה ךייבן של CS50. ונניח שאנחנו רוצים להתמקד בניצוץ בעיניים שלו, או ההשתקפות של איש רע שהיה באופן ברור שנתפס על ידי מצלמת האבטחה. זה מה שקורה כאשר לך להתמקד על תמונה ש יש רק מספר סופי ביטים הקשורים אליו. זה מה שהיית מקבל. ואכן, בעיניו של דייבן אינו אלא ארבעה, אולי שישה פיקסלים שמרכיבים בדיוק את מה ש היה מנצנץ שם. אז הבעיה סט ארבעה סופו של דבר יש לי לך לחקור את העולם הזה, במיוחד על ידי טבעו של משהו אנו קוראים לי קובץ / o, שבו i / o היא רק דרך מפוארת של אומר קלט ופלט. אז עד כה, כל האינטראקציות שהיינו לנו עם מחשב היה במידה רבה עם שלך מקלדת והמסך, אבל לא כל כך הרבה עם הדיסק הקשיח, או שמירה של קבצים מעבר לאלה שאתה את עצמך לכתוב. התוכניות שלך עד כה יש לי לא היה יצירת, ושמירה, ועדכון הקבצים שלהם. ובכן, מה קובץ? ובכן, משהו כמו JPEG. זוהי תמונה אולי אתה יש להם או להעלות לפייסבוק, או לראות בכל מקום באינטרנט. ואכן, תמונה שאנחנו פשוט מסור של ךייבן היה JPEG. ומה שמעניין על קבצים כמו תמונות JPEG הוא שהם יכולים להיות מזוהים, בדרך כלל, על ידי דפוסים מסוימים של ביטים. במילים אחרות, מהו דבר ש מבחין JPEG מGIF מPING מWord מסמך מקובץ Excel? ובכן, זה פשוט שונה דפוסים של ביטים. ודפוסים שונים אלה בדרך כלל בתחילת קבצים אלה. כך שכאשר המחשב שלך פותח Word doc, או כאשר מחשב נפתח JPEG, זה נראה בדרך כלל ב כמה ביטים הראשונים בקובץ. ואם היא מכירה דפוס, זה אומר, אה, זה הוא תמונה. תן לי להציג אותו ל המשתמש כגרפי. או, הו, זה נראה כמו Word דוק. תן לי להראות אותה למשתמש כמאמר. כך למשל, בפורמט JPEG, מתברר, הם מתוחכם למדי מתחת למכסה המנוע. אבל שלושה הבתים הראשונים ברוב בכל JPEG להתחיל עם שלושת המספרים האלה. אז הבתים אפס, אחד, ושתיים, ב כמעט בכל JPEG, 255, לאחר מכן את המספר 216, לאחר מכן את המספר 255. ומה אתה יכול להתחיל לעשות בשבוע הבא למעשה תוקע מתחת מכסה המנוע של קבצים כמו תמונות JPEG וכמו קבצי מפת סיביות, ורואה מה שתמיד היה שם בשביל עוד כפי שאתה כבר משתמש במחשב. אבל מה שאין בדרך כלל נכתב כמו מספרים עשרוניים כמו זה. מדעני מחשב לא נוטה לדבר בעשרוני. הם לא באמת מדברים בינארי. בדרך כלל, כאשר אנו רוצים להביע את המספרים, אנחנו בעצם להשתמש הקסדצימלי, שאולי זכור לך מ, למשל, בעיה סט אחת, שקרא תיגר על שתחשוב על מערכת שונה. אנחנו, כמובן, מכירים עם עשרוני, אפס עד תשע. דברנו על בינארי. ולא באמת יש לנו להשתמש כל כך הרבה כאן על החוצה, משום שמחשבים ישתמשו בזה. אבל מתכנתים מאוד יהיו לעתים קרובות, אך לא תמיד, להשתמש הקסדצימלי, שרק אומר יש לך 16 אותיות באלפבית שלך, בניגוד לשתיים או 10. אז איך אתה לספור עד גבוה מתשעה בהקסדצימלי? אתה הולך 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, , b, c, d, e, f, רק על ידי ועידה. אבל מה מפתח הוא שכל אלה הוא סמל יחיד. אין 10. אין 11, כשלעצמה, משום שכל אחד הספרות שלך, בדיוק כמו בעשרוני ובדיוק כמו בינארי, רק צריך להיות תו בודד, על ידי אמנה. כך שלאחר מכן הוא האלפבית שיש לנו עומד לרשותנו להקסדצימלי. אז מה עושה JPEG נראה כמו אם אתה היו לכתוב את השלושה ראשונים אלה ביטים לא כעשרוני אבל, למשל, כהקסדצימלי? ולמה הוא hex אפילו כל ששימושי? ובכן, מבט מהיר על ירושלים. אז אם אני כותב את הקטעים ש לייצג אחר מספרים העשרוניים אלה זה יכול להיות קצת חלוד עכשיו מכמה שבועות אחורה, אבל ואחד משמאל נכון הם די קלים. 255 היו לנו המספר הגדול ביותר יכול לייצג עם שמונה סיביות. זה היה כל אלה. אז רק אחד זה המעטה המעניין הוא האמצעי. ואם אתה סוג של לעשות את מתמטיקה, תוכל להסיק כי, אכן, דפוס זה של אחד ו אפסים מייצגים 216. אז בואו פשוט קובעים ל עכשיו שאלה היא נכונות. אבל למה זה מעניין? ובכן, בתים, כמובן, הוא שמונה סיביות. ומתברר שאם אתה חושב של בתים כשני גושים של ארבעה ביטים, כמו זה. תן לי רק להוסיף קצת מרחב. אז לפני ש, לאחר. אני רק הוספתי כמה שטח לבן למען ההדמיה כאן. איך ייתכן שאנו מהווים כיום ב, למשל, הקסדצימלי כל ארבעה ביטים, כל סט של ארבעה ביטים? כך למשל, בצד השמאל עכשיו, יש לנו 1,111 בינארי. מהו מספר שבעשרוני, אם אתה עושה את המתמטיקה? יש לך את המקום אלה, מקום הזוגות, מקום ארבע, ומקום השמיניות. קהל: 15. דוד י מלאן: זה 15. אז אם אנחנו עושים שמונה ועוד ארבעה בתוספת שתיים ועוד אחד, אנחנו מקבלים 15. כדי שאוכל לכתוב את 15 להלן 1111, אבל כל העניין כאן הוא הקסדצימלי, לא עשרוני. אז במקום לכתוב את 15, 1-5, אני הולך לכתוב את זה במשושה, שאם אתה חושב בחזרה, אם יש לך אפס דרך f, מה ש15 הולך להיות? קהל: f. דוד י מלאן: אז מתברר f זה של. ואתה יכול לעבוד שיצאת באומרו, טוב, אם הוא 10, לאחר מכן על אישור, f היא 15. אז אכן, אנחנו יכולים לשכתב אותו סט של מספרים כf f. ואז אם אנחנו עושים קצת מתמטיקה, אנו להסיק שזה ד. שמונה הוא די קלים, כי אנחנו יש לי אחד במקום השמיני. ואז, יש לנו עוד כמה f של f. אז מה בני אדם נוטה לעשות על ידי אמנה כאשר הם משתמשים בהקסדצימלי הוא שהם פשוט לכתוב את זה קצת יותר בתמציתיות, להיפטר מרוב שהשטח לבן. ורק כדי להיות סופר ברור לי קוראים שזה הקסדצימלי, אמנה הפשוטה בין בני אדם הוא שאתה כותב אפס x, שאין לו משמעות אחרת מ מזהה חזותי של, כאן מגיע מספר hex. ואז, אתה שם את שתי הספרות, f f במקרה זה, ולאחר מכן ד, אז f f. אז סיפור ארוך קצר, הקסדצימלי פשוט נוטה כדי להיות שימושי, כי כל אחד משלה ספרות, אפס דרך f, בצורה מושלמת קווים עם דפוס של ארבעה ביטים. אז אם יש לך שתי ספרות הקסדצימליים, אפס עד ו, שוב ושוב, זה נותן לך בצורה מושלמת שמונה סיביות או בית אחד. אז זאת הסיבה שהוא נוטה להיות מקובל שימושי. אין אינטלקטואלי תוכן באמת מעבר לכך, מלבד השירות שלה בפועל. עכשיו בפורמט JPEG הוא לא רק קובץ פורמטים לגרפיקה. אתם אולי זוכרים שיש קבצים כמו זה בעולם, לפחות מכמה שנים. אז זה היה למעשה מותקן במערכת Windows XP על מיליוני מחשבים אישיים ברחבי העולם. וזה היה קובץ מפת סיביות, BMP. וקובץ מפת סיביות, כפי שתראה הבא שבוע, רק אומר שדפוס של נקודות, פיקסלים כפי שהם נקראים, המפה על ביטים, באמת. אם כי אז מה שמעניין,, על פורמט קובץ זה, BMP, הוא שמתחת למכסת המנוע, זה יש יותר מאשר רק שלושה בתים המרכיבים את הכותרת שלו, כל כך לדבר, כמה העקיצות הראשונות. זה באמת נראה קצת מסובך במבט ראשון. ואתה רואה את זה בסט P. ומקבל משהו מתוך מסוים של זה עכשיו לא כל כך חשוב, כפי שרק את העובדה כי בתחילתו של כל מפת סיביות קובץ, בפורמט גרפי, יש חבורה של מספרים שלמות. עכשיו מיקרוסופט, מחבר של פורמט זה, נוטה לקרוא לאלה דברים לא ints ותווים וצוף אבל מילות וד מילים ומתגעגע ובתים. אז הם פשוט סוגי נתונים שונים. הם שמות שונים לאותו הדבר. אבל אתה תראה שבP הגדרת ארבע. אבל זה רק אומר שאם אדם כפול לוחץ כמה קובץ BMP עליו או הכונן הקשיח שלה, וכעת ייפתח חלון עד שהראה לו או לה תמונה ש, זה קרה משום שההפעלה מערכת ככל הנראה הבחינה לא רק סיומת הקובץ BMP בשם הקובץ, אלא גם את העובדה שיש כמה כנס לדפוס של ביטים ממש בהתחלה של שקובץ מפת סיביות. אבל בואו עכשיו להתמקד ב קובץ כזה מסובך, אבל במקום על משהו כזה. נניח כאן בgedit, אני רק צריכים ההתחלות של תכנית זה די פשוט. יש לי כמה כולל למעלה. "Structs.h" #include עכשיו יש לי אבל אני אחזור לזה שברגע. אבל זה שימושי לעת עתה. אז זה תכנית זה הולך ליישם כמו מסד הנתונים של הרשם. אז מסד נתונים של תלמידים, וכל תלמיד בעולם יש לו שם ובית וכנראה כמה דברים אחרים, אבל אנחנו נשמור את זה פשוט. לכל תלמיד שם ובית. אז אם אני רוצה לכתוב תכנית שמטרתה בחיים היה רק ​​כדי לחזר מ אפס על עד שלוש, אם יש שלושה תלמידים באוניברסיטת הרווארד. ואני רק רוצה לקבל, באמצעות GetString, שם של כל תלמיד והבית, ואז פשוט להדפיס אותם החוצה. זה כמו סוג של שבוע אחד, דברים השבוע שני עכשיו, שבו אני רק רוצה ל לולאה או משהו כזה. ואני רוצה לקרוא לGetString כמה פעמים, ולאחר מכן להדפיס f כמה פעמים. אז איך ייתכן שאני אף עושה זאת,, כאשר שני שם ובית מעורבים לכל תלמיד? אז אולי האינסטינקט הראשון שלי להיות לעשות משהו כזה. אולי אני ראשון לומר, גם, לתת לי, אומר, מערך של מחרוזות שנקראות בשמות. ואני לא רוצה hardcode שלוש כאן. מה שאני כן רוצה לשים שם? אז סטודנטים, כי זה פשוט קבוע הכריז בראש, רק אז אני לא צריך hardcode שלושה במספר מקומות. בדרך זו, אני יכול לשנות את זה מקום אחד, וזה משפיע על שינוי בכל מקום. ולאחר מכן, אני יכול לעשות מחרוזת בתי סטודנטים. ועכשיו, אני יכול לעשות משהו כזה עבור (אני int = 0; i <סטודנטים; i ++. אז אני מקליד מהר, אבל זה כנראה תחביר מוכר עכשיו. ועכשיו, זה היה אחרונים יותר. אם אני רוצה לשים בi-th שמו של הסטודנט, אני חושב שאני עושה את זה. ולאחר מכן, לא שמות אבל בתים ממסגרים i. אני עושה את זה, GetString, ולתת לי לחזור ולתקן את הקו הזה. מסכים? לא מסכים? זה לא מאוד ידידותי למשתמש. לא סיפרתי לי המשתמש מה לעשות. אבל עכשיו, אם אני גם רציתי מאוחר יותר, בואו למשל, להדפיס את הדברים האלה out-- כך TODO מאוחר יותר. אני הולך לעשות יותר עם זה- זה ניתן לטעון כלומר יישום נכון של מקבל שמות ובתים, שלוש כולל שלהם של כל אחד, ממשתמש. אבל זה לא עיצוב טוב מאוד, נכון? מה אם תלמיד יש לא רק שם ובית, אלא גם את מספר תעודת זהות, ומספר טלפון, וכתובת דואר אלקטרוני, ואולי דף בית, ו אולי ידית טוויטר, וכל מספר של פרטים אחרים הקשורים לסטודנט או אדם, באופן כללי יותר. איך היינו להתחיל להוסיף פונקציונלי לתכנית זו? ובכן, אני מרגיש כמו הדרך הפשוטה ביותר עלול להיות לעשות משהו כמו, נניח, int סטודנטים מזהי. אז אני יכול לשים את כל תעודות הזהות שלהם שם. ולאחר מכן, למשהו כמו מספרי טלפון, אני לא בטוח איך מייצג שפשוט עדיין. אז בואו נלך קדימה ורק שיחה זה הטוויטר סטודנטים, ש הוא קצת מוזר, but-- וחבורת שדות נוספת. אני כבר התחלתי בצורה יעילה להעתיק ולהדביק כאן. וזה הולך לגדול די מסורבל די מהר, נכון? האם לא יהיה זה נחמד אם היו בעולם מבנה נתונים ידוע לא כint או מחרוזת, אבל משהו רמה גבוהה יותר, הפשטה, כך לדבר, ידוע כתלמיד? C לא בא עם המובנה פונקציונלי לסטודנטים, אבל מה אם אני רוצה לתת לו כזה? ובכן, מתברר, אני הולך לפתוח קובץ שנקרא structs.h כאן, ואתה יכול לעשות בדיוק את זה. ואנחנו הולכים להתחיל לעשות את זה עכשיו. ומתחת למכסה המנוע של P סט שלוש, היית כבר עושה את זה עכשיו. אין דבר כזה כמו rect גרם כזה או סגלגל גרם בג שפת תכנות אנשים בסטנפורד מיושמים אלה סוגי נתונים על ידי שימוש בגישה זו לכאן, הכרזת נתונים החדשים משלהם סוגי שימוש במילות מפתח חדשים struct התקשר ועוד typedef קרא לאחד. ואכן, למרות שהתחביר נראה קצת שונה מדברים שראינו בעבר, ב עיקרון, זה פשוט סופר. זה רק אומר "מגדיר את סוג." זה הולך להיות מבנה, ומבנה הוא בדיוק כמו מיכל לדברים מרובים. והמבנה שהוא הולך יש מחרוזת קראה בשם, ומחרוזת שנקראת בית. ובואו נקרא, רק מטעמי נוחות, תלמיד זה כל מבנה הנתונים. אז ברגע שאתה מקבל פסיק, יש לך עכשיו נוצר נתונים משלך סטודנט שנקרא סוג שעומד כיום לצד int, ולצוף, וchar, ומחרוזת, וrect גרם, וסגלגל גרם, וכל מספר דברים אחרים שאנשים המציאו. אז מה שימושי על זה עכשיו הוא שאם אני חוזר לstruct 0 ולסיים את זה יישום, שכתבתי מראש כאן, שם לב שכל של את הלכלוכים הבלתי נמנעים ש עמד להתחיל קורה כמו שאני הוספתי מספרי טלפון וציוצים ולכל אלה דברים אחרים ההגדרה של תלמיד, עכשיו זה בתמציתיות עטוף כאחד בלבד מערך של תלמידים. וכל אחד מהתלמידים האלה עכשיו יש דברים רבים בתוכו. אז זה משאיר רק שאלה אחת. איך אתה מקבל בשם, והבית, ומזהה, וכל דבר אחר הוא בתוכו של התלמיד? סופר פשוט, כמו גם. תחביר חדש, אבל רעיון פשוט. אתה פשוט מדד לתוך המערך, כפי שעשינו בשבוע שעבר וזה. ומה באופן ברור יצירה חדשה של תחביר? רק., שפירושו "להיכנס פנימה מבנה ולקבל בשם השדה שם, לקבל את השדה שנקרא הבית, לקבל את השדה שנקרא תלמיד. " אז בP הגדרת שלוש, אם אתה עדיין עובד על זה, ורוב האנשים עדיין הם, מבינים שככל שאתה להתחיל להשתמש בדברים כמו rects גרם ואליפסות גרם ודברים אחרים שלא נראים לבוא משבוע אפס, אחת, או שתי, מבין שזה בגלל שסטנפורד הכריז כמה סוגי נתונים חדשים. ואכן, זה בדיוק מה שנעשינו כמו גם לעשות,, בP הגדרת ארבע, כאשר אנחנו מתחילים להתמודד עם דברים כמו תמונות, מפות סיביות, ועוד. אז זה רק טיזר ו מודל מנטלי למה לבוא. עכשיו, אני התמהמהתי קצת הבוקר. אני היה סוג של סקרן לראות מה הטפט של מיקרוסופט למעשה נראה כמו היום. ומתברר שמישהו בשנת 2006 למעשה הלכתי כמעט בדיוק באותו המקום לצלם במציאות מה שנראה כמו שבימים אלה. השדה הוא עכשיו קצת מגודל. אז דיבר עכשיו של תמונות, בואו להחזיר ךייבן כאן על המסך וניקולס, ורק להזכיר לך שאם אתה רוצה להצטרף אלינו לארוחת צהריים יום שישי, ראש זה לכתובת האתר הרגילה שלנו כאן. אז איפה אנחנו לא נעזוב את ביום שני? אנחנו הצגנו את הבעיה הזו, נכון? זה היה לכאורה נכון יישום ההחלפה, לפיה אתה לוקח שני ints, אחד בשם, אחד בשם b, להחליף אותם, בדיוק כמו לורה עשתה כאן על במה עם חלב והמים, על ידי שימוש זמני משתנה, או כוס ריקה, כדי שנוכל לשים ב וב ב בלי בלגן של דברים. אנחנו השתמשנו במשתנה. זה נקרא זמני. אבל מה שהיה היסוד בעיה עם הקוד הזה ביום שני? מה הייתה הבעיה כאן? כן. קהל: זה לוקח מקום רב יותר. דוד י מלאן: לוקח יותר חלל, כי אני משתמש משתנה, וזה בסדר. זה נכון, אבל אני הולך להגיד שזה בסדר. זה רק 32 סיביות בכנף תכנית של דברים, כל כך לא ביג דיל. מחשבות אחרות? קהל: זה מחליף רק המשתנים מקומיים. דוד י מלאן: בדיוק. זה רק מחליף את המשתנים באופן מקומי. כי בכל פעם שאתה קורא function-- כאשר היה לי את המגשים מאננברג הפעם האחרונה, יש לך עיקרי בתחתית. ברגע שאתה קורא לפונקציה שנקראת החלפה, החלפה לא מקבלת x, y, הערכים המקוריים. מה עושה גט החלפה, לא אנחנו טוענים? קהל: עותקים. דוד י מלאן: אז עותקים שלהם. אז זה נהיה אחד ושני, אם אתה זוכר את הדוגמא מהזמן האחרון, אבל עותק של אחד ושני שהם החליפו בהצלחה. אך למרבה הצער בסופו של הדבר, ערכים אלה הם עדיין אותו. אז אנחנו יכולים לראות את זה עם שלנו חבר חדש, בתקווה GDB, שיש לך או TFS וCa של מנחה אותך לכיוון כדלקמן. אז לא זוכרים החלפה נראית like-- בואו לפתוח את זה- נראה כך. אנו אותחלו x לאחד, y לשתי. היה לי חבורה של f של הדפסה. אבל אז, על המקש החיוג כאן היה להחליף, ש זה בדיוק אנחנו הקוד פשוט ראיתי לפני רגע. וזה נכון בהתחלה מבט חטוף, אבל מבחינה תפקודית, תכנית זה לא עובדת, משום ש זה לא באופן קבוע להחליף x, y. אז בואו יראו את זה, חם מהיר עד כאן עם GDB, ./noswap. חבורה של מידע מכריע ש אני להיפטר עם בקרת L לעת עתה. ועכשיו, אני הולך קדימה ולהפעיל אותו. ולמרבה הצער, ש לא היה כל כך שימושי. הוא רץ את התכנית פנימית של זה תכנית בשם GDB, הבאגים, אבל זה לא נתן לי לחטט. אז איך אני יכול בעצם להשהות ביצוע בתוך תכנית זו? אז לשבור. ואני יכול לשבור בכל שורת מספר, אחד, 10, 15. אבל אני גם יכול לשבור באופן סמלי באומרו עיקרי הפסקה. וזה הולך להגדיר הפסקה נקודה, כנראה בשורה 16 ​​בעיקרי. ואיפה הוא קו 16? בואו נלך עד הקוד וללכת עד noswap. ואכן, שורה 16 ​​היא הראשון בתכנית. אז עכשיו, אם אני הולך קדימה וסוג לרוץ הפעם, הזן, זה עצר. אז בואו לחטט. הדפסת x-- מדוע הוא אפס x? ולהתעלם מסימן הדולר. זה רק בשביל להשתכלל שימוש בתכנית. למה הוא x אפס באותו הרגע? כן. קהל: זה עצר ממש לפני שורה 16, לא ממש על קו 16. דוד י מלאן: בדיוק. GDB, כברירת מחדל, הושהה ביצוע ממש לפני קו 16. אז זה לא בוצע, ש משמעות הדבר היא x היא של ערך כלשהו לא ידוע. ויש לנו מזל שזה משהו נקי כמו אפס. אז עכשיו אם אני מקליד הבא, עכשיו שהיא ביצעה 16. זה מחכה לי לבצע 17. תן לי ללכת קדימה וx הדפסה. זה אחד. תן לי ללכת קדימה וy הדפסה. מה אני צריך לראות עכשיו? קהל: [לא ברור] דוד י מלאן: קצת יותר חזק. קהל: [לא ברור] דוד י מלאן: לא בדיוק קונסנסוס. אז כן, אנחנו רואים כמה ערך זבל. עכשיו, y הוא 134514064 שם. ובכן, זה רק חלק ערך זבל. התכנית שלי משתמשת בזכרון RAM למטרות שונות. יש פונקציות אחרות. אנשים אחרים כתבו בתוך המחשב שלי. אז פיסות אלה היו בשימוש במשך ערכים אחרים, ומה שאני רואה הוא השרידים של כמה שימוש קודם בזיכרון ש. אז לא ביג דיל, כי ברגע כמו שאני מקליד הבא ולאחר מכן להדפיס y, זה אותחל ל הערך שאני רוצה. אז עכשיו, בואו נלך קדימה קצת יותר מהר. N לבא. בואו נעשה את זה שוב. בואו נעשה את זה שוב. אבל אני לא רוצה לפגוע זה כאן, כי אם אני רוצה לראות מה קורה בתוך של החלפה, מה הפקודה? קהל: צעדים. דוד י מלאן: צעדים. אז זה ייכנס לי פונקציה, ולא על זה. ועכשיו, זה קצת לא ברור מאליהם בכנות, אבל זה רק אומר לי שאני בשורה 33 עכשיו. ובואו נעשיתי את זה שוב. טמפ הדפסה. ערך אשפה, שלילי הפעם, אבל זה רק עדיין ערך זבל. אז בואו נעשה זמני הבאה, הדפסה. זה אותחל ל1, ש היה הערך של x, aka. עכשיו, שבו הם שלנו וx מגיע? ובכן, שמנו לב בעיקרי, אנחנו נקרא x, y את הערכים הללו. לאחר מכן, אנו עוברים אותם כדי להחליף באופן הבא. X בא קודם, y פסיק. ולאחר מכן, החלפה יכולה לקרוא להם x, y. אבל לבהירות, זה קורא להם וb. אבל וb עכשיו הולכים להיות עותקים של x, y, בהתאמה. אז אם אני חוזר לGDB, זמני כיום הוא אחת וכיום הוא אחת. אבל אם אני עושה הבא ועכשיו לעשות הדפסה , כבר עבר. חלב כבר נשפך לתוך לשעבר הזכוכית של מיץ תפוזים, או להיפך. ואם אני עושה הבא שוב, ועכשיו אם אני להדפיס כבדיקת שפיות, עדיין שני, אבל ב היא כיום אחד. למען האמת, הוא עדיין שם. לא אכפת לי מה הוא זמני. אבל ברגע שאני עכשיו להקליד, נניח, תמשיך לחזור, עכשיו אני בסופו של הדבר התכנית. ולמרבה הצער, x הוא עדיין אחד וy הוא עדיין שני. אז מה הייתה התועלת של GDB שם? זה לא עזר לי לתקן הבעיה כשלעצמה, אבל אני מקווה שזה יעזור לי להבין את זה על ידי מימוש שכן, ההיגיון שלי הוא נכון, אבל הקוד שלי הוא לא סופו של דבר שיש השפעה קבועה. אז זה בעיה שאנחנו הולך עכשיו לפתור היום. אבל בואו להגיע לשם בדרך של זה. מחרוזת היא שקר. זה, יותר מדי, לא סוג הנתונים שקיים בג זה היה שם נרדף לכמה זמן למשהו אחר, ואנחנו יכולים לגלות שכדלקמן. תנו לי ללכת קדימה, לפתוח את תכנית בשם להשוות-0. ובמקום להקליד את זה, נתחיל ללכת דרך הקוד אני כבר כתבתי, אבל זה רק כמה שורות. אז זה להשוות-0. והדבר הראשון שאני עושה הוא מקבל שורת טקסט. אבל שים לב למה שאני עושה בפעם הראשונה. מה שונה באופן ברור על קו 21? למעשה, חכה רגע. זהו עותק שני. זה אפילו לא התכנית הנכונה. כל ההתראה. תקין, ספוילר בסדר, אז זה לא משנה ש. זו התשובה לשאלת עתיד. כאן הוא להשוות-0, ואני על מנת לקבל שורת טקסט. התכנית של הרבה יותר פשוט. אז זה הוא פשוט. זה כמו שבוע אחד, דברים השבוע שני ברגע. מחרוזת s = GetString. עכשיו, אני אומר את זה שוב כאן למטה. מחרוזת t = GetString. ואז, הדבר האחרון בזה תכנית, כפי ששמה מרמז, הוא אני הולך לנסות להשוות אותם. אז אם של, המחרוזת הראשונה, שווה = t, אז אני הולך להגיד לך להקליד את אותו הדבר. אחר, אני הולך לומר אתה מקליד דברים שונים. אז בואו לקמפל ולהריץ את התכנית. אז להפוך להשוות אפס. נראה טוב. אין שגיאות הידור. תן לי ללכת קדימה עכשיו והקלד ./compare-0. תן לי ללכת קדימה ואומרים משהו : ךייבן ומשהו: רוב. ואני מקליד דברים שונים. עד כה, כל כך טוב. נראית תכנית תהיה נכון. אבל בואו להפעיל אותו שוב. תגיד משהו: גייב. תגיד משהו: גייב. בסדר. אולי אני פגע מקש רווח או משהו פאנקי. בואו נעשה את זה שוב. אז Zamyla. Zamyla. דברים שונים. אז מה קורה פה? אז יש לנו שני קווים של אלה קוד, GetString להיקרא פעמיים. ואז, אני פשוט מנסה להשוות ים ולא. אבל מה שבאמת אז קורה? ובכן, של כתב היד שלי עומד לשחוט דוגמא זו במידה מסוימת. ובואו בעצם לזרוק כאן, כמו גם את זה. אז יש לנו קו כמו מחרוזת s = GetString. אז זה פשוט הראשון שורה מעניינת מתכנית ש. אבל מה כל הזמן הזה היה קורה מתחת למכסת המנוע? ובכן, בצד השמאל הוא מחרוזת, אשר הוא איזה סוג של משתנה, וזה נקרא ים. אז אני יודע שזו היא באמצעות זיכרון, או זיכרון RAM, במחשב שלי איכשהו. אז אני הולך למופשט לצייר את זה ככיכר. 32 סיביות, מתברר, אבל עוד על כך בעתיד. ואז, מה קורה כאן? ובכן, GetString ברור מקבל מחרוזת מהמשתמש. וGetString לי Zamyla או גייב או ךייבן. אז בואו לבחור הראשון של אלה, שהיה ךייבן. כל כך יעיל, מה GetString לי לי שבמקרה הראשון היה D--v-e-n. ואז, מה עוד עשה זה ייתן לי בסתר? קהל: [לא ברור] דוד י מלאן: כן, האופי / 0 או null. כך שלמעשה הוא נתן לי מחרוזת. אבל אנחנו כבר יודעים מקודמים נראה שמחרוזת היא פשוט מערך של דמויות, וזה הופסק על ידי אופי זקיף המיוחד הזה, / 0. אבל אם זה נכון וזה הוא ריבוע, זה ברור מלבן גדול הרבה יותר. ואכן, זו היא, אני טוען, רק 32 סיביות. וברור שזה יותר מ 32 ביטים, כי זה כנראה שמונה ועוד שמונה בתוספת שמונה בתוספת שמונה בתוספת שמונה, רק בגלל הבתים בASCII. איך לעזאזל אנחנו הולכים כדי שיתאימו להתפלל לקופסה קטנה הזאת כאן? ובכן, מה שGetString בעצם עושה? ובכן, רשת זו כאן מייצגת הזיכרון של המחשב שלי או זיכרון RAM. אז בואו באופן שרירותי אומרים שאם כל אחד מאלה מייצג בייט, אז אנחנו יכולים לחשוב על כל בתים כבעל כתובת, כמו רחוב 33 אוקספורד, או 34 רחוב אוקספורד רחוב אוקספורד, או 35. אז בדיוק כמו שיש לי בתי כתובות ויש לי בנייני כתובות, כך גם בתים בודדים של יש לי זיכרון כתובות או מספרים כי לזהות. עכשיו, זה הוא שרירותי. אבל לשמור את זה פשוט, אני הולך להשתמש הקסדצימלי רק על ידי אמנה, אבל 0x לא אומר כלום אחר מ "זה הקסדצימלי." ואני הולך לטעון ש "D" בסופו של בבית אחד בזיכרון. יש לי שום דבר אחר שקורה ב זיכרון, כך ךייבן קיבל את המקום הראשון בבית אחד. זהו, אם כן, הולך להיות 0x2. זה הולך 0x3. זה הולך להיות 0x4. זה הולך 0x5. זה הולך להיות 0x6. אבל ברגע שאתה מתחיל לחשוב על מה עושה את של המחשב מתחת למכסה המנוע, אתה יכול להתחיל להסיק איך אתה, לפני כמה שנים, היית יישמתי C עצמו. מה הוא GetString כנראה returning-- כי זה מרגיש שזה לא חוזר ךייבן, כשלעצמה, בגלל שהוא בוודאי לא הולך כדי להתאים בbox-- הקטן הזה אז מה הוא GetString כנראה חוזר? קהל: [לא ברור] דוד י מלאן: המיקום של ךייבן. וזה כבר עושה את זה מאז שבוע אחד. מה GetString הוא באמת חוזר הוא לא מחרוזת, כשלעצמו. זה אחד השקרים הלבנים הקטנים. זה מחזיר את הכתובת של מחרוזת בזיכרון, הכתובת הייחודית. להתפלל מתגורר ברחוב אוקספורד 33. אבל באופן תמציתי יותר, גאווין חי ב0x1, כתובת מספר אחת. אז מה מקבל לשים את זה קופסא קטנה אז, שתהיה ברורה, רק את הכתובת של מחרוזת ש. אז כל הזמן הזה, זה יש כבר קורה. אבל מה זה מרמז על כרגע הוא אם כל זה שיש לו הוא מספר בתוכו, מי לעצור אותך, מתכנת, מלשים כל מספר ב כל משתנה ופשוט קופץ לנתח זה של זיכרון? ואכן, אנו רואים זה בפעם הבאה איום. אבל לעת עתה, זה מרגיש לא מספיק. אם אני אומר, תבין אותי מחרוזת, אתה נותן לי ךייבן. אבל אתה לא באמת נותן לי ךייבן. כל מה שאתה נותן לי הכתובת של דייבן. איך אני מכן יודע בודאות בי ךייבן מתחיל וends-- סיפורו של מקבל weird-- בי ךייבן מתחיל ונגמר, ולאחר מכן, בסמוך מחרוזת בזיכרון מתחילה? ובכן, אם אתה מוסר לי בתחילת ךייבן, בעצם, איך אני אדע איפה הסוף של השם שלו הוא? כי אופי null מיוחד, ש הוא כל כך חשוב יותר עכשיו אם מחרוזות מתחת מכסה המנוע הוא פשוט זיהה באופן ייחודי על ידי מיקומם בזיכרון. אז כל הזמן הזה, זה מה שקורה. לכן, כאשר אנחנו מסתכלים עכשיו ב הקוד כאן, להסביר אם היית באג בשורה 26. למה הוא שונה Zamyla וZamyla? למה הוא שונה גייב וגייב? כן, בגב. קהל: יש להם כתובות שונות. דוד י מלאן: פשוט כי יש להם כתובות שונות. כי כשאתה קורא GetString שוב, שאני אעשה במהירות כאן, אם זה קו השני, המחרוזת t, כפי שעשיתי בתכנית ש, שווה שיחה נוספת לGetString. בפעם הבאה שאני קורא GetString, אני הולך כדי לקבל נתח של זיכרון שונה. GetString מותר לשאול ההפעלה מערכת ליותר ויותר זיכרון. זה לא הולך לשימוש חוזר באותה שישה בתים בכל פעם. זה הולך לקבל חדש נתח של זיכרון, ש משמעות הדבר היא לא הולך לקבל ערך אחר לכאן. לכן, כאשר אני עושה את של שווה = t, אתה לא משווה D נגד זה ונגד זה וV נגד זה. אתה משווה את זה נגד זה, ש כנות הוא useless-- די useful-- הוא די חסר תועלת, כי מי באמת אכפת איפה המחרוזות נמצאות בזיכרון? ואכן, יש לנו לא. ואנחנו לא מתכוונים ל להתחיל במיוחד אכפתיות. רק במידה שחרקים יכולים להתעורר ואיומי אבטחה עלולים להתעורר רצון אנחנו באמת להתחיל לדאוג בקשר לזה. אז בואו לתקן את הבעיה הזו. מתברר, לך לתקן את זה סופר פשוט. ובואו למעשה, לפני ש לחשוף את זה שוב, מה היית עושה אתה עושה אם בכיתת CS50, והיה לך ליישום השוואה נגד שתי מחרוזות. אתה בבירור לא יכול פשוט להשתמש ים שווה = t. אבל רק מבחינה לוגית, איך היית משווה את המחרוזת נגד מחרוזת זו באמצעות קוד C? כן. קהל: פשוט תעשה ללולאה [לא ברורה] דוד י מלאן: מושלם. קהל: [לא ברור] דוד י מלאן: כן. פשוט להשתמש בלולאה for או בעוד לולאה או מה. אבל רק ליישם את הרעיון הבסיסי שאם זה נתח של זיכרון או מערך וזה, לחזר על שניהם באותו הזמן. ורק להשוות את המכתבים. ואתה חייב להיות קצת זהיר, כי אתה לא רוצה אצבע אחת ללכת העבר האחר כי מחרוזת אחת היא יותר מאחר. אז אתה הולך רוצה לבדוק הערך המיוחד הזה בסוף, null. אבל זה באמת, ב הסוף, פשוט כמו ש. ולמען אמת, אנחנו לא צריכים להמציא מחדש את הגלגל ש. הנה גרסה השנייה. ומה שאני הולך להגיד כאן הוא ש במקום להשוות ים שווה = t, אני במקום שאני מתכוון לומר, אם מחרוזת השוואה של t הפסיק של שווה = 0. עכשיו, מה שהמחרוזת להשוות? מתברר, שזה פונקציה ש מגיע עם C, שמטרתו בחיים הוא להשוות בין שתי מחרוזות. ומערבבים להשוות, אם אנו קוראים דף גבר או תיעוד או CS50 התייחסות, זה יהיה פשוט להגיד לך התרגשות ש להשוות תשואות או שליליות מספר או מספר חיובי או אפס, שבו אפס אומר שהם שווים. אז רק השערה. מה יכול זה אומר אם מערבבים חוזרים להשוות ערך שלילי או ערך חיובי? קהל: גדול או פחות מ. דוד י מלאן: כן, גדול או פחות מ. אז אם אתה רוצה למיין את כל חבורה של מחרוזות בdictionary-- כפי שסופו של דבר את road-- פונקציה מושלמת לשימוש פוטנציאלי, כי זה הולך לעשות את זה השוואה של מחרוזות בשבילך, ואומר לי אתה עושה מגיע לפני b, או עושה ב לבוא לפני בסדר אלפביתי. אנחנו יכולים לעשות בדיוק את זה. ואני שם לב שעשיתי אחד אחר דבר בדוגמא זו. מה עוד השתנה גבוה יותר בתפקידו העיקרי זה? תו *. וזו היא שהשקר לבן אחר. כל הזמן הזה, כאשר יש לך כותב מחרוזת, יש לנו כבר שכתוב בחשאי מחרוזת כמו char * כל כך צלצול שלמעשה מבין אותך. במילים אחרות, בCS50.h וכפי שאנו רואים את סופו של דבר, עשינו מחרוזת מילה נרדפת נקראת זה אותו דבר כמו char *. ולעת עתה, רק יודע ש *, בהקשר זה, לפחות, משמעות הדבר היא הכתובת. הכתובת של מה? ובכן, העובדה שאמרתי * Char, ולא int * או לצוף *, משמעות הדבר היא כי char * הוא הכתובת של char. אז הקופסה קטנה הזאת כאן, aka מחרוזת, הוא באמת של char * סוג, וזה פשוט דרך מפוארת לומר, בתיבה זו תלך כתובת. ומה כתובת שאמנם מתייחסת ל? ככל הנראה, char. אבל אנחנו בהחלט יכולים יש לי * int ודברים אחרים. אבל לעת עתה, char * הוא באמת הכי פשוט ואחד של עניין. אז בעיה זה הולכת לעלות, אם כי, שוב. נניח שאני פותח את התכנית הזאת. בואו תראו אם עכשיו אנחנו יכולים לחזות מה לא בסדר עם הקוד הזה. אז בתכנית זו, להעתיק-0, אני הולך קדימה ושוב קוראים GetString ולאחסן את הערך בים. ולאחר מכן, למה אני עושה את זה, רק כתזכורת מהעבר שבועות? עשינו לומר GetString ש לפעמים מחזיר null. מה זה אומר אם GetString מחזיר null? משהו השתבש. זה כנראה אומר שהמחרוזת היא מדי גדול, את המחשב של זיכרון. זה קורה סופר, סופר, סופר לעתים רחוקות, אבל זה יכול לקרות. אנחנו רוצים לבדוק את זה, וזה כל מה שאנחנו עושים. כי אנחנו רואים עכשיו, אם לא להתחיל לבדוק נוהגים לדברים כמו null, אתה עלול בעצם להתחיל ללכת לכתובות בזיכרון שאינם חוקיים. ואתה הולך להתחיל התרמה יותר ויותר תקלות פילוח. או במקינטוש או PC, פשוט גורם למחשב להיתקע או תכנית להקפאה, באופן פוטנציאלי. אז עכשיו, אני טוען בעותק-0.c, ש אני הולך להעתיק מחרוזות אלה בדרך של קו 28. ולאחר מכן, אני הולך לטעון שבתחתית כאן שאני הולך כדי לשנות את אחד מהם. אז שם לב זה. אני מתקשר strlen ידידנו הוותיק. ורק להסביר באנגלית מה הקו הזה 34 עושה? מה עושה סוגר t 0 מייצג בצד השמאל. כן. קהל: דמות ראשונה של t? דוד י מלאן: דמות הראשונה של t. זהו זה. תו הראשון של t, אני רוצה כדי להקצות את גרסתו באותיות גדולות של התו הראשון בt. אז זה הוא ניצול המכתב הראשון. ואז, הדבר האחרון שאני עושה בתכנית זו היא שאני טוען כאן המקורי, זה, והנה ההעתק, t. אבל מבוסס על הסיפור שרק סיפר ​​על מה שמחרוזות באמת, מה הוא קו 28 באמת עושה, ומה הוא באג וכתוצאה מכך הולך להיות על המסך? אז קודם כל, השאלה הראשונה, 28. מה = t המחרוזת של עושה הוא באמת? אם יש לנו ביד השמאל צד כאן = t מחרוזת s; זה נותן לי קופסא אחת כאן והתיבה אחת כאן. ונניח שכתובת זו היא 0x, נניח, 50 הפעם, באופן שרירותי. מה עושה = t המחרוזת של לעשות מתחת למכסת המנוע? קהל: [לא ברור] דוד י מלאן: הוא מאחסן את הזיכרון לטפל שם, אז 0x50 הולך לשם. אז אם עכשיו, אני הולך לראשון דמות בt ואותיות גדולות זה, מה שאני למעשה אני עושה לים? אני באמת עושה את אותו דבר, נכון? כי אם כתובת 0x50-- ורק, אני אין להם הרבה מקום על הלוח כאן, אבל תניח שזה 0x50 כאן למטה, אי שם בזיכרון של המחשב שלי. ויש לי, למשל, גייב באותיות קטנות כאן, כמו זה. ויש לי אמר סוגר t 0 מקבל מהוונים. ובכן, סוגר t 0 הוא את האות הראשונה בt. אז גרם קצת הולך ג הגדול להיות אבל הבעיה הוא, מה זה גם מצביע על? קהל: אותו הדבר. דוד י מלאן: אותו דבר בדיוק. אז הסבר פשוט אולי, גם אם התחביר הוא קצת מוזר. אז בואו נעשיתי את זה. להכין עותק-0 ולאחר מכן ./copy-0. תגיד משהו: גייב. ולרוע מזל, שניהם שלהם עכשיו הוון, אבל בשביל זה שבבסיס סיבה שאנחנו פשוט עכשיו התמודדות עם כתובות. אז איך אנחנו מתחילים address-- לא משחק מלים intended-- איך אנחנו מתחילים לטפל בעיה המסוימת הזה? ובכן, בcopy1.c, דברים הולכים כדי לקבל קצת יותר מסובך. אבל אני טוען פתרון פשוט מבחינה מושגית. כל כך קשה להשיג במבט ראשון. לא הולך להיות קל לראשון פעם שאתה מקליד את זה, אולי, אבל אם הבעיה היא ש פשוט עושה = T S רק עותקי כתובת, מה, שוב, אם אני יכול להרים עליך, הולך להיות הפתרון לבעצם העתקת מחרוזת? קהל: כנראה ש להשתמש בלולאה שוב. דוד י מלאן: כן. אז אנחנו הולכים לצריכים לולאה שוב. וכי אם ברצוננו להעתיק מחרוזת s למחרוזת אחרת, אנחנו כנראה רוצים לעשות את זה תו אחרי תו. אבל הבעיה היא, אם זה הוא מקור של, עכשיו אנחנו צריכים להתחיל באופן מפורש הקצאת זיכרון עבור t. במילים אחרות, בואו לצייר מחדש בפעם האחרונה זה אחד. אם זה מחרוזת s = GetString. ובואו נשים את זה כאן, גם כן. זה GetString. ולאחר מכן, את התמונה למשהו כמו שהוא הולך להיות כמו קודם, g--b-e-/ 0. זה נראה משהו קטן כזה. וים ולכן, אנחנו קוראים לזה 0x50, וזה הולך להיות 51, 52. אז זה 0x50. ולאחר מכן, אני עושה לא מחרוזת. בזיכרון, שרק הולך תן לי קצת מרובע כמו זה. אז מה צעד מפתח עכשיו? אם אני רוצה להעתיק s לתוך t, מה ריק אנחנו צריכים למלא כאן? או מה שאנחנו צריכים לעשות כדי לעשות ברמה גבוהה? כן? מישהו? כן. קהל: אנחנו צריכים [לא ברורים]. דוד י מלאן: כן, אנחנו צריך למלא ריק זה. אני לא יכול להעתיק ולאחר מכן לנצל את שמו של גייב עד שאני שואל את מערכת ההפעלה עבור נתח נוסף של זיכרון זה לפחות גדול כמו מקורי. אז זה משאיר אותנו עם שאלה. איך אני שואל את מערכת ההפעלה לא רק בשביל pointer-- קטן ופשוט כזה נקרא, כתובת, pointer-- לא לתיבה קטנה ופשוט כמו הזה שנקרא מחרוזת? איך אני שואל את ההפעלה מערכת לנתח גדול של זיכרון? עד כה, אני כבר רק קיבלתי בחזרה ש בעקיפין על ידי קורא GetString. אז איך GetString אפילו מקבל את הזיכרון שלה? ובכן, מתברר שיש פונקציה כאן אחרת זה שאנחנו עכשיו נתחיל להשתמש. עכשיו, זה נראה than-- דרך יותר נסתר ואני יחיד שיכול לראות it-- קו זה נראה הרבה יותר מסתורי אז זה צריך במבט ראשון. אבל בואו להקניט אותו לגזרים. בצד השמאל, יש לי char * t. אז באנגלית, בואו נתחיל לגבש משפטים נכונים בז'רגון טכני. אז זה הקצאה משתנה מסוג char * נקרא t. עכשיו, מה זה באמת אומר? ובכן, זה אומר, מה אני הולך לשים במשתנה הזה שנקרא t? כתובת של char. אז זה פשוט פשוט, דרך סבירה יותר לתאר את צד השמאל. כך שיוצרת תיבה זו כאן רק. אז צד ימין, ככל הנראה, הוא הולך להקצות שגדול יותר נתח של זיכרון איך? אז בואו להקניט זה לגזרים. זה מדהים במבט ראשון, אבל מה קורה כאן בפנים? ראשית, יש malloc, ש כנראה החבר החדש שלנו, "זיכרון להקצות." אז זה הטיעון שעבר לתוך זה, אז זה ויכוח די גדול. אז בואו להקניט זה לגזרים. strlen של ים, כמובן, מייצג the-- קהל: מספר התווים. דוד י מלאן: רק מספר התווים בים. אז האורך של ים, את המחרוזת המקורית. אז G--b-e. אז זה כנראה ארבעה במקרה זה. למה אני עושה את +1 לאחר קורא strlen של ים? קהל: [לא ברור] דוד י מלאן: בשביל זה אופי null מיוחד. אם אתה שואל אותי מה אורכו של שמו של גייב, אני הולך לומר ארבעה. מתחת למכסה המנוע, אם כי, אני צריך כי הבתים חמישי לאופי null. אז בגלל זה אני עושה +1. עכשיו רק במקרה שאתה מפעיל את זה תכנית במחשב אחר מאשר, לומר, מכשיר CS50, שבו בגודל של char עשוי להיות שונה מcomputer-- שלי מתברר שאני יכול לקרוא לזה sizeof מפעיל, פשוט לשאול את המחשב, מה הוא בגודל של char במחשב הזה? ועל ידי הכפלת חמישה בזה דוגמא על ידי הגודל של char, ש ברוב המחשבים יהיו להיות רק אחד, malloc הולך להקצות עבורי זה גדול נתח של זיכרון כאן בצד הימין. וזה הולך return-- זה function-- אז זה הולך להחזיר לי מה? קהל: הכתובת? דוד י מלאן: הכתובת של מה? קהל: מהזיכרון זה מוקצה? דוד י מלאן: של זיכרון זה הוקצה. אז אין לי מושג, בכנות, לאן זה הולך בסופו של. אני הולך להציע ש זה הולך בסופו של ב0x88. שרירותי לחלוטין, אבל במקום אחר 0x50, מכיוון שמערכת ההפעלה, מה ש Windows ו Mac OS לעשות בשבילי, הוא לוודא שזה נותן שלי נתחים שונים של זיכרון RAM. אז זהו הערך שבו זה נתח של זיכרון עלול בסופו. אז זה מה שסופו של דבר כאן, 0x88. אז עכשיו ברור, אני יכול להבין שזה לא אותו הדבר כמו זה, בגלל שהם מצביעים על נתחים שונים של זיכרון. אז אם אני עכשיו באמת רוצה להעתיק את זה ב, בואו נעשה את הפתרון המוצע שלך. בואו פשוט ללכת, ליצור ללולאה, ולעשות סוגר t אני מקבל ים סוגר i. כי עכשיו אני יכול להשתמש סימון זה כמו מערך-, כי למרות שmalloc מאוד הגנרי מקצה לי זיכרון, זיכרון הוא בתים רק רציפים. Byte, בתים, בתים, גב אל גב אל גב. בוודאי שאני יכול כמתכנת להתייחס אליו כמערך, ש אומר שאני יכול להשתמש בסופו של דבר מוכר זה סימון של רק חלק סוגריים מרובעים. אז תן לי להשהות שם, כי זה הרבה בבת אחת, אפילו למרות שהרעיון הבסיסי כדי לסכם היא מחרוזת ש, כל הזמן הזה, אינו סוג נתונים חדש כשלעצמו. זה רק מצביע כביכול, כתובת של אופי, שרק אומר שזה מספר כי על ידי אמנה אנושית אנו נוטים לכתוב כמו 0x משהו. אבל זה רק מספר, כמו הרחוב אוקספורד 33, אשר קורה להיות הכתובת של בניין הפקולטה למדעי המחשב. כל שאלות על פרטים אישיים? כן? קהל: למה אנחנו בודקים עבור t שווה ל null? דוד י מלאן: למה אנחנו לבדוק t שווה ל null? אם אנו קוראים את documentation-- question-- נהדר עבור malloc, זה הולך לומר באותיות קטנות, לפעמים malloc עשוי לחזור null, בדיוק כמו GetString. ואכן, GetString מחזיר null אם, בתורו, malloc מחזיר null, בגלל GetString משתמש malloc. וזה עלול לקרות אם מערכת ההפעלה, Mac OS, Windows, מה, היא פשוט מתוך זיכרון בשבילך. אז זה מה שקרה שם. ותן לי לגלות דבר אחד אחר שאולי פשוט תפוצץ את דעתך או להיות לגמרי רחוק מדי מעבר לקו. אבל תנו לי להרים את אותו דבר עבור לולאה להעתקה, לפני רגע ש, זוכר היה זה. סוגר t אני מקבל ים סוגר i. נחמד וידידותי למשתמש. מרגיש כמו השבוע שני שוב. אבל גרסה זו באמת יכולה להיות שוכתב כמו זה, שנראה ברורים מאליהם. זה מצביע טכניקה הנקראת חשבון, חשבון כתובת. אבל למה זה עובד? עכשיו מעצבן, מחברים של C החליטו להשתמש הסמל * למטרות שונות. ראינו את זה בשימוש כבר פעם אחת, char *, שפירושו "תן לי משתנה זה הולך להכיל הכתובת של char. " * אז char בהקשר זה פירושו "תן לי משתנה." למרבה הצער, אם אתה משתמש ב* ללא מילה לפניו, כמו char, זה עכשיו נקרא מפעיל dereference. ואנו רואים יותר מזה לפני זמן רב. אבל זה רק אומר "ללכת לשם." זה כמו להגיד, אם מישהו הושיט לי על פיסת נייר "רחוב 33 אוקספורד," אם אני עושה את "הרחוב * 33 אוקספורד," זה אומר ש "ללכת במורד הכביש לבניין הפקולטה למדעי המחשב." אז * רק אומר ללכת לשם אם אין מילה לפניו. אז מה הוא לא, שיהיה ברור? t הוא הכתובת של הנתח של זיכרון שניתנו לי בחזרה. ים הוא הכתובת של מה, שיהיה ברור, בדוגמא שכבר דנים, של גייב האותיות הקטנות? ים הוא הכתובת of-- קהל: המחרוזת. דוד י מלאן: השם המקורי של גייב. אז זה הכתובת של נתח זה של זיכרון. אז אם אני אומר לא אני- + i, הודעה, רק ידידנו הוותיק. זה פשוט משתנה מדד שiterating מאפס על עד לאורכו של ים המחרוזת. אז זה הולך להיות אפס, ואז אחד, אז שתיים, ואז שלוש, אז ארבעה. אז בואו להרכיב חדש חלקי הפאזל כמו סריטות, אם תרצה, למרות, שוב, התחביר הרבה יותר מסתורי מאשר גירוד. אז לא הוא + כתובת אני הולך לתת לי מספר, כי כל אלה הם מספרים שאנחנו כבר ציור כמשושה. אבל הם רק מספרים. אז אם הכתובת של t שאמרנו היה 0x88, מה 0x88 בתוספת אפס. גם אם אתה לא מרגיש בנוח עם hex עדיין, לקחת ניחוש. קהל: המקורי. דוד י מלאן: עדיין 0x88. אז מה עושה * 0x88 אומר? זה אומר, "ללכת לשם", שפירושו ביעילות, "לשים את האצבע שלך כאן." ועכשיו בצד ימין של ביטוי זה, * ולאחר מכן בparens, ים + אומר שאני s, המהווה את יתייחס כאן לגרם הקטן. של 0 + הוא, כמובן, זה, כל מה שהים הוא. אז עכשיו, זה אותו ים *, שבדיוק כמו * 33 רחוב אוקספורד אומר ללכת לכתובת ים. אז הנה אצבע זו, יד ימין. אז מה אני הולך להעתיק למה? הדבר בצד הימין, שהוא גייב, גרם קצת לכאן, לכאן. ולכן ההשפעה של ש איטרציה הראשונה של הלולאה, כפי שאתה הציע, אף על פי שזה נראה משוגע יותר מסובך מכל דבר שראינו בעבר, הוא פשוט אומרים ללכת כאן ולהעתיק את הדמות שכאן. זה נותן לך מפה לשני המקומות. ואנו רואים הרבה יותר מזה. אבל לעת עתה, התקווה היא רק כדי להציג כמה מרעיונות הבסיסיים אלה. ואכן, בואו נסתכל על אחד תכנית סופית כאן, ולאחר מכן הפלסטלינה הבטיחה, שיעשה הכל בסדר. בסדר. אז תן לי לפתוח up-- שם אנחנו הולכים. אז בואו me-- אנחנו נחזור לתמונה הזאת לפני זמן רב. תן לי לפתוח את הדוגמא אחרונה זה כאן. אז הנה הוא סופר, סופר תכנית שמשיגה שום דבר בחיים שעושים את הדברים הבאים. היא מצהירה שני משתנים, x הראשון וy, שאינם מספרים הפעם, כשלעצמו. הם לא מספרים שלמים, כשלעצמו. הם, ככל הנראה, int *. כל כך פשוט לאף אחד, מה זה אומר אם סוג הנתונים שלך, משתנה, הוא של * int סוג כוכב? זה הכתובת של int. אז אין לי מושג איפה זה עדיין. זה פשוט "פירושו לשים, סופו של דבר, הכתובת של int כאן. " 0x50, 0x88, בכל מקום בו הוא ב זיכרון, כתובת הולכת לשם. וזה מה שהוא y הולך להיות, כמו גם. אם אני עכשיו אומר x = malloc (sizeof (int)), זו היא דרך מפוארת לומר, היי מערכת הפעלה, באמצעות malloc, תן לי מספיק זיכרון לגודל של int, שהוא כנראה הולך להיות 32 סיביות או ארבעה בתים. אז מה עושה malloc לחזור? Malloc מחזיר את כתובת. אז מה הולך לקבל מאוחסן בx? הכתובת של הנתח של זיכרון, ארבעה הבתים, malloc ש פשוט מצאו לי בשאלה מערכת ההפעלה. עכשיו בינתיים, שורה ארבעה כאן, * x = 42. רק שיהיה ברור, מה קורה שם למטה? בצד השמאל, * x. זה כמו * 33 רחוב אוקספורד. אז * x אומר מה? קהל: עבור ל. דוד י מלאן: מעבר לכתובת ש. בכל מקום שנתח זה של זיכרון הוא, ללכת אליו. ולשים את מה שיש, ללא ספק? קהל: 42. דוד י מלאן: 42. בסדר, y *, אותו רעיון. גש לכתובת בy. שים את המספר 13 שם, אבל מה הוא y באותו הרגע? קהל: אין זיכרון לy. דוד י מלאן: יש אין זיכרון לy. אז מה עושה y כנראה להכיל, כפי שאנו כבר אומרים? קהל: אשפה. דוד י מלאן: ערך אשפה חלק. עכשיו, ערך אשפה הוא עדיין מספר. זה עדיין יכול להיחשב בטעות לכתובת. זה כאילו מישהו רשם משהו, ואני שלא כהלכה את זה כמשמעות בניין כמה במורד הרחוב. ואם אתה רק מנסה להיכנס איזה בניין שאינו בבעלות, או כמה נתח של זיכרון יש לך לא היה נתון, דברים רעים עלולים לקרות. מחשב עלול לקרוס, או כמה אחר התנהגות לא נקבע שעלולה לקרות. אז intro, אז, לינקי הוא זו. אני עדיין זוכר, 20 כמה שנים מאוחר יותר מוזרות, איפה הייתי כשאני סוף סוף הבין מצביעים. כלומר, אם אתה תצא מכאן בשלוש דקות וחושב שאני לא מבין מצביעים, מבין יש לי זכרתי ל20 שנים מסיבה כלשהי מטורפת מתי ולמה זה סוף סוף שקוע ב, יושב עם ההוראה שלי , נישאט מהטה בבחור אחורי של חדר אוכל אליוט. עכשיו, אני כבר נזכרתי זה בגלל שזה היה אחד הנושאים שאני, ב בפרט, נאבק עם. ואז, פתאום קלט, כמו שאני מעז לומר הרבה נושאים סופו של דבר. ועכשיו, כדי שזה מרגיש כל מאושר יותר ומשכנע כל עוד, בואו נסתכל סופי בנו שלוש דקות האחרונות כאן בינקי, מידידנו, ניק Parlante מאוניברסיטת סטנפורד. [וידאו השמעה] היי, בינקי. תתעורר! זה זמן בשביל כיף מצביע. 'מה זה? למד על מצביעים? אה, טופי! "טוב, כדי להתחיל, אני מניח שאנחנו הולך צריך כמה עצות. "או-קיי. קוד זה מקצה שני מצביעים, אשר יכול להצביע על מספרים שלמים. "או-קיי. ובכן, אני רואה שני מצביעים, אבל הם אין נראה שיש להצביע לכל דבר. -That נכון. בתחילה, מצביעים אינו מצביע על שום דבר. הדברים שהם מצביעים עליהם בשם pointees, והקמתם של צעד נפרד. אה, נכון, נכון. ידעתי ש. Pointees הם נפרדים. Er, אז איך אתה להקצות pointee? "או-קיי. ובכן, את הקוד הזה מקצה pointee השלם חדש, וx סטי חלק זה להצביע על זה. היי, זה נראה טוב יותר. אז להפוך אותו לעשות משהו. "או-קיי. אני יהיה dereference x המצביע לאחסן את המספר 42 לpointee. על הטריק הזה, אני אצטרך שלי שרביט קסמים של ביטול הפניה. שרביט קסמי -Your של ביטול הפניה? That-- זה נהדר. -זהו מה הקוד נראה. אני רק להגדיר את המספר, ו[ POP] היי, נראה. הנה זה מתחיל. 'אז עושה dereference על x כדלקמן החצים כדי לגשת pointee. במקרה זה, חנות 42 שם. היי נסה להשתמש בו כדי לאחסן את המספר 13 באמצעות המצביע האחר, y. "או-קיי. אני פשוט אלך לכאן כדי y, ולקבל את הסט עד מספר 13. ולאחר מכן, לקחת את השרביט של ביטול הפניה ורק [BUZZ] אה! אה, היי! זה לא עבד. אומר, בינקי, אני לא חושב שביטול הפניה למבנה y הוא רעיון טוב, כי אתה יודע, הקמת pointee הוא צעד נפרד. ואני לא חושב שאי פעם עשינו את זה. נקודת -Good. 'כן. אנחנו הקצו את y המצביע, אבל אנחנו אף פעם לא להגדיר אותו כך שיצביע על pointee. -Very שומרי מצוות. היי, אתה נראה טוב שם, בינקי. האם אתה יכול לתקן את זה כדי שנקודתי y לאותו pointee כx? -Sure. אני אשתמש בשרביט הקסמים שלי של הקצאת פוינטר. 'האם זה הולך להיות בעיה כמו בעבר? 'לא. זה לא נוגע pointees. זה פשוט משנה את מצביע אחד ל מצביע על אותו הדבר כמו אחר. אה, אני רואה. עכשיו נקודות y לאותו המקום כמו x. אז תחכה. עכשיו, y הוא קבוע. יש לו pointee. אז אתה יכול לנסות את השרביט של ביטול הפניה שוב לשלוח מעל 13. -אה, על אישור. כאן זה הולך. [POP] היי, תראה את זה. עכשיו ביטול הפניה למבנה עבודות על y. ומכיוון שהמצביעים משתפים שpointee אחד, שניהם רואים 13. 'כן. שיתוף, לא משנה מה. אז אנחנו הולכים להתחלף עכשיו? אה, תראה. אנחנו מחוץ לזמן. -But-- פשוס לזכור שלושה כללי מצביע. טלפון אחד, את המבנה הבסיסי הוא שיש לך מצביע, והוא מצביע על לpointee. אבל והמצביע pointee הם נפרדים, והשגיאה הנפוצה הוא להגדיר מצביע, אבל לשכוח לתת לו pointee. מספר שתיים, ביטול הפנית מצביע מתחיל במצביע וכדלקמן חיצו מעל כדי לגשת pointee. כפי שכולנו יודעים, זה עובד רק אם יש pointee, איזה סוג של חוזר לכלל מספר אחת. מספר שלוש, מצביע משימה לוקחת מצביע אחד ומשנה אותו כך שיצביע על אותו pointee כמצביע אחר. אז אחרי המשימה, שני מצביעים יצביע לאותו pointee. לפעמים, זה נקרא שיתוף. וזה כל מה שיש בו, באמת. ביי ביי עכשיו. [END הפעלת וידאו] דוד י מלאן: זהו זה לCS50. אנחנו אראה אותך בשבוע הבא.