Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
Операторы проверки особенно полезны для описания двух разновидностей инвариантов: предусловий и постусловий: условий, которые должны быть истинными соответственно перед и после исполнения сегмента кода. Простым примером предусловий и постусловий является линейный поиск:
/* lsearch --- возвратить индекс с данным значением в массиве или -1, если не найдено */int lsearch(int *array, size_t size, int value) { size_t i; /* предусловие: array != NULL */ /* предусловие: size > 0 */ for (i = 0; i < size; i++) if (array[i] == value) return i; /* постусловие: i == size */ return -1;}Этот пример определяет условия, используя комментарии. Но не было бы лучше проверить условия с использованием кода? Это является задачей макроса
assert()#include <assert.h> /* ISO С */void assert(/* <i>скалярное выражение</i> */);Когда скалярное выражение ложно, макрос
assert()abort()abort()ch12-assert.clsearch()main()1 /* ch12-assert.с --- демонстрация операторов проверки */23 #include <stdio.h>4 #include <assert.h>56 /* lsearch --- возвращает индекс с данным значением в массиве или -1, если не найдено */78 int lsearch(int *array, size_t size, int value)9 {10 size_t i;1112 assert(array != NULL);13 assert(size > 0);14 for (i = 0; i < size; i++)15 if (array[i] == value)16 return i;1718 assert(i == size);1920 return -1;21 }2223 /* main --- проверить наши условия */2425 int main(void)26 {27 #define NELEMS 428 static int array[NELEMS] = { 1, 17, 42, 91 };29 int index;3031 index = lsearch(array, NELEMS, 21);32 assert(index == -1);3334 index = lsearch(array, NELEMS, 17);35 assert(index == 1);3637 index = lsearch(NULL, NELEMS, 10); /* won't return */3839 printf("index = %dn", index);4041 return 0;42 }После компиляции и запуска оператор проверки в строке 12 «выстреливает»:
$ <b>ch12-assert</b> /* Запуск программы */ch12-assert: ch12-assert.c:12: lsearch: Assertion 'array != ((void *)0)' failed.Aborted (core dumped)Сообщение от
assert()NULL((void*)0)'Сообщение '
Aborted (core dumped)ch12-assertcorecoreassert()Вы можете отменить оператор проверки, компилируя свою программу с помощью опции командной строки '
-DNDEBUG<assert.h>assert()$ <b>gcc -DNDEBUG=1 ch12-assert.c -о ch12-assert</b> /* Компиляция с -DNDEBUG */$ <b>ch12-assert</b> /* Запуск */Segmentation fault (core dumped) /* Что случилось? */Здесь мы получили настоящий дамп ядра! Мы знаем, что операторы проверки были запрещены; сообщения «failed assertion» нет. Что же случилось? Рассмотрите строку 15
lsearch()main()arrayNULLNULLNULLSIGSEGV