【问题标题】:Strange C function returned variable type behaviour奇怪的 C 函数返回变量类型行为
【发布时间】:2013-10-14 13:44:17
【问题描述】:

我遇到了我不理解的行为。 我想要有趣的返回一个 2 字节的值。 我创建了一个 4 字节的 var 来进行一些处理并返回变量。 我的假设是变量被隐式转换为short。 但是,返回值似乎不是 2 字节,因为 printf fun 打印的值大于 2^16,除非我在 fun() 之前放置(短)。 这是为什么呢?

short fun()
{
long var = 2<<20;
return var;
}

printf("%i", fun());

【问题讨论】:

  • 参见:stackoverflow.com/questions/1255775/… 这个故事的寓意是,如果默认行为不是你想要的,就不要依赖它。
  • 另外,var 未初始化...
  • 您的代码首先返回一个未初始化的值。
  • 这是一个例子,只是为了说明问题......
  • 该代码只是我的代码中的一个示例,它已被初始化,问题是它不是零扩展或从 fun 返回时未转换为短。

标签: c types return


【解决方案1】:

return var;中,var的值被转换为函数的返回类型,即short。由于在 C 实现中该值超出了 short 的范围,因此存在溢出。 C 规范没有定义整数溢出时会发生什么。

尽管如此,行为还是有点奇怪。在printf 调用中,许多C 实现将仅使用来自fun() 的16 位,将它们提升为int,并将它们传递给printf。因此,尽管溢出,输出仍为“0”。

在您的情况下可能发生的情况是编译器通过简单地忽略它并将值保留在为var 保存的处理器寄存器中来实现到short 的转换(并使用相同的寄存器返回函数值)。这是 C 标准允许的,因为如果寄存器中的 long 值在 short 域中,那么当解释为 short 时,保持位不变会产生相同的值。如果long 值在short 域之外,那么发生什么并不重要,因为C 标准没有定义必须发生什么。

然后寄存器的内容直接作为参数直接传递给printf。同样,这是有效的,因为如果值在 short 域中,它会产生正确的结果,如果 var 值不在 short 域中,则允许任何操作。

【讨论】:

    【解决方案2】:

    你从 10 开始,左移 20 到 1000000000000000000000,这超出了 short 的范围并将它传递给一个获取可变参数的函数 (...)

    当 printf(和其他可变参数函数)查看值时,它基本上只是一个内存位置,它使用格式说明符将其转换回原始类型。这是它基本上在做什么的宏观示例:

    #define va_arg(ap,type)     (*(type *)(((ap)+=(((sizeof(type))+(sizeof(int)-1)) \
                                & (~(sizeof(int)-1))))-(((sizeof(type))+ \
                                (sizeof(int)-1)) & (~(sizeof(int)-1)))))
    

    如果您添加了将其转换为 short 的格式说明符,它可以看到转换后的 short。除此之外,只需保持(短)-ing 你的 fun()。

    【讨论】:

      【解决方案3】:

      诸如printf 之类的可变参数函数在其操作数上执行所谓的默认参数提升。特别是,小于int 的整数(例如short)在传递到可变参数函数时会自动扩大到int

      解决此问题的一种方法是使用h 长度修饰符,它表示“即使您正在处理int 值,也要假装它真的是short”。然后,printf 将在格式化输出之前将值缩小回short。例如:

      printf("%hi", fun());
      

      【讨论】:

      • 这并不能解释行为。如果printf 参数中的short 值被提升,那么结果仍然是short 值(在-32768 到32767 的范围内,显然在OP 的C 实现中就是这种情况)。它不会产生更大的价值。
      猜你喜欢
      • 1970-01-01
      • 2012-12-21
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 1970-01-01
      • 2019-05-29
      • 1970-01-01
      • 2014-04-08
      相关资源
      最近更新 更多