printf()를 함수 또는 매크로로 랩하는 방법
면접 질문처럼 들릴 수 있지만 실제로는 현실적인 문제입니다.
저는 임베디드 플랫폼을 사용하고 있으며, 이러한 기능에 해당하는 기능만 사용할 수 있습니다.
- printf()
- snprintf()
①은,printf()
구현(및 시그니처)은 가까운 장래에 변경될 가능성이 있기 때문에 나중에 쉽게 이행할 수 있도록 구현(및 시그니처)에 대한 콜은 별도의 모듈에 존재해야 합니다.
이를 위해 로깅 콜을 일부 함수 또는 매크로로 랩할 수 있습니까?가 「」를 호출하는 입니다.THAT_MACRO("Number of bunnies: %d", numBunnies);
단, 위의 함수에 대한 호출은 한 곳에서만 볼 수 있습니다.
파파러:arm-gcc -std=c99
편집: 예를 들어 2000년 이후 베스트 프랙티스와 아마 훨씬 이전 단계에서 인라인 함수는 여러 가지 이유로 매크로보다 훨씬 우수합니다.
여기에는 다음 두 가지 방법이 있습니다.
변종 매크로
#define my_printf(...) printf(__VA_ARGS__)
「」를 전송
va_args
#include <stdarg.h> #include <stdio.h> void my_printf(const char *fmt, ...) { va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); }
, 또다있 there라는 것도 .vsnprintf
,vfprintf
할 수 것은 이든지.stdio
.
C99 를 사용할 수 있기 때문에, Variadic 매크로로 랩합니다.
#define TM_PRINTF(f_, ...) printf((f_), __VA_ARGS__)
#define TM_SNPRINTF(s_, sz_, f_, ...) snprintf((s_), (sz_), (f_), __VA_ARGS__)
이 있다고vprintf
뭐그 、 거잖잖요요요 요잖요요 。만약 그런 것이 있다면, 당신은 그것을 세르게이 L이 그의 답변에서 제공한 것과 같은 기능으로 포장할 수 있습니다.
위의 TM_PRINTF는 빈 VA_ARGS 목록에서는 작동하지 않습니다.적어도 GCC에서는 다음을 작성할 수 있습니다.
#define TM_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)
는 앞에 합니다.__VA_ARGS__
어어있있있있다다
#define TM_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)
##
하면 "token"이 사용됩니다.TM_PRINTF("aaa");
이것은 로그 전 시간을 인쇄하는 @ldav1의 우수한 답변의 약간 변경된 버전입니다.
#define TM_PRINTF(f_, ...) \
{ \
struct tm _tm123_; \
struct timeval _xxtv123_; \
gettimeofday(&_xxtv123_, NULL); \
localtime_r(&_xxtv123_.tv_sec, &_tm123_); \
printf("%2d:%2d:%2d.%d\t", _tm123_.tm_hour, _tm123_.tm_min, _tm123_.tm_sec, _xxtv123_.tv_usec); \
printf((f_), ##__VA_ARGS__); \
};
#define PRINTF(...) printf(__VA_ARGS__)
다음과 같이 동작합니다.
PRINTF를 하여 무한 후합니다.PRINTF(...)
로로 합니다.printf(__VA_ARGS__)
__VA_ARGS__
는 매개 변수화된 매크로 정의에서 지정된 인수를 나타내기 위해 사용됩니다(무한 인수에 이름을 붙일 수 없기 때문에).
콜을 2개의 괄호로 묶을 필요가 있는 경우는, 다음과 같이 할 수 있습니다.
#define THAT_MACRO(pargs) printf pargs
그 후 사용합니다.
THAT_MACRO(("This is a string: %s\n", "foo"));
^
|
OMG
이것은 프리프로세서의 관점에서 인수의 전체 목록이 하나의 매크로 인수가 되어 괄호로 대체되기 때문에 작동합니다.
이것은 그냥 하는 것보다 낫다.
#define THAT_MACRO printf
이를 통해 다음과 같이 정의할 수 있습니다.
#define THAT_MACRO(pargs) /* nothing */
이것은 매크로 인수를 "먹어버리고" 컴파일된 코드의 일부가 되지 않습니다.
업데이트 물론 C99에서는 이 기술은 사용되지 않습니다. 그냥 가변 매크로를 사용하고 행복하십시오.
제한된 라이브러리?임베디드 시스템?최대한의 퍼포먼스가 필요합니까?문제없어!
이 질문에 대한 답변에서 알 수 있듯이 어셈블리 언어를 사용하여 VA_LIST를 허용하지 않는 함수를 VA_LIST를 사용할 수 있는 함수로 래핑할 수 있습니다.따라서 적은 비용으로 자체 vprintf를 구현할 수 있습니다.
이 방법은 작동하며, 거의 확실하게 원하는 추상화 기능을 얻을 수 있지만, uClibc의 일부를 슬라이스함으로써 기능이 가득 찬 표준 라이브러리를 얻을 것을 권장합니다.모든 사이클이 반드시 필요한 경우를 제외하고, 이러한 솔루션은 조립품을 사용하는 것보다 휴대성이 뛰어나고 전반적으로 유용한 답변이 될 것입니다.
결국 그런 프로젝트가 존재하는 이유이기도 합니다.
언급URL : https://stackoverflow.com/questions/20639632/how-to-wrap-printf-into-a-function-or-macro
'source' 카테고리의 다른 글
VueJs: TypeError: Object(...)가 함수가 아닙니다. "withScopeId" (0) | 2022.08.27 |
---|---|
mapGetters를 모듈과 루트의 게터와 동시에 사용하는 방법 (0) | 2022.08.25 |
Vuex-persist가 localStorage에 아무것도 저장하지 않는 이유는 무엇입니까? (0) | 2022.08.25 |
Null Pointer를 명시적으로 슬로우하는 이유자연스럽게 일어나는 것이 아니라 예외인가? (0) | 2022.08.25 |
내부 클래스 개체에서 외부 클래스 개체를 가져오는 중 (0) | 2022.08.25 |