C语言中未指定行为的一个示例是函数的参数求值顺序.可能是从左到右,也可能是从右到左,只是你不知道.这将影响判断foo(c++, c)foo(++c, c)的方式.

还有什么其他未指明的行为会让不知情的程序员感到惊讶?

推荐答案

语言律师问题.嗯,凯.

我个人的top3:

  1. 违反了严格的别名规则

  2. 违反了严格的别名规则

  3. 违反了严格的别名规则

    :-)

Edit这里有一个小例子,它做错了两次:

(假设32位整数和小尾数)

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

该代码试图通过直接在浮点表示中旋转符号位,逐位获得浮点的绝对值.

然而,通过从一种类型转换到另一种类型来创建指向对象的指针的结果是无效的C.编译器可能会假设指向不同类型的指针不指向同一内存块.这适用于除void*和char*之外的所有类型的指针(符号性并不重要).

在上面的例子中,我做了两次.一次获取浮点a的int别名,一次将值转换回浮点.

有三种有效的方法可以做到这一点.

在转换过程中使用char或void指针.这些都是任何东西的别名,所以它们是安全的.

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;
}

使用memcopy.Memcpy使用空指针,因此它也会强制使用别名.

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

第三种有效方法:使用联合体.这显然是not undefined since 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++相关问答推荐

VS代码输入需要多次

如何在C中通过转换为char * 来访问float的字节表示?

球体—立方体重叠:无、部分或全部?

什么C代码将确定打开的套接字正在使用的网络适配器?

当main函数调用被重构时,C函数给出错误的结果

将 struct 变量赋给自身(通过指针取消引用)是否定义了行为?

为什么GDB/MI进程的FIFO循环中有read()阻塞

理解C版宏(看起来像未声明的变量?)

获取每个循环迭代结束时的当前时间

如何在C中使数组变量的值为常量?

从C文件中删除注释

从BIOS(8086)中读取刻度需要多少?

为什么我的旧式&q;函数在传递浮点数时会打印2?

带有数组指针的 struct 在print_stack()函数中打印随机数

从系统派生线程调用CRT

使用 _Atomic float 时,MSVC 编译的代码会命中调试断言

如何为avr atmega32微控制器构建C代码,通过光电二极管捕获光强度并通过串行通信传输数据

如何向 execl 创建的后台程序提供输入?

clion.我无法理解 Clion 中发生的 scanf 错误

比 * 更快的乘法