什么是常见的未定义/未指定对于C,你碰上的行为? [英] What are the common undefined/unspecified behavior for C that you run into?

查看:127
本文介绍了什么是常见的未定义/未指定对于C,你碰上的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C语言中不确定的行为的一个例子是参数评测给函数的顺序。它可能会从左至右或从右到左,你只是不知道。这将如何影响富(C ++,C)或富(++ C,C)被评估。

An example of unspecified behavior in the C language is the order of evaluation of arguments to a function. It might be left to right or right to left, you just don't know. This would affect how foo(c++, c) or foo(++c, c) gets evaluated.

还有什么其他未指定的行为是存在的,可以惊喜不知情的程序员?

What other unspecified behavior is there that can surprise the unaware programmer?

推荐答案

一个语言律师的问题。 Hmkay。

A language lawyer question. Hmkay.

我个人的TOP3:


  1. 违反了严格别名规则

  2. 违反了严格别名规则

  3. 违反了严格别名规则

  1. violating the strict aliasing rule
  2. violating the strict aliasing rule
  3. violating the strict aliasing rule

: - )

修改下面是确实错了两次小例子:

Edit Here is a little example that does it wrong twice:

(假设32位整数和little endian)

(assume 32 bit ints and little endian)

float funky_float_abs (float a)
{
  unsigned int temp = *(unsigned int *)&a;
  temp &= 0x7fffffff;
  return *(float *)&temp;
}

这code试图通过符号位位变换直接在一个浮动的重presentation得到一个浮动的绝对值。

That code tries to get the absolute value of a float by bit-twiddling with the sign bit directly in the representation of a float.

然而,通过浇注从一种类型到另一种创建的指针的对象的结果是无效的C的编译器可以假设指针的不同类型不指向相同的内存块。这是所有类型除无效*和char *指针真(登录内斯无所谓)。

However, the result of creating a pointer to an object by casting from one type to another is not valid C. The compiler may assume that pointers to different types don't point to the same chunk of memory. This is true for all kind of pointers except void* and char* (sign-ness does not matter).

在上面我做两次的情况。一旦获得一个int-别名浮动一个,一旦该值转换回浮动。

In the case above I do that twice. Once to get an int-alias for the float a, and once to convert the value back to float.

有三个有效的方式做同样的。

There are three valid ways to do the same.

剧组中使用char或空指针。这些总是别名任何东西,所以他们是安全的。

Use a char or void pointer during the cast. These always alias to anything, so they are safe.

float funky_float_abs (float a)
{
  float temp_float = a;
  // valid, because it's a char pointer. These are special.
  unsigned char * temp = (unsigned char *)&temp_float;
  temp[3] &= 0x7f;
  return temp_float;
}

使用的存储器复制。 memcpy的需要空指针,所以这将迫使走样也是如此。

Use memcopy. Memcpy takes void pointers, so it will force aliasing as well.

float funky_float_abs (float a)
{
  int i;
  float result;
  memcpy (&i, &a, sizeof (int));
  i &= 0x7fffffff;
  memcpy (&result, &i, sizeof (int));
  return result;
}

第三有效途径:利用工会。这是明确的不是未定义,因为C99:

float funky_float_abs (float a)
{
  union 
  {
     unsigned int i;
     float f;
  } cast_helper;

  cast_helper.f = a;
  cast_helper.i &= 0x7fffffff;
  return cast_helper.f;
}

这篇关于什么是常见的未定义/未指定对于C,你碰上的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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