c primer plus 專題16:C預處理器

1 翻譯程序的第一步

2 重新定義宏

3 帶參數宏

注意:帶參數宏定義中要使用 ( ) 括號將每個參數都包圍起來,以免出錯。

4 宏定義創建字符串:#運算符

執行流程:

5 預處理器粘合劑:##運算符

6 變參宏(... 和 __VA_ARGS__)

#include <stdio.h>

/* 按照 printf 格式輸入時,fmt 爲字符串,和前後的黏合起來 */
#define debug(fmt, ...)		printf("<- This is debug mode ->\n" fmt "\n", __VA_ARGS__)
	
int main(void)
{
	debug("debug message print\n");
	debug("%.2f + %.3f = %.5f", 2.1, 3.4, 2.1 + 3.4);

	return 0;
}

7 文件包含 #include 

8 其他指令

1 #undef 指令  取消宏定義

2 條件編譯

2.1 #ifdef    #else    #endif

2.2 #ifndef    #else    #endif  (常用來防止頭文件被重複包含)

3 #if    #else    #endif

defined 預處理運算符

4 預定義宏 (在代碼調試中非常有用)

#include <stdio.h>

int main(void)
{
	printf("This file is %s.\n", __FILE__);
	printf("This function is %s.\n", __func__);
	printf("This date is %s.\n", __DATE__);
	printf("This line is %d.\n", __LINE__);

	return 0;
}

5 #error

9 斷言 assert

C語言提供了斷言標準庫,#include <assert.h>

下面是標準庫 <assert.h> 的說明:

#ifdef NDEBUG

    #define assert(expression) ((void)0)

#else

    _ACRTIMP void __cdecl _wassert(
        _In_z_ wchar_t const* _Message,
        _In_z_ wchar_t const* _File,
        _In_   unsigned       _Line
        );

    #define assert(expression) (void)(                                                       \
            (!!(expression)) ||                                                              \
            (_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \
        )

#endif

這裏有一個疑問,((void)0)是什麼意思?

實際上,((void)0)表示一個什麼都不做的空語句

參考鏈接:https://stackoverflow.com/questions/2198950/why-is-void-0-a-no-operation-in-c-and-c

stm32官方提供的斷言機制(也是使用(void(0)) 或者打印文件名和行號)

// 用於斷言中檢查輸入參數
#define IS_GPIO_ALL_INSTANCE(INSTANCE) (((INSTANCE) == GPIOA) || \
                                        ((INSTANCE) == GPIOB) || \
                                        ((INSTANCE) == GPIOC) || \
                                        ((INSTANCE) == GPIOD) || \
                                        ((INSTANCE) == GPIOE) || \
                                        ((INSTANCE) == GPIOF) || \
                                        ((INSTANCE) == GPIOG))

// 使用斷言檢查參數
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));

// 關於斷言的宏定義(默認關閉斷言),位於 stm32f1xx_hal_conf.h 文件中
#ifdef  USE_FULL_ASSERT
/**
  * @brief  The assert_param macro is used for function's parameters check.
  * @param  expr If expr is false, it calls assert_failed function
  *         which reports the name of the source file and the source
  *         line number of the call that failed.
  *         If expr is true, it returns no value.
  * @retval None
  */
// 這裏使用 (void(0)) 來作爲空語句填充
// 如果斷言爲1,則爲空語句;如果斷言爲0,則調用 assert_failed 函數,這個函數需要我們自己實現
// assert_failed 函數傳入了文件和行號等作爲形參,我們可以打印來定位錯誤位置
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */

// 斷言函數實現,位於 main.c 中
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
  // 默認爲空,這裏還給出了推薦用法
	printf("Wrong parameters value: file %s on line %d\r\n", file, line);
}
#endif /* USE_FULL_ASSERT */

10 <string.g> 中的其他函數

1 memcmp 函數

2 memcpy 函數

3 memset 函數

這個函數相當有用,可以將一塊內存清零或置一,如下所示:

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

#define SIZE	50

int main(void)
{
	int data[SIZE];

	memset(data, 0, sizeof(int) * SIZE);		// 內存清 0
	memset(data, 0XFF, sizeof(int) * SIZE);		// 內存置 1

	return 0;
}

當執行內存清零時,整個數組如下所示:

當執行內存置一時,整個數組如下所示:

 

 

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