它是危险的促进printf的参数类型? [英] Is it dangerous to promote types in printf arguments?

查看:119
本文介绍了它是危险的促进printf的参数类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的提问从试图尝试建立的多比特深度平台(32/64为例)时,用printf登录事情干。

My questions stem from trying to use printf to log things when trying to build for multiple bit-depth platforms (32/64 for example).

这一直饲养它丑恶的头一个问题是试图打印在多架构整数。在32位这会是这样

A problem that keeps rearing its ugly head is trying to print ints on multiple architectures. On 32 bit it would be something like

printf(" my int: %d\n", myInt);

但在64位,它必须被改变到

but on 64 bit, it would have to be changed to

print (" my int: %ld\n", (long)myInt);

我有两个相关的问题:

I have two related questions:


  1. 我首先想到的是,当你告诉的printf打印变量,给它一个格式,它看起来在这个变量的地址,当它需要的格式,获取尽可能多的字节。这似乎是一个很大的问题在第一。例如,如果你有一个变量myChar这是一个char(1字节),但使用的%D的格式说明,这会告诉printf的去myChar的地址,并抢在接下来的4个字节把它当作一个int。如果是这样的话,似乎如printf将抓住从邻近的变量垃圾日期(因为它抓住4个字节,但真正的价值只有1个字节)。这似乎不是这样但是。通过使用myChar并指定%D,printf的抓住1个字节,然后垫与0上3个字节。我的理解是正确的吗?

  1. My first thought was that when you tell printf to print a variable, giving it a format, it would look at the address of that variable and grab as many bytes as it needed for that format. This seemed like a big problem at first. For example if you had a variable myChar that was a char (1 byte), but used a format specifier of %d, that would tell printf to go to the address of myChar and grab the next 4 bytes to treat it like an int. If this were the case, it seems like printf would grab garbage date from neighboring variables (because it was grabbing 4 bytes, but the real value is only 1 byte). This appears to not be the case however. By using myChar and specifying %d, printf grabs 1 byte and then pads the upper 3 bytes with 0's. Is my understanding correct here?

如果上面是真实的,有没有总是推动变量到自己最大的价值,以避免类型的32/64位的情况下看到问题的任何实际伤害。例如,如果你有一个简短的变量myShort,和一个int变量,敏,有没有始终打印它们的任何缺点:

If the above is true, is there any real harm in always promoting variables up to their largest values to avoid the types of problems seen in the 32/64 bit case. For example if you have a short variable myShort, and an int variable, myInt, is there any downside in printing them always as:

的printf(%myShort LD,(长)myShort);
的printf(%敏LD,(长)敏);

printf("myShort %ld", (long)myShort); printf("myInt %ld", (long)myInt);

感谢任何澄清。

推荐答案

关于的printf :在您选址的情况下,%D必须通过规范处理平台定义的'廉政'的数据类型。不要紧,无论是32位,64位,128位或线性AS / 400的价值。如果你想推广的价值,更大的字段类型(以及相匹配的推广与相关格式字符串粒子),你当然可以自由地这样做,

Regarding printf: In the case you sited, "%d" must, by specification, handle the platform-defined 'int' data type. It doesn't matter whether it is 32bits, 64bits, or 128bit linear AS/400 value. If you want to promote the value to a larger field type (and match that promotion with the related format string particle) you're certainly free to do so,

int a=0;
printf("%ld", (long)a);

使用推广肯定定义的行为。

is certainly defined behavior using promotion.

我觉得你的问题的真正关键来如以下情况,以及是否强制推广能解决出现的任何问题。例如:

I think the real crux of your question comes in cases like the following, and whether forcing promotion can "solve" any problems that arise. For example:

char ch = 'a';
printf("%d", ch);

或者怎么样:

char ch = 'a';
printf("%ld", (long)ch);

或也许这(你似乎这是实际情况要尽量避免):

or maybe this (which is the real condition you seem to be trying to avoid):

char ch = 'a';
printf("%ld", ch);

第一项工作,但只是因为任何事物的最小尺寸的VA-ARG名单上叠推是一个 INT 平台尺寸。编译器将自动提升价值为您一个int。由于%D需要一个平台 INT 所有会出现很好。

The first of these will work, but only because the minimum size of anything stack-pushed on a va-arg list is the platform-size of an int. The compiler will auto-promote the value to an int for you. Since "%d" expects a platform int all will appear well.

第二个将工作的总是的,并完全支持。有一个从字符明确和界定推广长。即使是64位(或更大),它仍然可以工作。

The second will work always and is fully supported. There is a clear and defined promotion from char to long. Even if long is 64bits (or larger) it will still work.

三是UB一路。 的printf 正在寻找一个键,将只psented $ P $一个字节 INT 。如果这似乎你的平台上工作,然后检查 INT 您的平台宽度和。这是可能的工作,只是因为你的平台 INT 是相同的位宽。它使移植的code,在那里他们没有平台时的乐趣惊喜,因为它是通过VA-ARG推,你不会看到它,直到的真正的不同宽度进来玩了。

The third is UB all the way. printf is looking for a long and will be presented with only bytes for an int. If this seems to "work" on your platform, then check your platform width for int and long. It is likely "working" only because your platform long and int are the same bit-width. It makes for fun surprises when porting the code to platforms where they are not, and since it is pushed through a va-arg, you won't see it until real different widths come in to play.

所有的这样说,现在抛出一个真实的地址的东西(什么,真的)如由 scanf函数需要和我们'重新寻找的东西完全不同。

All of that being said, now throw an actual address to something (anything, really) such as that required by scanf and we're looking at something entirely different.

int val;
sscanf("%ld",&val);

这是一个赛格故障等待发生。就像上面,你永远不会,如果你的平台和平台 INT 宽度相同知道这一点。借此code到一个框, INT 是不同的大小和preP自己的随后的核心文件的GDB负载。

This is a seg-fault waiting to happen. Just like above, you'll never know it if your platform long and platform int are the same width. Take this code to a box where long and int are different sizes and prep yourself for a gdb-load of the ensuing core file.

这篇关于它是危险的促进printf的参数类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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