正确的格式说明打印指针(地址)? [英] Correct format specifier to print pointer (address)?

查看:195
本文介绍了正确的格式说明打印指针(地址)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

哪种格式说明我应该用打印变量的地址?我很困惑下面很多的。

Which format specifier should I be using to print the address of a variable? I am confused between the below lot.

%U - 无符号整数

%u - unsigned integer

%X - 十六进制值

%x - hexadecimal value

%P - 空指针

这将是打印的地址的最佳方式?

Which would be the optimum format to print an address?

推荐答案

最简单的答案,假设你不介意在不同平台之间的格式变化无常和变化,是标准的%P 标记。

The simplest answer, assuming you don't mind the vagaries and variations in format between different platforms, is the standard %p notation.

C99标准(ISO / IEC 9899:1999)说,在§7.19.6.1¶8:

The C99 standard (ISO/IEC 9899:1999) says in §7.19.6.1 ¶8:

P 参数应该是一个指向无效。指针的值是
  转换为打印字符的序列,在一个定义的实现
  方式。

p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.

(在C11 - ISO / IEC 9899:2011 - 资料在§7.21.6.1¶8)

(In C11 — ISO/IEC 9899:2011 — the information is in §7.21.6.1 ¶8.)

在一些平台上,将包括一个领先的 0X 和别人也不会,字母可能是小写或大写,而C标准甚至没有定义,这应是十六进制的输出虽然我知道没有实现的地方是没有的。

On some platforms, that will include a leading 0x and on others it won't, and the letters could be in lower-case or upper-case, and the C standard doesn't even define that it shall be hexadecimal output though I know of no implementation where it is not.

这是有点开放的辩论是否应该显式转换指针以(无效*)演员。它被明确,这通常是很好的(所以这是我做的),以及标准说的说法应是一个指向无效。在大多数机器上,你会逃脱省略有明确的转换。然而,这将一台机器上无论身在何处位再一个的char *的presentation 地址对于一个给定的内存位置是从的别的指针不同的'地址为同一存储器位置。这将是代替字节寻址,机字寻址。这种机器是不常见的(可能不适用)这些天,但我大学毕业后在工作第一台机器就是这样一个(ICL Perq)。

It is somewhat open to debate whether you should explicitly convert the pointers with a (void *) cast. It is being explicit, which is usually good (so it is what I do), and the standard says 'the argument shall be a pointer to void'. On most machines, you would get away with omitting an explicit cast. However, it would matter on a machine where the bit representation of a char * address for a given memory location is different from the 'anything else pointer' address for the same memory location. This would be a word-addressed, instead of byte-addressed, machine. Such machines are not common (probably not available) these days, but the first machine I worked on after university was one such (ICL Perq).

如果你不快乐与%P ,然后使用C99的实现定义的< inttypes.h> uintptr_t形式而不是:

If you aren't happy with the implementation-defined behaviour of %p, then use C99 <inttypes.h> and uintptr_t instead:

printf("0x%" PRIXPTR "\n", (uintptr_t)your_pointer);

这允许你微调再presentation适合自己。我选择了有大写的十六进制数字,这样的数字是均匀相同的高度,并在开始时的特征浸 0xA1B2CDEF 出现,因此,不会像 0xa1b2cdef 沿人数太多逢低上下。您的选择虽然很广泛的范围内。在(uintptr_t形式)铸件明确由GCC建议时,它可以读取在编译时格式字符串。我认为这是正确的,要求演员,但我敢肯定有一些谁也无视警告,并摆脱它的大部分时间。

This allows you to fine-tune the representation to suit yourself. I chose to have the hex digits in upper-case so that the number is uniformly the same height and the characteristic dip at the start of 0xA1B2CDEF appears thus, not like 0xa1b2cdef which dips up and down along the number too. Your choice though, within very broad limits. The (uintptr_t) cast is unambiguously recommended by GCC when it can read the format string at compile time. I think it is correct to request the cast, though I'm sure there are some who would ignore the warning and get away with it most of the time.

Kerrek要求在评论:

Kerrek asks in the comments:

我有点困惑标准的推广和可变参数。是否所有的指针获得标准晋升为void *?否则,如果为int * ,比如说,是两个字节,无效* 分别为4个字节,那么它会清楚可以读取从参数4字节的错误,非?

I'm a bit confused about standard promotions and variadic arguments. Do all pointers get standard-promoted to void*? Otherwise, if int* were, say, two bytes, and void* were 4 bytes, then it'd clearly be an error to read four bytes from the argument, non?

我是这样的误解,认为C标准说,所有对象指针必须是相同的大小,因此无效* 为int * 不能具有不同的尺寸。不过,我认为是C99标准的相关部分没有那么斩钉截铁(虽然我不知道哪里是什么我建议是真实的其实是假象实现的):

I was under the illusion that the C standard says that all object pointers must be the same size, so void * and int * cannot be different sizes. However, what I think is the relevant section of the C99 standard is not so emphatic (though I don't know of an implementation where what I suggested is true is actually false):

§6.2.5类型

¶26作废的指针应具有相同的重presentation和对齐要求为指针为字符类型。 39)同样,指向兼容类型的合格的或不合格的版本应具有相同的重presentation和对齐要求。所有指针结构类型应具有相同的重presentation和对齐要求对方。所有指向联合类型应具有相同的重presentation和对齐要求对方。指向其他类型不必具有相同的重presentation或对齐要求。

¶26 A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.39) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.

39)同样重presentation和对齐要求是为了暗示互换性作为函数的参数,从函数返回值,和工会的成员。

39) The same representation and alignment requirements are meant to imply interchangeability as arguments to functions, return values from functions, and members of unions.

(C11表示正好在部分§6.2.5,¶28和脚注48是相同的。)

(C11 says exactly the same in the section §6.2.5, ¶28, and footnote 48.)

因此​​,所有的指针的结构的大小必须彼此相同,并且必须共享相同的对准要求,即使指针指向所述结构可以具有不同的对齐要求。同样,对于工会。字符指针和空指针必须具有相同的尺寸和取向的要求。指针的变化对 INT (即 unsigned int类型符号int )必须将大小和对齐要求对方相同;类似的其它类型。但C标准没有正式说的sizeof(INT *)==的sizeof(无效*)。哦,这样有利于让你检查你的假设。

So, all pointers to structures must be the same size as each other, and must share the same alignment requirements, even though the structures the pointers point at may have different alignment requirements. Similarly for unions. Character pointers and void pointers must have the same size and alignment requirements. Pointers to variations on int (meaning unsigned int and signed int) must have the same size and alignment requirements as each other; similarly for other types. But the C standard doesn't formally say that sizeof(int *) == sizeof(void *). Oh well, SO is good for making you inspect your assumptions.

C标准明确不要求函数指针是大小对象指针一样。这是必要的,不要打破像DOS的系统不同的内存模型。在那里,你可以有16位的数据指针,但32位的函数指针,反之亦然。这就是为什么C标准并不强制函数指针可以转换为对象指针,反之亦然。

The C standard definitively does not require function pointers to be the same size as object pointers. That was necessary not to break the different memory models on DOS-like systems. There you could have 16-bit data pointers but 32-bit function pointers, or vice versa. This is why the C standard does not mandate that function pointers can be converted to object pointers and vice versa.

幸运(程序员打靶POSIX),POSIX步入违约和不强制要求函数指针和数据指针的大小相同:

Fortunately (for programmers targetting POSIX), POSIX steps into the breach and does mandate that function pointers and data pointers are the same size:

指针类型

所有的函数指针类型应具有相同的重presentation为类型的指针为void。一个函数指针转换为无效* 不得改变重presentation。从这样的转换导致的无效* 值可以转换回原来的函数指针类型,使用显式的转换,而不会丢失信息。

All function pointer types shall have the same representation as the type pointer to void. Conversion of a function pointer to void * shall not alter the representation. A void * value resulting from such a conversion can be converted back to the original function pointer type, using an explicit cast, without loss of information.

请注意:
  ISO C标准不要求,但它需要POSIX一致性。

Note: The ISO C standard does not require this, but it is required for POSIX conformance.

因此​​,它似乎是显式转换为无效* 强烈建议在传递指针时,一个可变参数函数,如code最高的可靠性的printf()。在POSIX系统,它是安全的函数指针转换为用于打印的空指针。在其他系统上,它不一定是安全要做到这一点,它也不一定是安全的,通过其他指针比无效* 不进行强制转换。

So, it does seem that explicit casts to void * are strongly advisable for maximum reliability in the code when passing a pointer to a variadic function such as printf(). On POSIX systems, it is safe to cast a function pointer to a void pointer for printing. On other systems, it is not necessarily safe to do that, nor is it necessarily safe to pass pointers other than void * without a cast.

这篇关于正确的格式说明打印指针(地址)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆