我已经code in Code Reveiw按预期“工作”,但可能已经UB
.
代码有一个大小相同的char数组,称为GP2_format[]。为了检测指针format是否与其中一个元素GP2_format[][0]的地址具有相同的值,下面的代码简单地测试指针是否>=是最小的元素而<=是最大的元素。由于元素的大小为1,不需要进一步检查。

const char GP2_format[GP2_format_N + 1][1];
const char *format = ...;

if (format >= GP2_format[0] && format <= GP2_format[GP2_format_N]) Inside()
else Outside();

C11§6.5.8/5关系运算符< > <= >=似乎将此定义为比较数组外部指针时可怕的未定义行为。
比较两个指针时,结果取决于所指向对象的地址空间中的相对位置。如果指向对象类型的两个指针都指向
相同的对象。。。对于同一个数组对象,它们比较相等。…(相同的对象确定)。。。。(同一工会确定)。。。。(相同的数组确定)。。。在所有其他情况下,行为都是未定义的。
Q1代码指针是否在UB中比较?
如果是,那么什么是定义良好的备选方案,搜索O(1)到可疑的GP2_get_type()
较慢的解决方案
代码可以对每个GP2_get_type()依次测试format,或者将值转换为GP2_format[],排序一次并执行O(ln2(n))搜索。
类似
...if a pointer is part of a set,但这个“集合”不是随机的,它是一个数组。
intptr_t approach-也许是UB。
#include <stdio.h>

typedef enum {
  GP2_set_precision,
  GP2_set_w,
  GP2_setios_flags_,
  GP2_string_,
  GP2_unknown_,
  GP2_format_N
} GP2_type;

const char GP2_format[GP2_format_N + 1][1];

static int GP2_get_type(const char *format) {
  // candidate UB with pointer compare
  if (format >= GP2_format[0] && format <= GP2_format[GP2_format_N]) {
    return (int) (format - GP2_format[0]);
  }
  return GP2_format_N;
}

int main(void) {
  printf("%d\n", GP2_get_type(GP2_format[1]));
  printf("%d\n", GP2_get_type("Hello World"));  // potential UB
  return 0;
}

输出(如预期,但可能是UB)
1
5

最佳答案

如果您想遵守C标准,您可以选择:
对目标范围内的每个指针执行单独的==!=测试
如果是一个非常大的集合,可以使用哈希表或搜索树之类的东西来加速这个过程
重新设计代码以不需要此检查。
“可能有效”的方法是将所有值强制转换为uintptr_t,然后进行关系比较。如果系统有一个具有绝对顺序的内存模型,那么它应该定义uintptr_t并保留该顺序;如果它没有这样的模型,那么关系比较的思想无论如何都不会起作用。

10-05 21:02
查看更多