代码之家  ›  专栏  ›  技术社区  ›  yesraaj

C/C++中的原始指针和函数指针支持哪些操作?

  •  6
  • yesraaj  · 技术社区  · 16 年前

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

    5 回复  |  直到 16 年前
        1
  •  14
  •   Johannes Schaub - litb    16 年前

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

    使用 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 值,根据定义的操作 西泽 指针类型的将不起作用,其中包括:

    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;
    
        2
  •  2
  •   Adrian McCarthy    16 年前

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

    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
    
        3
  •  1
  •   yesraaj    16 年前

    #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; 
    }
    
        4
  •  1
  •   Todd Gardner    16 年前

    指针支持运算符<、>、<=、>,但只有当正在比较的两个指针是同一内存分配的一部分时(如将两个指针与数组分配中的索引进行比较),才能保证产生可靠的结果。对于这些,它指示分配中的相对位置(即,如果a<b,则a指向数组中比b低的索引)。对于不在同一分配中的指针,结果是实现定义的(在某些体系结构中,可能违反严格的低于映射所需的兼容性)。例如,如果单个分配不能超过32位指针所允许的大小,则可以将64位指针与仅使用较低32位的<或>进行比较。在函数指针的上下文中,这些实际上没有意义,因为它们不处理连续内存分配。

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

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

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

        5
  •  0
  •   codymanix    16 年前

    指针表示为普通整数值。您可以使用指针执行所有操作,这在所有其他数值类型上也是允许的。+-*/<<>==^&!~%。希望我什么都没忘记。

    函数指针只有在使用()运算符调用时才不同。