40
ססססס סס' ססססס סס'2 2 - ססססס ססססססס סססססססס ס- ססססס ססססססס סססססססס סC C - ססס סססס ס- ססס סססס סC C I/O redirection I/O redirection סססססס ססססס סססססס ססססס ססססססס ססססססס סססססס סססססס ססססס סס סססססס ססססססס ססססס סס סססססס ססססססס

תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

  • View
    240

  • Download
    13

Embed Size (px)

Citation preview

Page 1: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

22תרגול מס' תרגול מס'

-העברת פרמטרים לתוכניות ב-העברת פרמטרים לתוכניות בCC-קלט ופלט ב-קלט ופלט בCCI/O redirectionI/O redirectionזיכרון דינמיזיכרון דינמימצביעיםמצביעיםמערכיםמערכיםגישות לא חוקיות לזיכרוןגישות לא חוקיות לזיכרון

Page 2: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

CCהעברת פרמטרים לתוכניות בהעברת פרמטרים לתוכניות ב-- כאשר כאשרmainmain:נקראת מועברים אליה שני פרמטרים: נקראת מועברים אליה שני פרמטרים

argcargc מספר הארגומנטים בשורת הפקודה )כולל הפקודה - מספר הארגומנטים בשורת הפקודה )כולל הפקודה - עצמה(עצמה(

argvargv מצביע למערך של מחרוזות אשר מכילות את - מצביע למערך של מחרוזות אשר מכילות את - הארגומנטים בשורת הפקודההארגומנטים בשורת הפקודה

נכתוב תוכנית בשם נכתוב תוכנית בשםechoecho אשר תדפיס את הארגומנטים אשר תדפיס את הארגומנטים בשורת הפקודה שלה בשורה אחת עם רווח ביניהםבשורת הפקודה שלה בשורה אחת עם רווח ביניהם

:לדוגמא:לדוגמא> echo hello, worldhello, world>

הוחלט ש הוחלט שargv[0]argv[0] הוא שם התוכנית הנקראת. לכן הוא שם התוכנית הנקראת. לכן argcargc הוא הוא אין ארגומנטים אחרי שם התוכנית. אין ארגומנטים אחרי שם התוכנית. 11 הוא הוא argcargc. אם . אם 11לפחות לפחות

הם הם argv[2]argv[2] ו ו argv[0]argv[0], , argv[1]argv[1] ו ו 33 הוא הוא argcargcבדוגמא לעיל בדוגמא לעיל ""echo"echo", , "hello"hello",", ו ו ""worldworld""בהתאמה בהתאמה

Page 3: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

CCהעברת פרמטרים לתוכניות בהעברת פרמטרים לתוכניות ב-- הארגומט האופציונלי הראשון יהיה ב הארגומט האופציונלי הראשון יהיה בargv[1]argv[1] והאחרון יהיה ב והאחרון יהיה ב

argv[argc-1]argv[argc-1] בנוסף הסטנדרט קובע ש . בנוסף הסטנדרט קובע ש .argv[argc]argv[argc] יהיה מחרוזת יהיה מחרוזת ריקה.ריקה.

התוכנית התוכניתechoecho::#include#include <stdio.h> <stdio.h>/* echo command-line arguments *//* echo command-line arguments */intint main (int argc, char* argv[]) main (int argc, char* argv[]){{

intint i; i;forfor (i = 1; i < argc; i++) (i = 1; i < argc; i++)

printf ("%s ", argv[i]);printf ("%s ", argv[i]);printf ("\n");printf ("\n");returnreturn 0; 0;

}}

echo\0

hello,\0

World\0

argv

argc=3

NULL

Page 4: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

CCחזרה על קלט פלט בחזרה על קלט פלט ב-- פונקציות קלט/פלט נמצאות בספריה פונקציות קלט/פלט נמצאות בספריהstdio.hstdio.h כלומר צריך לבצע , כלומר צריך לבצע ,

#include#include <stdio.h> <stdio.h>

ניתן בעזרתן לבצע קלט מהמקלדת, פלט למסך וקלט/פלט לקבציםניתן בעזרתן לבצע קלט מהמקלדת, פלט למסך וקלט/פלט לקבצים:כדי להשתמש בקובץ יש צורך:כדי להשתמש בקובץ יש צורךלפתוח את הקובץ לקריאה או לכתיבהלפתוח את הקובץ לקריאה או לכתיבה..11לקרוא/לכתוב אל הקובץלקרוא/לכתוב אל הקובץ..22לסגור את הקובץלסגור את הקובץ..33 כל הפעולות על קבצים נעשות ע"י משתנה מטיפוס מצביע כל הפעולות על קבצים נעשות ע"י משתנה מטיפוס מצביע

((stdio.hstdio.h מוגדר ב מוגדר ב FILEFILE )הטיפוס )הטיפוס --FILEFILEלל:לדוגמא:לדוגמא

FILE* fd;FILE* fd;/* file descriptor *//* file descriptor */

Page 5: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

פתיחה של קובץפתיחה של קובץ 'פתיחת קובץ נעשית ע"י הפונק' פתיחת קובץ נעשית ע"י הפונקfopenfopen::

FILE* fopen(const char* filename,const char* mode);FILE* fopen(const char* filename,const char* mode);filenamefilenameשם הקובץ לפתיחה - שם הקובץ לפתיחה - modemode:המצב בו יש לפתוח את הקובץ: - המצב בו יש לפתוח את הקובץ - ""rr""פתח לקריאה בלבד - פתח לקריאה בלבד - ""ww""פתח לכתיבה בלבד - פתח לכתיבה בלבד - ""aa""פתח לכתיבה בסוף הקובץ - פתח לכתיבה בסוף הקובץ - הפונקציה מחזירה מצביע לערוץ הפתוח אם הצליחה לפותחו הפונקציה מחזירה מצביע לערוץ הפתוח אם הצליחה לפותחו

NULLNULLואחרת מחזירה ואחרת מחזירה :לדוגמא: לדוגמא

FILE* fd;FILE* fd;fd = fopen("hello.c" , "r");fd = fopen("hello.c" , "r");

אם פותחים קובץ לכתיבה והקובץ לא קיים עדיין, אזי הוא נוצר אם פותחים קובץ לכתיבה והקובץ לא קיים עדיין, אזי הוא נוצר. פתיחה לקריאה של קובץ . פתיחה לקריאה של קובץ fopenfopenבעקבות הקריאה לפונקציה בעקבות הקריאה לפונקציה

שאינו קיים גורמת לשגיאהשאינו קיים גורמת לשגיאה

Page 6: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

סגירה של קובץסגירה של קובץ סגירת קובץ שנפתח ע"י סגירת קובץ שנפתח ע"יfopenfopen 'נעשית ע"י הפונק' נעשית ע"י הפונק fclosefclose::

int fclose (FILE* fd);int fclose (FILE* fd);fclosefclose אם הצליחה ו אם הצליחה ו 00 מחזירה מחזירה EOFEOF.אם קרתה שגיאה. אם קרתה שגיאה :לדוגמא:לדוגמא

FILE* fd;fd = fopen("hello.c" , "r");/* Perform input/output on file */if (fclose(fd) == EOF)

printf ("Could not close file!\n");else printf ("File closed successfuly.\n");

בסיום ריצת תוכנית מערכת ההפעלה דואגת לסגור את כל בסיום ריצת תוכנית מערכת ההפעלה דואגת לסגור את כלהקבציםהקבצים

קיימת מגבלה על מספר הקבצים הפתוחים בו-זמנית עבור קיימת מגבלה על מספר הקבצים הפתוחים בו-זמנית עבורתוכנית מסויימתתוכנית מסויימת

Page 7: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

ערוצים סטנדרטייםערוצים סטנדרטייםבC- יש התייחסות אחידה לכל סוגי הקלט והפלט. גם הקלט מהמקלדת

FILEוהפלט מהמסך נעשים ע"י ערוצים ומצביעים ל כאשר תוכניתC מתחילה לרוץ מערכת ההפעלה פותחת עבורה בצורה

אוטומטית שלושה ערוצים סטנדרטיים:11..stdinstdin )נפתח לקריאה )בד"כ מהמקלדת22..stdoutstdout )נפתח לכתיבה )בד"כ אל המסך33..stderrstderr )נפתח לכתיבה )בד"כ אל המסךstdin, stdout ו stderr הם למעשה שמות משתנים כאשר כולם מטיפוס

.FILEמצביעים ל :לדוגמא הפקודה

fclose (stdin);fclose (stdin);תגרום לכך שלא ניתן יותר לקרוא קלט מהמקלדת

יש EOF אם תוכנית קוראת נתונים מהמקלדת ורוצים להקליד תו הערה:Ctrl-dלהקיש

Page 8: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

ערוצים סטנדרטייםערוצים סטנדרטיים:התוכנית התוכנית דוגמא:דוגמא copycopy

במידה וקבלה שני פרמטרים, מעתיקה את הקובץ אשר שמו במידה וקבלה שני פרמטרים, מעתיקה את הקובץ אשר שמוהנו הפרמטר הראשון, לקובץ אשר שמו הנו הפרמטר השניהנו הפרמטר הראשון, לקובץ אשר שמו הנו הפרמטר השני

במידה וקיבלה פרמטר יחיד, מעתיקה את הקובץ אשר שמו במידה וקיבלה פרמטר יחיד, מעתיקה את הקובץ אשר שמוהנו פרמטר זה לערוץ הפלט הסטנדרטיהנו פרמטר זה לערוץ הפלט הסטנדרטי

במידה ולא התקבלו שמות קבצים כלל, התוכנית מעתיקה את במידה ולא התקבלו שמות קבצים כלל, התוכנית מעתיקה אתמה שמתקבל בערוץ הקלט הסטנדרטי לערוץ הפלט מה שמתקבל בערוץ הקלט הסטנדרטי לערוץ הפלט

הסטנדרטיהסטנדרטי

Page 9: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

ערוצים סטנדרטייםערוצים סטנדרטיים#include <stdio.h>#define CHUNK_LEN 100void error(char *msg) {

fprintf(stderr, "Error: %s\n", msg);exit(1);

}int main(int argc, char *argv[]) {

FILE *in = stdin;FILE *out = stdout;char buf[CHUNK_LEN];if (argc>3) error("Bad Number of parameters");if (argc>1){

in = fopen(argv[1], "r");if (in==NULL) error("Can't open input file");

}if (argc>2) {

out = fopen(argv[2], "w");if (out==NULL) error("Can't open output file");

}while(fgets(buf, CHUNK_LEN, in) != NULL)

fputs(buf, out);fclose(in);fclose(out);return 0;

}

Page 10: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

ערוצים סטנדרטייםערוצים סטנדרטיים

char* fgets (char* line, int maxline, FILE *fp)char* fgets (char* line, int maxline, FILE *fp) קוראת שורה, כולל\'n’ מקובץ ,fp לתוך line לכל היותר .

maxline-1תווים יקראו מחזירהNULL-בסוף קובץ וב error אחרת מחזירה ,line

int fputs(char* line, FILE *fp)int fputs(char* line, FILE *fp) כותבת אתlineלקובץ מחזירהEOFאם יש שגיאה, אפס אחרת

char* gets(char* s)char* gets(char* s)-בדומה לfgetsרק מהקלט הסטנדרטי מחליף\'n’-0‘\ ב’

int puts(char* s)int puts(char* s)-בדומה לfpusרק אל הפלט הסטנדרטי מוסיף\'n’

Page 11: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

I/O redirectionI/O redirection

בכל תוכנית שרצה תחת בכל תוכנית שרצה תחתUnixUnix ערוץ הקלט הסטנדרטי מחובר ערוץ הקלט הסטנדרטי מחובר אל המקלדת, וערוצי הפלט והודעות השגיאה הסטנדרטיים אל המקלדת, וערוצי הפלט והודעות השגיאה הסטנדרטיים

מחוברים אל המסך כברירת מחדלמחוברים אל המסך כברירת מחדל ב בCShellCShell ניתן לכוון מחדש הן את ערוץ הקלט הסטנדרטי והן ניתן לכוון מחדש הן את ערוץ הקלט הסטנדרטי והן

את ערוצי הפלט והשגיאות הסטנדרטיים אל ומאת קבצים את ערוצי הפלט והשגיאות הסטנדרטיים אל ומאת קבצים redirectionredirectionכלשהם. הכיוון מחדש נקרא כלשהם. הכיוון מחדש נקרא stdout

stdin

stderr

Program

Page 12: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

Input redirectionInput redirection

<program> < < <filename> -תגרום לprogram לקבל את הקלט הסטנדרטי שלה מהקובץ

filename:לדוגמא

% copy < filename% copy < filename-תגרום ל copy הנתונה לקחת את הקלט מהקובץ filename ההפעלה בצורה הנ"ל שקולה )מבחינת התוצאה( עבור

להפעלה:copyהתוכנית % copy filename% copy filename

אך מה ההבדל מבחינת התוכנית?

Page 13: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

Output redirectionOutput redirection<program> > > <filename>

-תגרום לprogram לכתוב את הפלט הסטנדרטי שלה לקובץ filename אם קיים כבר קובץ בשם .filename לפני ביצוע

הפקודה, הפקודה לא תבוצע% cat myfile% cat myfileline 1line 1line 2line 2% cat myfile > out% cat myfile > out% cat out% cat outline 1line 1line 2line 2%%

Page 14: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

Output redirectionOutput redirection

<program> >> >> <filename> מכוונת את הפלט הסטנדרטי שלprogram לקובץ filename

אך משרשרת אותו לסוף הקובץ. אם לא קיים קובץ בשם filenameלפני ביצוע הפקודה, הפקודה לא תבוצע

% cat yourfile% cat yourfileline 3line 3% cat yourfile >> out% cat yourfile >> out% cat out% cat outline 1line 1line 2line 2line 3line 3%%

Page 15: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

Output redirectionOutput redirection

.ראינו ששתי פקודות כיוון הפלט הקודמות עלולות להיכשלהראשונה )<( אם הקובץ קיים, והשנייה )<<( אם הקובץ אינו קיים

! ניתן להבטיח שהפקודות הנ"ל יצליחו בכל מקרה ע"י הוספתלפקודות הכיוון:

<program> >! >! <filename> הורסת את הקובץfilename וכותבת עליו את הפלט הסטנדרטי של

program בכל מקרה אם הקובץfilename אינו קיים, אזי מתקבלת אותה התנהגות כשל

> <program> >>!>>! <filename>>

יוצרת את הקובץfilename.אם הוא לא קיים אם הקובץfilename>> קיים, אזי מתקבלת אותה התנהגות כשל

Page 16: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

Input and output redirectionInput and output redirection ניתן להפנות גם את ערוץ הקלט הסטנדרטי של התוכנית וגם ניתן להפנות גם את ערוץ הקלט הסטנדרטי של התוכנית וגם

את ערוץ הפלטאת ערוץ הפלט:לדוגמא הפקודות:לדוגמא הפקודות

% cat < in > out % cat < in > out % cat < in >! out% cat < in >! out

)מה ההבדל? ( )מה ההבדל? (outout לקובץ לקובץ ininגורמת להעתקת קובץ גורמת להעתקת קובץ

% cat < in >> out % cat < in >> out % cat < in >>! out % cat < in >>! out

)מה ההבדל?( )מה ההבדל?(outout לסוף קובץ לסוף קובץ ininגורמת להוספת קובץ גורמת להוספת קובץ

Page 17: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

Multiple redirectionMultiple redirection בנוסף להפנית קלט/פלט סטנדרטיים ניתן להפנות גם את ערוץ

השגיאות הסטנדרטי מהמסך אל קבצים<command> >& <file><command> >& <file>

מפנה הן את הפלט הסטנדרטי והן את ערוץ השגיאותfileהסטנדרטי לקובץ

% gcc try_input.c -o try_input > out_err% gcc try_input.c -o try_input > out_errtry_input.c: In function `main':try_input.c: In function `main':try_input.c:4: parse error before `printf'try_input.c:4: parse error before `printf'*** Error code 1*** Error code 1% more out_err% more out_err% gcc try_input.c -o try_input >& out_err% gcc try_input.c -o try_input >& out_err% more out_err % more out_err try_input.c: In function `main':try_input.c: In function `main':try_input.c:4: parse error before `printf'try_input.c:4: parse error before `printf'*** Error code 1*** Error code 1

הדבר יכול להיות שימושי כאשר נרצה לראות את השגיאותהראשונות שהקומפילר מוציא

Page 18: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

Multiple redirectionMultiple redirection

<command> >&! >&! <file> זהה לפקודה הקודמת אבל עובדת גם אם הקובץ זהה לפקודה הקודמת אבל עובדת גם אם הקובץfilefile קיים קיים

<command> >>& >>& <file> פועלת כמו במקרה הקודם, אבל כאן המידע החדש משורשר פועלת כמו במקרה הקודם, אבל כאן המידע החדש משורשר

אל סוף הקובץ. ניתן גם להיעזר ב- ! אם רוצים להבטיח כי אל סוף הקובץ. ניתן גם להיעזר ב- ! אם רוצים להבטיח כי הפקודה תתבצעהפקודה תתבצע

<command> >>&!>>&! <file>הפקודההפקודה

(<command> > > <f1>) >& >& <f2> גורמת לפלט הסטנדרטי להכתב אל הקובץ גורמת לפלט הסטנדרטי להכתב אל הקובץf1f1 ואילו להודעות ואילו להודעות

f2f2השגיאה להכתב אל קובץ השגיאה להכתב אל קובץ

Page 19: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

Multiple redirectionMultiple redirection#include#include <stdio.h> <stdio.h>intint main() main() {{

fprintf(stderr, “This is error\n”);fprintf(stderr, “This is error\n”);printf(“This is stdout\n”);printf(“This is stdout\n”);returnreturn 0; 0;

}}

> gcc prog.c –o prog> gcc prog.c –o prog> prog> progThis is errorThis is errorThis is stdoutThis is stdout> prog > out.txt> prog > out.txtThis is errorThis is error> cat out.txt> cat out.txtThis is stdoutThis is stdout> prog >& errout.txt> prog >& errout.txt> cat errout.txt> cat errout.txtThis is errorThis is errorThis is stdoutThis is stdout> )prog > out( >& err> )prog > out( >& err> cat out> cat outThis is stdoutThis is stdout> cat err> cat errThis is errorThis is error

Page 20: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

CCניהול זיכרון של תוכניות בניהול זיכרון של תוכניות ב-- משתנים ב משתנים בCC:נבדלים האחד מהשני בשני אופנים: נבדלים האחד מהשני בשני אופנים

למשל למשל –– טיפוסטיפוסintint, , charchar ו ו doubledouble שונים האחד מהשני מבחינת . שונים האחד מהשני מבחינת .הערכים האפשריים עבור כל אחד, אילו פעולות ניתן לבצע על כל הערכים האפשריים עבור כל אחד, אילו פעולות ניתן לבצע על כל

אחד מהם, וכמות הזיכרון שנדרשת עבור כל אחד מהם אחד מהם, וכמות הזיכרון שנדרשת עבור כל אחד מהם אופן ההקצאהאופן ההקצאה

אופנים: אופנים:44ניתן להקצות משתנים ב ניתן להקצות משתנים ב משתנים גלובלים משתנים גלובליםמשתנים לוקאלייםמשתנים לוקאלייםמשתנים סטאטייםמשתנים סטאטייםמשתנים דינמייםמשתנים דינמיים

Page 21: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

CCניהול זיכרון של תוכניות בניהול זיכרון של תוכניות ב--משתנים אשר מוגדרים לאורך כל - משתנים אשר מוגדרים לאורך כל משתנים גלובליםמשתנים גלובלים -

התוכנית וניתן לגשת אליהם מכל הפונקציות של התוכנית. התוכנית וניתן לגשת אליהם מכל הפונקציות של התוכנית. המשתנים מוקצים באופן אוטומטי כאשר התוכנית מתחילה, המשתנים מוקצים באופן אוטומטי כאשר התוכנית מתחילה,

ונשמרים לאורך כל הריצהונשמרים לאורך כל הריצהמשתנים פנימיים של פונקציות, רק - משתנים פנימיים של פונקציות, רק משתנים לוקאליםמשתנים לוקאלים -

הפונקציה שבה הם מוגדרים יכולה לגשת אליהם. משתנים הפונקציה שבה הם מוגדרים יכולה לגשת אליהם. משתנים אלו מוקצים בכל פעם שהפונקציה נקראת, ומשוחררים אלו מוקצים בכל פעם שהפונקציה נקראת, ומשוחררים

כאשר הפונקציה מסתיימתכאשר הפונקציה מסתיימתמשתנים פנימיים של פונקציות. - משתנים פנימיים של פונקציות. משתנים סטאטייםמשתנים סטאטיים -

משתנים אילו שומרים על ערכם בין קריאות שונות משתנים אילו שומרים על ערכם בין קריאות שונות לפונקציה, ומשוחררים רק בסיום התוכנית. קיים רק עותק לפונקציה, ומשוחררים רק בסיום התוכנית. קיים רק עותק

אחד של כל משתנה לאורך כל התוכניתאחד של כל משתנה לאורך כל התוכנית מבין שלושת הקבוצות הללו סוג המשתנים השימושי ביותר מבין שלושת הקבוצות הללו סוג המשתנים השימושי ביותר

הנו המשתנים הלוקאליים. שמוש בשאר סוגי המשתנים הנו המשתנים הלוקאליים. שמוש בשאר סוגי המשתנים נחשב לרוב כתכנות רע.נחשב לרוב כתכנות רע.

Page 22: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

משתנים דינמייםמשתנים דינמיים הבעיה עם משתנים לוקאלים הנה כי המשתנים נהרסים

כאשר פונקציה נגמרת. לעיתים נרצה כי משתנים מסוימים ישארו בזיכרון גם לאחר שהפונקציה נגמרת, יתר על כן

לעיתים נרצה להקצות בזמן ריצה מספר רב של משתנים אשר מספרם אינו ידוע בזמן כתיבת התוכנית אלא רק בזמן

ריצה מוקצים ע"י התוכנית בזמן ריצה. משתנים דינמייםמשתנים דינמיים -

המתכנת מקצה את המשתנים מאיזור בזיכרון המכונה ובאחריות המתכנת לשחרר את המשתנים (Heap)ערימה

שהוקצו לאחר שאין בהם צורך אי שחרור זכרון שהוקצה עלול לגרום לתוכנית להכשל עקב

חוסר בזיכרון הקצאת הזכרון מתבצעת ע"יmallocmalloc. שחרור הזכרון מתבצע ע"יfreefree.

Page 23: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מבנה הזיכרוןמבנה הזיכרון תוכנית המחשב רואה את הזיכרון כמערך גדול, של בתים תוכנית המחשב רואה את הזיכרון כמערך גדול, של בתים((bytesbytes))

לכל בית יש כתובת ייחודית לולכל בית יש כתובת ייחודית לוהתוכנית יכולה להיעזר בבית אחד או יותר בכדי לשמור משתניםהתוכנית יכולה להיעזר בבית אחד או יותר בכדי לשמור משתנים

שמות משתנים

נדרש בית אחד עבור ערך .char מסוג

בתים עבור 4נדרשים .int ערך מסוג

c

i

כתובת ערך0x200 (זבל)?0x201 'a'

0x202 ?0x203 60x204 00x205 00x206 00x207 ?

… …

Page 24: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מבנה הזיכרוןמבנה הזיכרון תוכנית המחשב רואה את הזיכרון כמערך גדול, של בתים תוכנית המחשב רואה את הזיכרון כמערך גדול, של בתים((bytesbytes))

לכל בית יש כתובת ייחודית לולכל בית יש כתובת ייחודית לוהתוכנית יכולה להיעזר בבית אחד או יותר בכדי לשמור משתניםהתוכנית יכולה להיעזר בבית אחד או יותר בכדי לשמור משתנים

זכרון המחשב מחולק עבור התוכנית לשני חלקים עיקרייםזכרון המחשב מחולק עבור התוכנית לשני חלקים עיקריים חלק המנוהל באופן אוטומטי ע"י התוכנית שם נשמרים המשתנים חלק המנוהל באופן אוטומטי ע"י התוכנית שם נשמרים המשתנים

הגלובלים, הלוקאלים והסטאטייםהגלובלים, הלוקאלים והסטאטייםheapheap ערימה( - חלק המנוהל ע"י המתכנת במפורש )ערימה( - חלק המנוהל ע"י המתכנת במפורש(

ניתן לבקש להקצות מחלק זה שטחי זיכרון בגדלים שונים ע"י ניתן לבקש להקצות מחלק זה שטחי זיכרון בגדלים שונים ע"י • mallocmallocהפקודה הפקודה

freefreeלשחרר זיכרון אשר אין בו צורך יותר ע"י הפקודה לשחרר זיכרון אשר אין בו צורך יותר ע"י הפקודה • פעולת ההקצאה מחזירה את הכתובת של תחילת שטח הזיכרון פעולת ההקצאה מחזירה את הכתובת של תחילת שטח הזיכרון

שהוקצה. בכדי לשמור כתובת זו יש להיעזר במשתנה מסוג מצביעשהוקצה. בכדי לשמור כתובת זו יש להיעזר במשתנה מסוג מצביע

Page 25: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מצביעיםמצביעיםמשתנה מסוג מצביעמשתנה מסוג מצביע

משתנה שערכו הוא כתובת בזיכרון שבתוכה נמצא נתון משתנה שערכו הוא כתובת בזיכרון שבתוכה נמצא נתון <type name> *<variable name> <type name> *<variable name> כלשהואכלשהוא

המשתנה מיועד להצביע על מקום בזיכרון המכיל משתנה מטפוס המשתנה מיועד להצביע על מקום בזיכרון המכיל משתנה מטפוס >>type nametype name<<

int *ptr;int *ptr;ptrptr הוא משתנה אשר מיועד להצביע על מקום בזיכרון מטפוס הוא משתנה אשר מיועד להצביע על מקום בזיכרון מטפוס intint

כתובותכתובותנניח שהגדרנו משתנה ע"י נניח שהגדרנו משתנה ע"י

int x;int x;הביטוי: הביטוי:

&x&xxxהוא הכתובת בזיכרון בה שמור תוכנו של הוא הכתובת בזיכרון בה שמור תוכנו של

אזי ערכו של אזי ערכו של 20002000 הוא שלוש ומאוחסן בכתובת הוא שלוש ומאוחסן בכתובת xxלמשל, אם למשל, אם 20002000 הוא הוא xx&&הביטוי הביטוי

Page 26: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מצביעיםמצביעים

שימוש במשתנה מסוג מצביעשימוש במשתנה מסוג מצביע

גישה למשתנה בעזרת מצביע לכתובתו

:הפקודה האחרונה שקולה לx=5.8. שימו לב כי מצביע הוא משתנה

בעצמו ולכן גם הוא נשמר בזיכרון.

float x;float* ptr;ptr = &x;*ptr=5.8;

.

.

.

.

.

.

2000ptr (address=10)

5.8x (address=2000)

1996

2004

14

6

Page 27: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מצביעים ומוצבעיםמצביעים ומוצבעיםהגדרת מצביע אינה גורמת ליצירת המקום אשר אליו הוא יצביע

int *pi; pi אינו מצביע למקום בזכרון המכיל integer יכול אלא רק

intלהצביע למקומות בזכרון המכילים *pi = 0 ;

למקום אליו מצביע 0הצבת pi עלולה לגרום להעפת התוכנית מצביע וגישה למקום אליו הוא piכיוון שלא ידוע להיכן בזכרון

"מצביע" עלולה להיות גישה לא חוקית לזכרון לפני גישה למקום בזכרון המוצבע ע"י מצביע יש לוודא כי

המצביע מצביע לכתובת חוקית. יש לאתחל מצביעים כך שיכילו לפני שמוכנסת אליהם כתובת חוקית, בצורה NULLאת הערך

זאת ניתן לבדוק האם הם אינם מצביעים לכתובת חוקיתint j ;int j ;int *pi ;int *pi ;pi = & j ;pi = & j ;*pi = 0;*pi = 0;

Page 28: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מצביעים ומערכיםמצביעים ומערכים יצירת מערך עם יצירת מערך עםnumbernumber איברים כאשר ערכי האינדקסים נעים איברים כאשר ערכי האינדקסים נעים

number-1number-1 ל ל 00בין בין <type name> <variable> [<number>]<type name> <variable> [<number>]int x[3];int x[3];

:גישה למקום במערך )חד-ממדי( ע"י: גישה למקום במערך )חד-ממדי( ע"י>>variable variable name>[<index>]name>[<index>]

x[2];x[2]; שם המערך" הנו מצביע אשר לא ניתן לשנות את המקום אליו "שם המערך" הנו מצביע אשר לא ניתן לשנות את המקום אליו"

ללא אינדקסים מהווה מצביע אל ללא אינדקסים מהווה מצביע אל xxהוא מצביע. לכן הביטוי הוא מצביע. לכן הביטוי x[0]=3x[0]=3 שקול ל שקול ל x=3x=3**המקום הראשון במערך! כלומר, המקום הראשון במערך! כלומר,

הגדרת מערך בגודלnumber גוררת הקצאת number אברים מהטפוס המתאים, בעוד שהגדרת מצביע אינה גורמת להקצאת

האיבר המוצבעניתן להצביע למערך )או איבר במערך( גם ע"י מצביעניתן להצביע למערך )או איבר במערך( גם ע"י מצביע

int *p, *q ;int *p, *q ;p = x ; p = x ; /* p points to x[0] *//* p points to x[0] */q = x+2 ; q = x+2 ; /* q points to x[2] *//* q points to x[2] */p = q-1; p = q-1; /* p points to x[1] *//* p points to x[1] */

Page 29: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מצביעים למצביעיםמצביעים למצביעים מצביע הנו משתנה, ולכן יש לו כתובת. ניתן להציב את כתובתו במשתנה מטיפוס מצביע הנו משתנה, ולכן יש לו כתובת. ניתן להציב את כתובתו במשתנה מטיפוס

מצביע למצביעמצביע למצביעintint a, b ; a, b ; /* a and b are integers *//* a and b are integers */intint *pi = &a ; *pi = &a ; /* pi is a pointer to integer /* pi is a pointer to integer that points to a */ that points to a */ intint** ppi = &pi; ** ppi = &pi; /* ppi is a pointer to pointer /* ppi is a pointer to pointer to integer. It points to pi */to integer. It points to pi */pi = &b ; pi = &b ; /* pi points to b *//* pi points to b */*pi = 5 ; *pi = 5 ; /* b is set to 5 *//* b is set to 5 */*ppi = &a ; *ppi = &a ; /* pi is set to &a, pi points to a now *//* pi is set to &a, pi points to a now */*pi = 6 ; *pi = 6 ; /* a is set to 6 *//* a is set to 6 */*)*ppi( = 7; *)*ppi( = 7; /* a is set to 7 *//* a is set to 7 */

נתעלם בדוגמא ממספר הבתים שנדרשים לכל משתנה)נתעלם בדוגמא ממספר הבתים שנדרשים לכל משתנה(((

כתובת ערך משתנה

0x200 0x202 ppi

0x201 'a'

0x202 0x205 pi

0x203 6

0x204

0x205 7 a

0x206

0x207 5 b

… …

Page 30: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

voidvoidמצביע למצביע ל-- ניתן להגדיר מצביע מטפוס ניתן להגדיר מצביע מטפוסvoidvoid** במצביע מטפוס זה ניתן לשמור כתובת . במצביע מטפוס זה ניתן לשמור כתובת .

של טפוס כלשהו של טפוס כלשהו

כיוון שלקומפיילר לא ידוע מהו הטפוס המוצבע ע"י על ידי מצביע מסוג כיוון שלקומפיילר לא ידוע מהו הטפוס המוצבע ע"י על ידי מצביע מסוגvoidvoid** בכדי לקבל את הערך המוצבע יש צורך ב , בכדי לקבל את הערך המוצבע יש צורך ב ,castcast שימיר את המצביע שימיר את המצביע

::voidvoidלמצביע לטיפוס ששונה מ למצביע לטיפוס ששונה מ

מצביע ל מצביע לvoidvoid הנו שמושי עבור פונקציות נהול הזיכרון הדינמי אשר הנו שמושי עבור פונקציות נהול הזיכרון הדינמי אשר מסוגלות להקצות שטח זכרון עבור טפוס כלשהו. שמושים נוספים למצביע מסוגלות להקצות שטח זכרון עבור טפוס כלשהו. שמושים נוספים למצביע

מסוג זה נראה בהמשך.מסוג זה נראה בהמשך.

voidvoid *ptr; *ptr;intint i; i;doubledouble d ; d ;……....ifif ) …( ) …(

ptr = &d ;ptr = &d ;elseelse

ptr = &i;ptr = &i;

intint *pi; *pi;intint j; j;pi = )pi = )intint*( ptr ;*( ptr ;j = *))j = *))intint *( ptr(; *( ptr(;

Page 31: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מצביעים והקצאות זיכרון דינמיותמצביעים והקצאות זיכרון דינמיותvoid* malloc )unsigned nbytes(void* malloc )unsigned nbytes(

אם ההקצאה הצליחה מוחזר מצביע לקטע בזיכרון, אחרת מוחזר אם ההקצאה הצליחה מוחזר מצביע לקטע בזיכרון, אחרת מוחזרNULLNULLהערך הערך

כיוון שהזכרון המוקצה יכול לשמש לשמירת ערכים מטיפוס כיוון שהזכרון המוקצה יכול לשמש לשמירת ערכים מטיפוס**voidvoid הנו הנו mallocmallocכלשהו, הטפוס המוחזר ע"י כלשהו, הטפוס המוחזר ע"י

ההגדרות של ההגדרות שלmallocmalloc ו ו NULLNULL נמצאים ב נמצאים ב stdlib.hstdlib.h לכן, כדי . לכן, כדי .להשתמש בהם יש לבצע:להשתמש בהם יש לבצע:

לדוגמא:לדוגמא:intint *ptr; *ptr;ptr=)int*(malloc)4(; ptr=)int*(malloc)4(; /* allocate 4 bytes *//* allocate 4 bytes */ifif )ptr==NULL( )ptr==NULL( /* check if allocated *//* check if allocated */

error)(;error)(; כעת כעתptrptr מצביע למקום בזיכרון שבו ארבעה בתים פנויים )אם מצביע למקום בזיכרון שבו ארבעה בתים פנויים )אם

ההקצאה הצליחה(ההקצאה הצליחה( כיוון ש כיוון שptrptr הנו מטפוס הנו מטפוס intint** ו ו mallocmalloc מחזירה ערך מטפוס מחזירה ערך מטפוס voidvoid** , ,

castingcastingיש לבצע יש לבצע

#include <stdlib.h>

Page 32: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מצביעים והקצאות זיכרון דינמיותמצביעים והקצאות זיכרון דינמיות ,כדי למנוע את הצורך בשינוי תוכנית בגלל גודל שונה של טיפוסים, כדי למנוע את הצורך בשינוי תוכנית בגלל גודל שונה של טיפוסים

sizeofsizeofבמהדרים שונים, ניתן להשתמש באופרטור במהדרים שונים, ניתן להשתמש באופרטור sizeof(<type name>)sizeof(<type name>)

מחזיר את מספר הבתים של הטיפוס במערכת הנוכחיתמחזיר את מספר הבתים של הטיפוס במערכת הנוכחיתptr=)int*(malloc)sizeof)int((;ptr=)int*(malloc)sizeof)int((;*ptr=3;*ptr=3;

)אם ההקצאה הצליחה( )אם ההקצאה הצליחה(intint כמשתנה מסוג כמשתנה מסוג ptrptr**כעת ניתן להשתמש ב כעת ניתן להשתמש ב

מה הטעות במיקרה זה?מה הטעות במיקרה זה?ptr=)int*(malloc)sizeof)int *((;ptr=)int*(malloc)sizeof)int *((;

Page 33: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

מצביעים והקצאות זיכרון דינמיותמצביעים והקצאות זיכרון דינמיות

free(<ptr var>)free(<ptr var>)

משחרר את בלוק הזיכרון שהוקצה ושמהמשתנה מצביע עליו. יש משחרר את בלוק הזיכרון שהוקצה ושמהמשתנה מצביע עליו. יש, כדי , כדי לאחר סיום השימוש בולאחר סיום השימוש בולשחרר כל בלוק זיכרון שהוקצה, לשחרר כל בלוק זיכרון שהוקצה,

למנוע מצב של חוסר זיכרון. דוגמא:למנוע מצב של חוסר זיכרון. דוגמא:ptr=)ptr=)int int *(malloc)sizeof)int((;*(malloc)sizeof)int((;ifif )ptr==NULL( )ptr==NULL(

error)(;error)(;/* use ptr *//* use ptr */free )ptr(;free )ptr(;

Page 34: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

גישות לא חוקיות לזיכרוןגישות לא חוקיות לזיכרון

טעויות נפוצותטעויות נפוצות

Page 35: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

גישה לא חוקית לזיכרוןגישה לא חוקית לזיכרון

מצביע יכול להכיל כל כתובת שהיאמצביע יכול להכיל כל כתובת שהיאזיכרון שלא הוקצה לשימושזיכרון שלא הוקצה לשימוש זיכרון שמשמש לדברים אחרים זיכרון שמשמש לדברים אחרים

– התוכנית עלולה לקרוס –התוכנית עלולה לקרוס / /Bus errorBus error Segmentation Segmentation FaultFault

התוכנית עלולה לרוץ כרגילהתוכנית עלולה לרוץ כרגיל אבל... ריצה מוצלחת על קלט אחד לא מבטיחה כלום על קלט אבל... ריצה מוצלחת על קלט אחד לא מבטיחה כלום על קלט

אחראחר

כל גישה )קריאה או כתיבה( דרך מצביע שאינו מצביע כל גישה )קריאה או כתיבה( דרך מצביע שאינו מצביעלכתובת חוקית עלולה לגרום לשגיאהלכתובת חוקית עלולה לגרום לשגיאה

Page 36: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

טעויות נפוצותטעויות נפוצות

הקצאת מחרוזת קצרה מדייהקצאת מחרוזת קצרה מדיי 00‘\‘\לא לשכוח את לא לשכוח את’’strlenstrlen כאשר היא מחזירה כאשר היא מחזירה ’’00‘\‘\ איננה סופרת את איננה סופרת את

אורך של מחרוזתאורך של מחרוזת-שימוש שגוי ב-שימוש שגוי בsizeofsizeof

האופרטור מקבל טיפוס של משתנההאופרטור מקבל טיפוס של משתנה ptr = )int*(malloc)sizeof)int *((;ptr = )int*(malloc)sizeof)int *((; ptr = )int*(malloc)sizeof)int((;ptr = )int*(malloc)sizeof)int((;

Page 37: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

טעויות נפוצות - המשךטעויות נפוצות - המשך

חריגה מגבולות המערךחריגה מגבולות המערך הקומפיילר לא שומר את האינפורמציה מהו גודל הקומפיילר לא שומר את האינפורמציה מהו גודל

המערך ולכן אינו מתריע בזמן קומפילציה על גישה המערך ולכן אינו מתריע בזמן קומפילציה על גישה מחוץ לגבולות המערך מחוץ לגבולות המערך

הזבל לסל וחסלהזבל לסל וחסל אחרי אחריfreefree אי אפשר להשתמש בזיכרון, גם לא אי אפשר להשתמש בזיכרון, גם לא

ממצביע אחרממצביע אחר

Page 38: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

טעויות נפוצות - המשךטעויות נפוצות - המשך

שימוש במשתנים לוקליים של פונקציה מחוץ שימוש במשתנים לוקליים של פונקציה מחוץלפונקציהלפונקציה

יצירת משתנה לוקלי בפונקציה, והחזרת הכתובת יצירת משתנה לוקלי בפונקציה, והחזרת הכתובתשלו לפונקציה הקוראתשלו לפונקציה הקוראת

== -ההבדל בין = ל- ==ההבדל בין = ל if)ptr == NULL( printf)“Bad pointer!\n”(;if)ptr == NULL( printf)“Bad pointer!\n”(; if)ptr = NULL( printf)“Bad pointer!\n”(;if)ptr = NULL( printf)“Bad pointer!\n”(;

Page 39: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

דוגמא – חריגה מגבולות המערךדוגמא – חריגה מגבולות המערך#include <stdio.h>#define TITLE )"\n\tMemory Corruption: How easy it is\n\n"(#define BUF_SIZE )8(int main)({

int i;char c[BUF_SIZE], buf[BUF_SIZE];printf)"Type string c[]\n"(;gets)c(;printf)"%s\n",c(;printf)"Type string buf[]\n"(;gets)buf(;printf)"%s\n",buf(;for )i=4; i > -10 ; i--({

c[i] = 'a';printf)"i= %2d, buf = %s c= %s\n", i, buf, c(;

}return 0;

}

Page 40: תרגול מס' 2 העברת פרמטרים לתוכניות ב-C קלט ופלט ב-C I/O redirection זיכרון דינמי מצביעים מערכים גישות לא חוקיות

00

11

22

33

44

55

66

\0\0

00

11

22

\0\0

זבלזבל

זבלזבל

buf

c

aa

Memory Corruption: How easy it is

Type string c[]

012

Type string buf[]

0123456

I = 4, buf = 0123456 c = 012

I = 3, buf = 0123456 c = 012aaÿ•

I = 2, buf = 0123456 c = 01aaaÿ•

I = 1, buf = 0123456 c = 0aaaaÿ•

I = 0, buf = 0123456 c = aaaaaÿ•

I = -1, buf = 0123456aaaaaaÿ• c = aaaaaÿ•

I = -2, buf = 012345aaaaaaaÿ• c = aaaaaÿ•

I = -3, buf = 01234aaaaaaaaÿ• c = aaaaaÿ•

Program mem_corruption.c)output(

aa

aaaa

aa

aa

aa

aa