שפת C/הקדם מעבד: הבדלים בין גרסאות בדף

תוכן שנמחק תוכן שנוסף
Atavory (שיחה | תרומות)
Atavory (שיחה | תרומות)
שורה 381:
</source>
אך יש מספר בעיות עם פתרון זה:
*הקוד הופך להיות פחות יעיל, מפני שאם אכן x לעולם אינו 0 - ביצענו בדיקה מיותרת.
*הקוד מסורבל יותר; קשה יותר להבין מה הפונקציה עושה.
*אם נעביר את הקוד לקובץ אחר או לשורה אחרת - הודעת השגיאה המודפסת סתם תבלבל.
 
כדי לפתור זאת, נוכל להשתמש ב[[#התניה באי-הגדרת קבוע|התניה באי-הגדרת קבוע]] וב[[#קבועים מקובלים|קבועים מקובלים]], כך:
<source lang = "c">
void foo(int x)
שורה 388 ⟵ 392:
if(!(x != 0))
{
printf("Assertion failed: 'x != 0' in line 80%d test.c%s", __LINE__, __FILE__);
exit(-1);
שורה 399 ⟵ 403:
}
</source>
אך הקוד הופך להיות אפילו יותר מסורבל.
 
כעת נראה איך להשתמש במאקרו assert להשגת אותה התוצאה, אך בפחות סרבול.
 
===השימוש במאקרו===
<source lang = "c">
void foo(int x)
{
#ifndef NDEBUG
if(!(x != 0))
{
printf("Assertion failed: 'x != 0' in line 80 test.c");
exit(-1);
}
#endif /* #ifndef NDEBUG */
float y = 1.0 / x;
...
</source>
 
משתמשים במאקרו assert בצורה הבאה:
===הגדרת המאקרו===
 
השימוש מתבצע בצורה הבאה:
<source lang = "c">
assert(<cond>);
</source>
כאשר cond הוא [[שפת C/ערכים בוליאניים ותנאים|ערך בוליאני]]. לדוגמה, אפשר לכתוב כך:
 
<source lang = "c">
assert(x != 0);
</source>
אם התנאי אינולא מתקייםיתקיים - התוכנית נעצרת, ומודפסתתדפיס הודעה שהתנאי המסויים לא התקייםכזו:
<source lang = "c">
Assertion failed: 'x != 0' in line 80 test.c
</source>
ותעצר.
 
אם יש שורה שלעולם אין להגיע אליה, אפשר לכתוב:
<source lang = "c">
assert(0);
void foo(int x)
</source>
{
אם בכל אופן התוכנית תגיע לשורה אי פעם (כלומר - יש טעות בקוד), התוכנית תדפיס הודעה כזו:
assert(x != 0);
<source lang = "c">
printf("Assertion failed: 'x != 0' in line 80100 testfoo.c");
float y = 1.0 / x;
...
}
</source>
ותעצר.
 
 
===דוגמאות===
 
 
נוכל להשתמש במאקרו כדי לפתור את הבעיה הקודמת שראינו:
<source lang = "c">
void foo(int x)
{
if(!assert(x != 0));
{
printf("Assertion failed: 'x != 0' in line 80 test.c");
exit(-1);
}
float y = 1.0 / x;
שורה 465 ⟵ 449:
</source>
 
לפעמים גם מוסיפים את המאקרו ב[[שפת C/ערכים בוליאניים ותנאים#switch-case|switch-case]] שלא אמור לקבל ערך ברירת-מחדל לעולם. לדוגמה, נתבונן בקטע הבא:
<source lang = "c">
switch(b)
void foo(int x)
{
case 1:
float y = 1.0 / x;
...
case 3:
}
...
</source>
case 15:
...
};
 
...
עם הנתונים המתאימים. המאקרו assert מאפשר לדעת בצורה נוחה האם תנאי מסויים שאנו מניחים שהוא מתקיים - אכן מתקיים. אפשר אף להוסיף את השורה
<source lang = "c">
assert(0);
</source>
קטע הקוד עשוי להתאים למצב בו b אמור לקבל בדיוק אחד משלושת הערכים 1, 3, ו15. במקרה זה, נוכל להוסיף את החלק הבא:
 
<source lang = "c">
switch(b)
שורה 494 ⟵ 479:
...
</source>
כך, אם אירעה שגיאה בקוד, נקבל הודעת שגיאה מתאימה.
במקומות אליהם לא אמורה התוכנית להגיע. אם תגיע לשם התוכנית - היא תעצור באופן מיידי. כדאי להתרגל לשימוש ב-assert, כיוון ששימוש תכוף בו יביא לגילוי מוקדם של תקלות רבות. היתרון בהיותו של assert מאקרו נעוץ באפשרות לבטל אותו: אם מהדרים את התוכנית עם [[שפת C/הקדם מעבד#קבועים מקובלים|הקבוע NDEBUG]], הוא הופך לביטוי ריק על ידי הקדם-מהדר, ולמעשה - נעלם, בלי שהיה צורך לשנות את הקוד. נראה דוגמה לשימוש בו ב[[שפת C/הקדם מעבד#דוגמה לקוד לניפוי שגיאות|דוגמה לקוד לניפוי שגיאות]].
 
==דוגמה לקוד לניפוי שגיאות==