C / C ++中原始指针和函数指针支持的操作是什么?

时间:2009-09-13 16:01:33

标签: c++ c pointers function-pointers

函数指针支持的所有操作与原始指针有什么不同? 是>> ,< ,< =,> =原始指针支持的运算符,如果有,有什么用?

5 个答案:

答案 0 :(得分:14)

对于函数和对象指针,它们都会编译但是它们的结果只保证对于同一个完整对象的子对象的地址是一致的(你可以比较一个类或数组的两个成员的地址),如果你将一个函数或对象与自身进行比较。

使用std::less<>std::greater<>等将适用于任何指针类型,并且将提供一致的结果,即使未指定相应内置运算符的结果:

void f() { }
void g() { }

int main() {
  int a, b;

  ///// not guaranteed to pass
  assert((&a < &b) == (&a < &b));

  ///// guaranteed to pass
  std::less<int*> lss1;
  assert(lss1(&a, &b) == lss1(&a, &b));
  // note: we don't know whether lss1(&a, &b) is true or false. 
  //       But it's either always true or always false. 

  ////// guaranteed to pass
  int c[2];
  assert((&c[0] < &c[1]) == (&c[0] < &c[1]));
  // in addition, the smaller index compares less:
  assert(&c[0] < &c[1]);

  ///// not guaranteed to pass
  assert((&f < &g) == (&f < &g));

  ///// guaranteed to pass
  assert((&g < &g) == (&g < &g));
  // in addition, a function compares not less against itself. 
  assert(!(&g < &g));

  ///// guaranteed to pass
  std::less<void(*)()> lss2;
  assert(lss2(&f, &g) == lss2(&f, &g));
  // note: same, we don't know whether lss2(&f, &g) is true or false.

  ///// guaranteed to pass
  struct test {
    int a;
  // no "access:" thing may be between these!
    int b;

    int c[1];
  // likewise here
    int d[1];

    test() {
      assert((&a < &b) == (&a < &b));
      assert((&c[0] < &d[0]) == (&c[0] < &d[0]));

      // in addition, the previous member compares less:
      assert((&a < &b) && (&c[0] < &d[0]));
    }
  } t;
}

这一切都应该编译(尽管编译器可以自由地警告它想要的任何代码片段。)


由于函数类型没有sizeof值,因此根据指针类型的sizeof定义的操作将不起作用,包括:

void(*p)() = ...;
// all won't work, since `sizeof (void())` won't work.
// GCC has an extension that treats it as 1 byte, though.
p++; p--; p + n; p - n; 

一元+适用于任何指针类型,只返回它的值,函数指针没有什么特别之处。

+ p; // works. the result is the address stored in p.

最后请注意,指向函数指针的指针不再是函数指针:

void (**pp)() = &p;
// all do work, because `sizeof (void(*)())` is defined.
pp++; pp--; pp + n; pp - n;

答案 1 :(得分:2)

如果指针指向相同的分配,则可以比较指针。例如,如果有两个指针指向同一个数组的元素,则可以在这些指针上使用不等式比较运算符。另一方面,如果你有两个指针指向不同的对象,那么比较是“未定义的”,但实际上,大多数编译器可能只是比较地址。

char *text[] = "hello";
const char *e_ptr = strchr(text, 'e');
const char *o_ptr = strchr(text, 'o');
if (e_ptr < o_ptr) { ... }  // this is legal
char *other_text[] = "goodbye";
const char *b_ptr = strchr(other_text, 'b');
if (b_ptr > o_ptr) { ... }  // not strictly legal

答案 2 :(得分:1)

#1 :可以调用函数指针。

#2 :指针支持关系运算符,因为您可以在指针算术中使用它们并将地址相互比较。实际示例:遍历数组

int data[5] = { 1, 2, 3, 4, 5 };

// Increment pointer until it reaches the end-address. 
for (int* i = data; i < data + 5; ++i) {
    std::cout << *i << endl; 
}

答案 3 :(得分:1)

指针支持运算符&lt;,&gt;,&lt; =,&gt; =,但如果要比较的两个指针是相同内存分配的一部分,则只能保证产生可靠的结果(比如指向两个指针)数组分配中的索引)。对于这些,它指示分配中的相对位置(即,如果&lt; b,则a指向阵列中的较低索引而不是b)。对于不在相同分配中的指针,结果是实现定义的(在某些体系结构中,可能违反严格的地图所需的兼容性。例如,可以仅使用&lt;或&gt;来比较64位指针低32位,如果单个分配不能超过32位指针允许的大小)。这些在函数指针的上下文中没有意义,因为它们不能解决连续的内存分配问题。

其他原始指针操作:==如果指针指向同一个对象,则返回true。 - 产生两个指针之间的字节数(我认为仅适用于相同的分配?)。 +不编译,因为它没有意义。

对于函数指针,可以通过*取消引用它们并调用它们。

对于指向成员函数的指针,有运算符 - &gt; *和。*

答案 4 :(得分:0)

指针表示为普通整数值。您可以使用指针执行所有操作,这也适用于所有其他数字类型。 + - * /&lt;&lt; &GT;&GT; ==!= ^&amp; | ! 〜%。我希望我什么也没忘记。

函数指针的不同之处在于可以使用()运算符调用它。