C printf。这是有效的代码吗?

时间:2014-09-27 12:58:00

标签: c

以下代码使用gcc输出14。为什么?

printf("%d", (int*)2+3); // This code is meant to be obfuscated! 

3 个答案:

答案 0 :(得分:11)

int *2作为地址投射。添加3会向其添加3*sizeof(int)。在您的系统上,似乎sizeof(int)等于4,这就是它给2 + 12 = 14的原因。

但是,您应该注意到给定的代码调用未定义的行为有两个原因:

  1. 对不指向数组元素的指针执行算术会导致未定义的行为。

  2. 7.21.6格式化输入/输出功能:

  3.   

    如果转换规范无效,则行为未定义。 282)如果任何参数是   不是相应转换规范的正确类型,行为是   未定义。

答案 1 :(得分:4)

这里有两个问题。

首先,您的表达式(int*)2+3导致未定义的行为,因为[几乎可以肯定] 0x2处没有有效数组扩展为0xE(14):

  

[C99: 6.5.6/8]:当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型。 如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向与原始元素偏移的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式。换句话说,如果表达式P指向数组对象的第i个元素,则表达式(P)+ N(等效地,N +(P))和(P)-N(其中N具有值n)分别指向数组对象的第i + n和第i-n个元素,只要它们存在即可。此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向一个超过数组对象的最后一个元素,如果表达式Q指向一个超过数组对象的最后一个元素,表达式(Q)-1指向数组对象的最后一个元素。 如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。如果结果指向数组对象的最后一个元素之后,则不应将其用作已计算的一元*运算符的操作数。

第二个是您使用%d格式说明符但提供指针类型的对象:

  

[C99: 7.19.6.1/9]:如果转换规范无效,则行为未定义。 如果任何参数不是相应转换规范的正确类型,则行为是   未定义。

这些因素中的任何一个足以说明你的程序没有任何有意义的输出。但是,如果你确实看到" 14"它是因为(int*)2导致指向0x2内存的指针,并且应用指针算术+3,尽管未定义的行为可能再添加sizeof(int)*3 0x2 + 4*3 1}}到指针。 0x2 + 120xE%d(14)。问题是通过sizeof(int) != sizeof(int*)打印此指针值甚至可能是{{1}}的系统上的安全漏洞。

如果你在面试中没有给出这个答案,你就不应该有这份工作;如果你在面试中没有给出这个答案,但你得到了这份工作,你就不应该接受这份工作。

答案 2 :(得分:0)

我认为它的代码无效,因为我们将整数指针(int *)传递给printf的第二个参数,并在第一个参数中定义一个整数格式(%d)。

我在c中没有更多的知识,但这是我的想法。