开发者

C++ Pointers & Arrays

Below is some code from a C++ procedure. The original can be found here; https://code.ros.org/trac/opencv/browser/trunk/opencv/modules/imgproc/src/grabcut.cpp

My perspective is that I am a C# rather than C++ programmer so this code is a bit of a mystery to me even though I ran it through a code converter and it came out unchanged.

My questions are: a). How does 'coefs' become an array, and b). how does 'c' get populated?

To give a bit more information: 'coefs' does not seem to start out as an array and 'c' somehow seems to magically get at least 8 items

    // fields in class called MAT:
    // a distance between successive rows in bytes; includes the gap if any 
    size_t step;
    // pointer to the data
    uchar* data;

    // where ptr comes from:
    template<typename _Tp> _Tp* ptr(int y=0);
    template<typename _Tp> inline _Tp* Mat::ptr(int y)
    {
        CV_DbgAssert( (unsigned)y < (unsigned)rows );
        return (_Tp*)(data + step*y);
    }    
    .....

    // original question code:
    static const int componentsCount = 5;
    Mat model;
    float* coefs;
    float* mean;
    float* cov;

    co开发者_StackOverflowefs = model.ptr<float>(0);
    mean = coefs + componentsCount;
    cov = mean + 3*componentsCount;

    for( int ci = 0; ci < componentsCount; ci++ )
        if( coefs[ci] > 0 )
            calcInverseCovAndDeterm( ci );

    void GMM::calcInverseCovAndDeterm( int ci )
    {
        if( coefs[ci] > 0 )
        {
            float *c = cov + 9*ci;
            float dtrm =
                covDeterms[ci] = c[0]*(c[4]*c[8]-c[5]*c[7]) - c[1]*(c[3]*c[8]-c[5]*c[6]) + c[2]*(c[3]*c[7]-c[4]*c[6]);


When you declare an array like this:

int my_ints[10];

my_ints is an array. But in C++ my_ints can also be evaluated as a pointer to the first item in the array. So code like this:

int* the_first_int = my_ints;

...is legal and valid, not to mention very common. You can also use the_first_int as if it were also an array, like this:

int the_third_int = the_first_int[2];

...which makes it practically seamless to go between C-style arrays and pointers and back again.

In your code you declare a pointer to a float:

float* coefs;

(by the way, this should be initialized to NULLL, but that's another story), and then you set it to some value:

coefs = model.ptr<float>(0);

I don't know what model.ptr<float>(0) does, but it probably either allocates an array and returns a pointer to that, or returns a pointer to an array that was already set up.

Now because the coefs is a pointer to float, you can use it like it were an array, which you do in the loop:

for( int ci = 0; ci < componentsCount; ci++ )
    if( coefs[ci] > 0 )

That's why this works.


How does coefs become an array

In C and C++, p[i] is just syntactic sugar for *(p + i). Of course, this construct is only meaningful if p happens to point to an element of an array and p + i does not march off the bounds of that array. Otherwise, you get undefined behavior.

Kos wrote: please don't just say "undefined behaviour" every time something's wrong unless you can back it up with a standard

Okay, since you were asking for it:

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i + n-th and i - n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.


In C and C++ pointers and arrays are equivalent. You can treat them as pointer or array ,tht up to you. A pointer to single variable can be considered an array of 1 element.


It appears from your code that model is the data structure that actually contains an array.

coefs = model.ptr<float>(0);

Here, coefs doesn't "become" an array, but it points to the existing array in model, after which it can be used just like a real array. The same happens with the other variables mean, cov and c -- they are all assigned a pointer to a specific location within the array. For example:

mean = coefs + componentsCount;

makes mean point to the 6th (since componentsCount = 5) element of the coefs "array". After this, mean can be viewed as an array that begins from the 6th element of model.


float *c = cov + 9*ci;

c is a pointer to wherever cov points to plus 9 times the size of a float (4 bytes assuming standard IEEE-754 float). This is pointer arithmetic.

I'm unsure what coefs points to, but I assume it gets assigned somewhere in the model.ptr<float>(0); statement. Otherwise, it's an invalid pointer (probably NULL).

In C and C++, there exists a breakdown of the distinction between pointers and arrays. Consider the following code:

int A[5];
int y = *A;  // The first occurrence of A is also the dereferenced value of *A
int z = A[0]; // The first occurrence of A
int *w = A;  // pointer to the beginning of A
if (*w == y) {} // TRUE, dereferenced int value == int value
if (w == A) {} // TRUE, address == address
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜