linux printf int64,关于stdint:如何在C中打印int64_t类型

博客讨论了在C99标准中使用int64_t类型时遇到的printf格式化问题。在不同的编译器和平台上,使用%lld、%I64d或其他格式化宏可能会产生警告。解决方案包括使用inttypes.h头文件中的格式化宏,如PRId64,以确保可移植性。同时提到了在不同系统中可能存在的差异,以及在Windows和Linux环境下的处理方式。
摘要由CSDN通过智能技术生成

C99标准具有整数类型,字节大小类似于int64_t。 我使用以下代码:

#include

#include

int64_t my_int = 999999999999999999;

printf("This is my_int: %I64d

", my_int);

我得到这个编译器警告:

warning: format ‘%I64d’ expects type ‘int’, but argument 2 has type ‘int64_t’

我尝试过:

printf("This is my_int: %lld

", my_int); // long long decimal

但我得到同样的警告。 我正在使用这个编译器:

~/dev/c$ cc -v

Using built-in specs.

Target: i686-apple-darwin10

Configured with: /var/tmp/gcc/gcc-5664~89/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1

Thread model: posix

gcc version 4.2.1 (Apple Inc. build 5664)

我应该使用哪种格式打印my_int变量而不发出警告?

对于C ++,请参阅stackoverflow.com/questions/8132399/how-to-printf-uint64-t

对于int64_t类型:

#include

int64_t t;

printf("%" PRId64"

", t);

对于uint64_t类型:

#include

uint64_t t;

printf("%" PRIu64"

", t);

您也可以使用PRIx64以十六进制打印。

cppreference.com包含所有类型的可用宏的完整列表,包括intptr_t(PRIxPTR)。 scanf有单独的宏,如SCNd64。

PRIu16的典型定义是"hu",因此隐式字符串常量级联在编译时发生。

要使代码完全可移植,必须使用PRId32等打印int32_t,"%d"或类似打印int。

格式化宏常量的完整列表:en.cppreference.com/w/cpp/types/integer

请注意,这不是"%PRId64 n",而是字符串连接...

而且,如果在Linux上使用C ++,请确保在包含inttypes.h之前#define __STDC_FORMAT_MACROS。

PRId64是一个内部转换为"lld"的宏。所以,它与编写printf("%lld

", t);一样好请参阅说明:qnx.com/developers/docs/6.5.0/

@Gaurav,这在某些平台上是正确的,但不是全部。例如,在我的amd64 Linux机器上,PRId64被定义为ld。可移植性是宏的原因。

我认为通过一些额外的努力,他们可能会使它更加令人讨厌

显然gcc集合的头代码不匹配,导致PRId64在64位linux上定义为"ld",在32位上定义为"lld",这是不正确的。

C99的方式是

#include

int64_t my_int = 999999999999999999;

printf("%" PRId64"

", my_int);

或者你可以投!

printf("%ld", (long)my_int);

printf("%lld", (long long)my_int); /* C89 didn't define `long long` */

printf("%f", (double)my_int);

如果你坚持使用C89实现(特别是Visual Studio),你可以使用开源(和):http://code.google.com/p/msinttypes/

在code.google.com链接中使用msinttypes时,我需要定义__STDC_FORMAT_MACROS。请参阅stackoverflow.com/questions/8132399/how-to-printf-uint64-t。

谢谢你的抬头,@ariscris。看起来只有C ++才需要宏。链接到的代码中的定义位于#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)内

使用C99,%j长度修改器也可以与printf系列函数一起使用,以打印int64_t和uint64_t类型的值:

#include

#include

int main(int argc, char *argv[])

{

int64_t  a = 1LL << 63;

uint64_t b = 1ULL << 63;

printf("a=%jd (0x%jx)

", a, a);

printf("b=%ju (0x%jx)

", b, b);

return 0;

}

使用gcc -Wall -pedantic -std=c99编译此代码不会产生警告,程序将打印预期的输出:

a=-9223372036854775808 (0x8000000000000000)

b=9223372036854775808 (0x8000000000000000)

这是根据我的Linux系统上的printf(3)(手册页明确指出j用于表示转换为intmax_t或uintmax_t;在我的stdint.h中,int64_t和以完全相同的方式进行typedef,对于uint64_t类似。我不确定这是否完全可以移植到其他系统。

如果%jd prnts intmax_t,则正确的调用将是printf("a=%jd (0x%jx)", (intmax_t) a, (intmax_t) a)。无法保证int64_t和intmax_t是相同的类型,如果不是,则行为未定义。

如果在将它们传递给printf之前将它们显式转换为intmax_t,则可以移植使用%jd来打印int64_t值:printf("a=%jd

", (intmax_t)a)。这避免了(恕我直言)宏的丑陋。当然,这假设您的实现支持%jd,int64_t和intmax_t,所有这些都是由C99添加的。

来自嵌入式世界,甚至uclibc并不总是可用,代码就像

uint64_t myval = 0xdeadfacedeadbeef;

printf("%llx", myval);

是打印废话或根本不工作 - 我总是使用一个小助手,允许我正确转储uint64_t十六进制:

#include

#include

#include

char* ullx(uint64_t val)

{

static char buf[34] = { [0 ... 33] = 0 };

char* out = &buf[33];

uint64_t hval = val;

unsigned int hbase = 16;

do {

*out ="0123456789abcdef"[hval % hbase];

--out;

hval /= hbase;

} while(hval);

*out-- = 'x', *out = '0';

return out;

}

在Windows环境中,使用

%I64d

在Linux中,使用

%lld

%lld是long long int的格式,不一定与int64_t相同。 有一个宏,用于int64_t的正确格式;看到ouah的回答。

@KeithThompson但是,由于long long至少为64位,printf("%lld", (long long)x);应该可以工作,除了-0x8000000000000000,如果该类型不使用二进制补码,则无法表示为long long。

@PascalCuoq:是的,它应该与强制转换一起工作(你提到的异常是非常不可能的,只适用于支持二进制补丁但不用于long long的系统)。

//VC6.0(386及更高)

__int64 my_qw_var = 0x1234567890abcdef;

__int32 v_dw_h;

__int32 v_dw_l;

__asm

{

mov eax,[dword ptr my_qw_var + 4]   //dwh

mov [dword ptr v_dw_h],eax

mov eax,[dword ptr my_qw_var]   //dwl

mov [dword ptr v_dw_l],eax

}

//Oops 0.8 format

printf("val = 0x%0.8x%0.8x

", (__int32)v_dw_h, (__int32)v_dw_l);

问候。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值