现在的位置: 首页 > 综合 > 正文

printf的一些用法和64位移植性问题

2014年03月10日 ⁄ 综合 ⁄ 共 1370字 ⁄ 字号 评论关闭
// Debian Linux 32bit
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h>

typedef struct data_t {
	unsigned int a:12;
	unsigned int b:20;
} data_t;

int main()
{
	uint8_t u8i = 1;
	uint16_t u16i = 1;
	uint32_t u32i = 1;
	uint64_t u64i = 1;

	data_t data;
	data_t *pdata = malloc(sizeof(data_t));

	//printf("%x", (unsigned int)data);	// Error: aggregate value used where an integer was expected
	printf("1 %x\n", *(unsigned int *)&data);
	printf("2 %x\n", u8i);	// OK
	printf("3 %x\n", u16i);	// OK
	printf("4 %x\n", u32i);	// OK
	printf("5 %llx\n", u64i);	// in 64bit, gcc will report warning, format '%llx' expect argument of type 'long long unsigned int', but argument 2 has type 'uint64_t'  
	printf("6 %lx\n", u64i);	// in 32bit, gcc will report warning, format '%lx' expect argument of type 'long unsigned int', but argument 2 has type 'uint64_t'
    printf("7 %"PRIu64"\n", u64i);    // OK, with portable format string introduced in C99

	printf("8 %p\n", pdata);	// OK, will automatically add prefix "0x"
	printf("9 %x\n", pdata);	// warning, and without prefix "0x" 
	printf("10 %#x\n", pdata);	// identical to %p, but with warning
	printf("11 %#lx\n", pdata);	// identical to %p, but with warning 

	free(pdata);
	return 0;
}

输出为:

1 80485c0
2 1
3 1
4 1
5 1
6 1
7 1
8 0x97e5008
9 97e5008
10 0x97e5008
11 0x97e5008

几个值得注意的地方:

1. 由于uint64_t在32位和64位机上的定义是不一样的,所以移植的时候会出warning。可以用C99引入的可移植的描述符:

这些宏一般都以PRI开头,可以参见/usr/include/inttypes.h,也可以见http://en.wikipedia.org/wiki/Printf#Format_placeholders

2. 如果一个结构体刚好是32位,想用%x输出,直接输出会出错,需要两次转型。 

3. 输出地址是优先选%p,它会自动输出"0x",并且也方便移植。

抱歉!评论已关闭.