【问题标题】:Exception Thrown: access violation抛出异常:访问冲突
【发布时间】:2020-02-23 14:02:11
【问题描述】:

此函数反转指针数组并将其返回给 main。主要问题是代码返回一个 抛出异常:读取访问冲突。 fptr 为 0xCCCCCCCC。

错误的来源是什么?

int* mirror(int* p[], int n) {
    int* ptr,* fptr;
    int swap;
    ptr = p[0];
    fptr = p[n-1];
    while (fptr > ptr) {
        swap = *ptr;
        *ptr = *fptr;
        *fptr = swap;
        ptr++;
        fptr--;
    }
    return *p;
}

【问题讨论】:

标签: c++ arrays algorithm pointers reverse


【解决方案1】:

这就是问题所在:

while (fptr > ptr) { ... }

ptr 是第一个元素(第一个指针),fptr 是最后一个元素(最后一个指针),当第一个元素小于最后一个元素时,您正在遍历数组,但这暗示数组中的元素是按地址顺序插入的,我认为不是..

您应该使用维度 (n) 来执行此操作:

int** mirror(int* p[], int n) { // return a pointer to integers pointer, not a pointer to integer
    for(int i = 0; i < n/2 ; i++){ // go through the first half of the array
       int* tmp = p[i];  // and those three lines swap the current and the n - current elements
       p[i] = p[n-i-1];
       p[n] = tmp;
    }
    return p;
}

【讨论】:

    【解决方案2】:

    对于初学者来说,函数的返回类型int * 没有意义。

    int* mirror(int* p[], int n) {
    

    最好将函数声明为返回类型为void

    如果您有一个int * 类型的指针数组,那么指向其元素的指针的类型为int **

    此外,用户可以将 0 作为第二个参数传递。你应该检查一下这个案例。

    异常的原因可能是数组包含指向原始数组之外的无效指针。

    此外,如果指针数组的形成方式不需要例如第一个指针指向原始数组的第一个元素,那么您的函数将无法工作。

    函数可以这样定义

    void mirror( int * p[], size_t n ) 
    {
        if ( n != 0 )
        {
            for ( int **first = p, **last = p + n; first < --last; ++first )
            {
                int tmp = **first;
                **first = **last;
                **last = tmp;
            }
        }
    }
    

    这是一个演示程序

    #include <iostream>
    
    void mirror( int * p[], size_t n ) 
    {
        if ( n != 0 )
        {
            for ( int **first = p, **last = p + n; first < --last; ++first )
            {
                int tmp = **first;
                **first = **last;
                **last = tmp;
            }
        }
    }
    
    int main() 
    {
        const size_t N = 5;
        int a[N] = { 10, 30, 30, 40, 50 };
        int * b[N] = { a, a + 1, a + 2, a + 3, a + 4 };
    
        for ( const auto &item : a )
        {
            std::cout << item << ' ';
        }
        std::cout << '\n';
    
        mirror( b, N );
    
        for ( const auto &item : a )
        {
            std::cout << item << ' ';
        }
        std::cout << '\n';
    
        return 0;
    }
    

    程序输出是

    10 30 30 40 50 
    50 40 30 30 10
    

    请注意,您可以使用标准函数std::swap,而不是“手动”交换元素。

    【讨论】:

      【解决方案3】:

      问题是您使用了错误的类型。正确的版本是:

          int **ptr, **fptr;
          int* swap;
          ptr = &p[0];
          fptr = &p[n - 1];
      

      通过这些更改,您的函数将按预期工作,尽管它返回的内容无法用于大多数用途。要么返回p (int**) 要么返回void

      void mirror(int* p[], int n) {
          if(n > 0) {                  // check this or you risk undefined behavior
              int** ptr = &p[0];
              int** fptr = &p[n-1];
              int* swap;
              while(ptr < fptr) {
                  swap = *ptr;
                  *ptr = *fptr;
                  *fptr = swap;
                  ptr++;
                  fptr--;
              }
          }
      }
      
      

      请注意,已经有一个用于交换两个值的标准实用程序,称为 std::swap

      void mirror(int* p[], int n) {
          if(n > 0) {
              for(int **ptr = &p[0], **fptr = &p[n - 1]; ptr < fptr; ++ptr, --fptr) {
                  std::swap(*ptr, *fptr);
              }
          }
      }
      

      最后一点,还有一个用于反转容器中的值的标准实用程序,称为 std::reverse,它的作用与您的 mirror 函数一样。

      代替

      mirror(arr, std::size(arr));
      

      std::reverse(std::begin(arr), std::end(arr));
      

      【讨论】:

        【解决方案4】:

        尝试按如下方式导航您的数组:

        void mirror(int* p, int n){
          int* ptr,* fptr;
          int swap;
          ptr = p;
          fptr = p+n-1;
          while (fptr != ptr) {
            swap = *ptr;
            *ptr = *fptr;
            *fptr = swap;
            ptr++;
            fptr--;
          }
        }
        

        【讨论】:

        • 不,如果一个元素被多次插入,这段代码就不起作用了
        • 如果他真的在操作一个指针数组,我不明白他为什么要尝试递增它们,因为它们肯定不连续。
        猜你喜欢
        • 2021-07-12
        • 1970-01-01
        • 2022-01-08
        • 1970-01-01
        • 1970-01-01
        • 2018-05-19
        • 1970-01-01
        • 2021-07-02
        • 2021-06-04
        相关资源
        最近更新 更多