다음을 인쇄하는 C ++ 코드가 있습니다 size_t
.
size_t a;
printf("%lu", a);
32 비트 및 64 비트 아키텍처 모두에서 경고없이 컴파일하고 싶습니다.
이것이 C99라면 printf("%z", a);
. 그러나 AFAICT %z
는 표준 C ++ 방언에는 존재하지 않습니다. 그래서 대신에
printf("%lu", (unsigned long) a);
정말 추합니다.
size_t
언어에 내장 된 s 를 인쇄 할 수있는 기능이 없다면 size_t
, 좋은 것을 유지하면서 가짜 컴파일러 경고를 제거하기 위해 s에 적절한 캐스트를 삽입 할 printf 래퍼를 작성하는 것이 가능한지 궁금 합니다.
어떤 아이디어?
편집 내가 printf를 사용하는 이유를 명확히하기 위해 : 나는 정리하고있는 비교적 큰 코드베이스를 가지고 있습니다. printf 래퍼를 사용하여 “경고를 작성하고, 파일에 기록하고, 오류와 함께 코드를 종료”와 같은 작업을 수행합니다. cout 래퍼로이 작업을 수행하기에 충분한 C ++-foo를 수집 할 수 있지만 컴파일러 경고를 제거하기 위해 프로그램의 모든 warn () 호출을 변경하는 것은 아닙니다.
답변
대부분의 컴파일러에는 자체 지정자 size_t
와 ptrdiff_t
인수가 있습니다. 예를 들어 Visual C ++는 각각 % Iu와 % Id를 사용합니다. gcc를 사용하면 % zu 및 % zd를 사용할 수 있다고 생각합니다.
매크로를 만들 수 있습니다.
#if defined(_MSC_VER) || defined(__MINGW32__) //__MINGW32__ should goes before __GNUC__
#define JL_SIZE_T_SPECIFIER "%Iu"
#define JL_SSIZE_T_SPECIFIER "%Id"
#define JL_PTRDIFF_T_SPECIFIER "%Id"
#elif defined(__GNUC__)
#define JL_SIZE_T_SPECIFIER "%zu"
#define JL_SSIZE_T_SPECIFIER "%zd"
#define JL_PTRDIFF_T_SPECIFIER "%zd"
#else
// TODO figure out which to use.
#if NUMBITS == 32
#define JL_SIZE_T_SPECIFIER something_unsigned
#define JL_SSIZE_T_SPECIFIER something_signed
#define JL_PTRDIFF_T_SPECIFIER something_signed
#else
#define JL_SIZE_T_SPECIFIER something_bigger_unsigned
#define JL_SSIZE_T_SPECIFIER something_bigger_signed
#define JL_PTRDIFF_T_SPECIFIER something-bigger_signed
#endif
#endif
용법:
size_t a;
printf(JL_SIZE_T_SPECIFIER, a);
printf("The size of a is " JL_SIZE_T_SPECIFIER " bytes", a);
답변
printf
형식 지정은 %zu
C ++ 시스템에서 잘 작동합니다; 더 복잡하게 만들 필요가 없습니다.
답변
C ++ 11
C ++ 11 std::printf
은 C99를 가져 오므로 C99 %zu
형식 지정자를 지원해야 합니다.
C ++ 98
대부분의 플랫폼에서, size_t
그리고 uintptr_t
당신이 사용할 수있는 경우, 동일 PRIuPTR
에 정의 된 매크로를 <cinttypes>
:
size_t a = 42;
printf("If the answer is %" PRIuPTR " then what is the question?\n", a);
당신이 경우 정말 안전하려면, 캐스팅 uintmax_t
및 사용 PRIuMAX
:
printf("If the answer is %" PRIuMAX " then what is the question?\n", static_cast<uintmax_t>(a));
답변
답변
C ++를 사용하고 있으므로 IOStreams를 사용하지 않는 이유는 무엇입니까? 당신은 정의하지 않습니다 뇌사 C ++ 구현을 사용하지 않는로 즉 한, 경고없이 컴파일하고 오른쪽 종류를 인식하는 일을해야합니다 operator <<
위해를 size_t
.
실제 출력이으로 완료되어야 printf()
하는 경우에도이를 IOStreams와 결합하여 유형 안전 동작을 얻을 수 있습니다.
size_t foo = bar;
ostringstream os;
os << foo;
printf("%s", os.str().c_str());
매우 효율적이지는 않지만 위의 사례는 파일 I / O를 다루기 때문에이 문자열 형식화 코드가 아닌 병목 현상입니다.
답변
여기에 가능한 해결책이 있지만 꽤 좋은 해결책은 아닙니다 ..
template< class T >
struct GetPrintfID
{
static const char* id;
};
template< class T >
const char* GetPrintfID< T >::id = "%u";
template<>
struct GetPrintfID< unsigned long long > //or whatever the 64bit unsigned is called..
{
static const char* id;
};
const char* GetPrintfID< unsigned long long >::id = "%lu";
//should be repeated for any type size_t can ever have
printf( GetPrintfID< size_t >::id, sizeof( x ) );
답변
FMT 라이브러리 의 빠른 휴대용 (안전) 구현을 제공 printf
포함 z
개질제를 size_t
:
#include "fmt/printf.h"
size_t a = 42;
int main() {
fmt::printf("%zu", a);
}
또한 Python과 유사한 형식 문자열 구문을 지원하고 유형 정보를 캡처하므로 수동으로 제공 할 필요가 없습니다.
fmt::print("{}", a);
주요 컴파일러로 테스트되었으며 플랫폼간에 일관된 출력을 제공합니다.
부인 성명 : 저는이 도서관의 저자입니다.