Thread: Help with pointers

  1. #1
    Caution: Wet Floor
    Join Date
    May 2006
    Posts
    55

    Help with pointers

    Why does the address &ra[0] keep changing?

    Code:
    void overlappingPermutations(Distribution& D, int* ra) {
    
      // overlappingPermutations
      //
      //      Take five consecutively-generated RNs at a time and
      //      determine their order. There are 5P5 = 120 different
      //      orderings.
      //
      //
      // Example:
      //
      //
      //
      //
      // Expected distribution: Flat
      //
      // Complexity: O(N)
     vector<int> pattern(120);
      int is[5] = {0};
    
      while(ra) {
        int i = 0;
        while(i < 5){
          is[i++] = *ra++;
        }
        if(ra - &ra[0] == 0) cout << "bang!\n"; // Always written!
        rankPermutations(pattern, is, 5);
        }
    
    // Rest of implementation comes later
    
    }
    
    // ... 
    
    int main(void) {
    
      Distribution* D = new Distribution[12];
      bool running = true;
      int* ra;
    
    
      try {
    
        ra = new int[10000000];
    
      } catch (bad_alloc) { 
    
        cout << "Memory allocation failed\n";
        return 127;
    
      }
    
      long int count = 0;
    
      seedRNG();
    
      while(running) {
    
    
        ra[count++] = rand();
    
        if(count % 1000000 == 0) cout << count << " values so far.\n";
        if(count == 10000000) running = false;
      }
    
      diehard(ra); // Diehard just calls functions like `overlappingPermutations', 
                          // which all have the same prototype.
    }
    Thanks.

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    ra and &ra[0] should always be equal. ra is not a magic array whose start won't change and a magic pointer that you can make point elsewhere at the same time.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I suggest that you post the smallest and simplest compilable program that demonstrates the problem.

    I noticed a few problems:

    1. You use new[] in main(), but it lacks a matching delete[].

    2. You rather randomly return 127 from main(). You should return 0, EXIT_SUCCESS or perhaps in this case, EXIT_FAILURE. The latter two are found in <cstddef>.

    3. You might want to indent by 4 spaces instead. 2 spaces (or at one point, it was one space) can be rather... insignificant.

    Also, I noticed that:
    Code:
    while(running) {
    
    
      ra[count++] = rand();
    
      if(count &#37; 1000000 == 0) cout << count << " values so far.\n";
      if(count == 10000000) running = false;
    }
    Is far more simply and directly expressed as:
    Code:
    while (count < 10000000) {
        ra[count++] = rand();
    
        if(count % 1000000 == 0) cout << count << " values so far.\n";
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Caution: Wet Floor
    Join Date
    May 2006
    Posts
    55
    ra and &ra[0] should always be equal. ra is not a magic array whose start won't change and a magic pointer that you can make point elsewhere at the same time.
    But doesn't ra++ move the pointer up by sizeof(int)? I thought &ra[0] points to the zeroth element (always), and ra is the current position. Does ra++ move &ra[0] up too? Why?

  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    ra[0] points to the zeroth element of the array starting at ra.
    ra++ does increment the pointer - and ra[0] points the zero'th element starting at ra.

    ra is just a pointer sized variable. The compiler does not generate code to keep track of ra's initial value - as the "fixed zero'th element".

    gg

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    ra is a pointer, which (in this context) should be equivalent to &ra[0], no matter what you've done to ra previously. Which means that ra-&ra[0] should always compare equal to zero.

    If you do this;
    Code:
        int *rb = new int[5];
        int *ra = rb;
        ++ra;
    then ra will be equal to rb+1. Manipulating ra[0] (or, equivalently, *ra) will therefore manipulate rb[1]. So &ra[0] == &rb[1] will always compare true.

  7. #7
    Caution: Wet Floor
    Join Date
    May 2006
    Posts
    55
    Thanks for your help!

    I traced the problem to the way values are assigned to an array in a structure:

    Code:
    #include <iostream>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <ctime>
    #include <cstddef>
    
    using namespace std;
    
    typedef struct {
    
      string d;   // Statistical distribution
    
      int n;      // Number of entries
    
      double* dx; // x-values
      double* dy; // y-values
      double* dz; // z-values
    
    } Distribution;
    
    void seedRNG() {
    
      srand(static_cast<unsigned>(time(0)));
    
    }
    
    void fill(Distribution& D, double x) {
    
      *(D.dx + D.n) = x; // crash!!!!!
    
      D.n++;
    }
    
    double l2Norm(double p1, double p2) {
    
      return p1 - p2 >= 0 ? p1 - p2 : p2 - p1;
    
    }
    
    void poissonL2Norm(Distribution& D, int* ra) {
    
      // poissonL2Norm
      //
      //      Throw beans on a closed interval of width RAND_MAX+1
      //      and measure the distance between adjacent beans:
      //
      // Example:
      //           0                       RAND_MAX
      //           [--B---BB--- ... ---B--B]
      //              |< >||<         >|<>|
      //
      //    Width:    3   1  RAND_MAX-7 2
      //
      // Expected distribution: Poisson
      //
      // Efficiency: O(n)
    
      //    while(*(1+ra++));
      fill(D, l2Norm(*ra, *(ra+1)) );
    
    }
    
    void diehard(int* ra, Distribution* D  =0) {
    
      poissonL2Norm(D[0], ra);
      
    
    }
    
    int main(void) { // Thanks, laserlight
    
      Distribution* D = new Distribution[12];
      int* ra;
    
    
      try {
        ra = new int[10000000];
    
      } catch (bad_alloc) { // Handling not mandatory, but safe
        cout << "Memory exhausted\n";
        return EXIT_FAILURE;
      }
    
      long int count = 0;
    
      seedRNG();
    
      cout << "start: " << ra << '\n';
      while(count < 10000000) {
    
        ra[count++] = rand();
        if(count % 1000000 == 0) cout << count << " values so far.\n";
      }
    
    
      diehard(ra, D);
    
      delete[] ra;
      delete[] D;
    
    }
    This program goes up in flames at runtime because of the way I "fill" the distribution. I just want to add one number at a time to D.dx, but I'm having trouble doing this. Any ideas? This is my first 1000-liner in C++, and it looks like I'll be 100 by the time it works completely : (

    Also: Emacs' syntax highlighter for C++ is only indenting two deep. How do you tell it to go four deep? I'm so, so lost here : (

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    You are incorrectly assuming, when you create a pointer, that it points at something valid.

    For example;
    Code:
    int main()
    {
        int *p;
        *(p + 4) = 5;   // undefined behaviour here
    }
    yields undefined behaviour, for which a common (but not guaranteed) symptom is a program crash, as p is uninitialised. It does NOT point at the first element of any array.

    Furthermore, initialising to NULL (or zero), also yield undefined behaviour.
    Code:
    #include <stdlib.h>
    int main()
    {
        int *p = NULL;
        *(p + 4) = 5;   // undefined behaviour
    }
    The bottom line is that YOU need to ensure the pointer points at something valid.
    Code:
    int main()
    {
        int *p = new int[5];
        *(p + 4) = 5;    //  OK, as p points at an array of 5 elements
        delete [] p;
        *(p + 4) = 10;   // undefined behaviour here, as the memory pointed at by p has been released by the program
    }

  9. #9
    Caution: Wet Floor
    Join Date
    May 2006
    Posts
    55
    It does NOT point at the first element of any array.
    ...
    The bottom line is that YOU need to ensure the pointer points at something valid.
    Thanks!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Variable pointers and function pointers
    By Luciferek in forum C++ Programming
    Replies: 11
    Last Post: 08-02-2008, 02:04 AM
  2. Using pointers to pointers
    By steve1_rm in forum C Programming
    Replies: 18
    Last Post: 05-29-2008, 05:59 AM
  3. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  4. Staticly Bound Member Function Pointers
    By Polymorphic OOP in forum C++ Programming
    Replies: 29
    Last Post: 11-28-2002, 01:18 PM