STM32學習筆記--assert_param斷言宏

1、基本概念 宏定義 在stm32f10x_conf.h頭文件中,有如下定義:

/* #define USE_FULL_ASSERT    1 */
#ifdef  USE_FULL_ASSERT
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
  void assert_failed(uint8_t* file, uint32_t line);
#else
  #define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */

   如果定義了宏USE_FULL_ASSERT,assert_param(expr)宏展開就是((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
    如果沒有定義宏USE_FULL_ASSERT,assert_param(expr)宏展開就是((void)0) 相當於什麼也不執行
    ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))是C語言的一個雙目運算符
    如果expr爲TRUE,assert(expr)就是(void)0不執行任何動作。
    如果expr爲FALSE, assert(expr)就是函數assert_failed((uint8_t *)__FILE__, __LINE__))
    void assert_failed(uint8_t* file, uint32_t line);只是在頭文件中的函數聲明,函數實體可以自己定義,例如使用printf查看。

void assert_failed(u8* file, u32 line) 
{ /* User can add his own implementation to report the file name and linenumber, 
ex: printf("Wrong parameters value: file %s on line %d\r\n", file,line) */ 
/* Infinite loop */ 
while (1) { } 
}


    注意__FILE__和__LINE__是標準庫中的宏定義

例如:GPIO_Init函數的斷言宏的使用:
 

assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
#define IS_GPIO_ALL_PERIPH(PERIPH) (((PERIPH) == GPIOA) || \
                                    ((PERIPH) == GPIOB) || \
                                    ((PERIPH) == GPIOC) || \
                                    ((PERIPH) == GPIOD) || \
                                    ((PERIPH) == GPIOE) || \
                                    ((PERIPH) == GPIOF) || \
                                    ((PERIPH) == GPIOG))

判斷輸入參數GPIOx是否是GPIOA、B、C、D、E、F、G中的一個

2、C語言自定義斷言函數實現斷言

#include<stdio.h>

#define USE_FULL_ASSERT    1
#ifdef  USE_FULL_ASSERT
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((unsigned char *)__FILE__, __LINE__))
  void assert_failed(unsigned char* file, unsigned int line); /*函數聲明*/
#else
  #define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */


int
main(int argc, char *argv)
{
    int a = 0;
    char str[10] = {0};

    printf("請輸入一個大於10的整數:");
    scanf("%d", &a);

    assert_param(a > 10);
    printf("輸入的整數是:%d\n", a);

    printf("請輸入一個字符串,長度不要超過%d :", sizeof(str) / sizeof(str[0]));
    scanf("%s", &str);

    assert_param(str != NULL && strlen(str) < 10);
    printf("輸入的字符串是:%s\n", str);

    return(0);
}

void
assert_failed(unsigned char* file, unsigned int line)
{
    printf("%s \r\n", file);
    printf("%d \r\n", line);

    while(1);
}

 運行平臺:w7+codeblocks

3、C語言庫函數實現斷言

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

int main()
{
    int a = 0;
    char str[10] = {0};

    printf("請輸入一個大於10的整數:");
    scanf("%d", &a);

    assert(a > 10);
    printf("輸入的整數是:%d\n", a);

    printf("請輸入一個字符串,長度不要超過%d :", sizeof(str) / sizeof(str[0]));
    scanf("%s", &str);

    assert(str != NULL && strlen(str) < 10);
    printf("輸入的字符串是:%s\n", str);

    return(0);
}

#include <assert.h>庫中有如下定義:

#ifdef NDEBUG
/*
 * If not debugging, assert does nothing.
 */
#define assert(x)	((void)0)

#else /* debugging enabled */

/*
 * CRTDLL nicely supplies a function which does the actual output and
 * call to abort.
 */
_CRTIMP void __cdecl __MINGW_NOTHROW _assert (const char*, const char*, int) __MINGW_ATTRIB_NORETURN;

/*
 * Definition of the assert macro.
 */
#define assert(e)       ((e) ? (void)0 : _assert(#e, __FILE__, __LINE__))

#endif	/* NDEBUG */

從庫函數中的定義可以看出,如果不需要使用C語言庫函數中的斷言功能

#define NDEBUG
#include <assert.h>

運行平臺:w7+codeblocks 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章