【问题标题】:C++ Pointers & ArraysC++ 指针和数组
【发布时间】:2010-11-27 17:17:18
【问题描述】:

以下是来自 C++ 过程的一些代码。原件可以在这里找到; https://code.ros.org/trac/opencv/browser/trunk/opencv/modules/imgproc/src/grabcut.cpp

我的观点是我是一个 C# 而不是 C++ 程序员,所以这个代码对我来说有点神秘,即使我通过一个代码转换器运行它并且它没有改变。

我的问题是:a)。 'coefs' 如何成为一个数组,以及 b)。 'c' 是如何填充的?

提供更多信息:'coefs' 开始时似乎不是一个数组,而 'c' 似乎神奇地获得了至少 8 个项目

    // 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;

    coefs = 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]);

【问题讨论】:

    标签: c++ arrays pointers opencv


    【解决方案1】:

    当你像这样声明一个数组时:

    int my_ints[10];
    

    my_ints 一个数组。但在 C++ 中,my_ints 也可以作为指向数组中第一项的指针来计算。所以代码如下:

    int* the_first_int = my_ints;
    

    ...是合法有效的,更不用说很常见了。您也可以像使用数组一样使用the_first_int,如下所示:

    int the_third_int = the_first_int[2];
    

    ...这使得在 C 样式数组和指针之间来回切换几乎无缝。

    在您的代码中,您声明了一个指向 float 的指针:

    float* coefs;
    

    (顺便说一句,这应该初始化为NULLL,但那是另一回事了),然后将其设置为某个值:

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

    我不知道model.ptr&lt;float&gt;(0) 做了什么,但它可能要么分配一个数组并返回一个指向该数组的指针,要么返回一个指向已经设置好的数组的指针。

    现在因为coefs 是指向float 的指针,所以您可以像使用数组一样使用它,您可以在循环中这样做:

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

    这就是它起作用的原因。

    【讨论】:

      【解决方案2】:

      coefs如何变成数组

      在 C 和 C++ 中,p[i] 只是 *(p + i) 的语法糖。当然,这个结构只有在p 恰好指向一个数组的元素并且p + i 没有超出该数组的边界时才有意义。否则,你会得到undefined behavior

      Kos 写道:请不要在每次出现问题时都说“未定义的行为”,除非你可以用标准来支持它

      好的,既然你要求它:

      当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有类型 的指针操作数。如果指针操作数指向数组对象的一个​​元素,并且数组是 足够大,结果指向与原始元素偏移的元素,使得 结果和原始数组元素的下标等于整数表达式。换句话说,如果 表达式P 指向数组对象的第i 个元素,表达式(P)+N(等效于N+(P)) 和(P)-N(其中N 的值为n)分别指向数组的第i + n 个和第i 个元素 对象,只要它们存在。此外,如果表达式P 指向数组对象的最后一个元素, 表达式 (P)+1 指向数组对象的最后一个元素,如果表达式 Q 指向 在数组对象的最后一个元素之后,表达式(Q)-1 指向数组的最后一个元素 目的。 如果指针操作数和结果都指向同一个数组对象的元素,或者一个过去 数组对象的最后一个元素,评估不应产生溢出; 否则,行为未定义。

      【讨论】:

      • 不真实...好吧,技术上正确,但不清楚:),因为p 实际上可能指向数组的任何元素。另外,请不要每次出现问题时都说“未定义的行为”,除非您可以用标准来支持它 - 仍然存在“未指定”和“实现定义”,后者基本上意味着存在情况(特定机器,架构,编译器...)这样的代码将是有效的。
      • @Kos:我明白你的观点,我并不反对,但这实际上是未定义的行为。
      • @Fred:说“是 p 恰好指向数组中的第一个元素,[否则它是 UB]”不太正确。正确的说法是“如果 *(p+1) 不指向数组中的元素,则得到 ub”是正确的。如果你要祈求UB之神,你应该是正确和准确的。
      • 你是说 - 假设我在 GCC 的 32 位机器上有 3 个 32 位浮点数的 POD 结构 - 如果我尝试通过指向第一个浮点数的指针来引用第二个浮点数增加 1 ,我可以期待恶魔从我的鼻子里飞出来,或者 - 嗯 - 比人们指责我的坏作风更糟糕的事情吗?虽然我无法确认,但我相信这种情况下的行为是可以预测的;这就是我对“实现定义”的理解(类似于工会、reinterpret_casts 等的情况)。如果我在这里错了,请用一些来源纠正我。
      • @Kos:事物可以由实现定义,而不是实现定义。 C++ 标准将很多东西保留为 UB(这意味着它不是实现定义的),但是没有规则阻止特定实现定义它在该特定实现上的行为方式(所以它是可以预测的,但 C++ 标准并不要求它是这样,因此它仍然是 UB)。如果标准说它是由实现定义的,那么事情只有在 C++ 用语中是实现定义的。这有意义吗?
      【解决方案3】:

      在 C 和 C++ 中,指针和数组是等价的。您可以将它们视为指针或数组,这取决于您。指向单个变量的指针可以被认为是一个包含 1 个元素的数组。

      【讨论】:

      • 不,指针和数组不等价。在某些情况下,数组的行为很像指针(数组到指针衰减),但它不是指针。例如,sizeof(some_array) 产生整个数组的大小,而sizeof(some_pointer) 产生指针的大小。
      • float*float[1] 是存储不同内容的不同类型。
      • @FredOverflow:它们是等价的,但它们并不相同。 int 和 short 是等价的,但不一样。
      • intshort 到底是如何等效的?
      • “数组对象可以隐式转换为指向数组内部类型的指针”,用 C++ 术语表示。我不记得 C++ 有 “等效” 的概念。
      【解决方案4】:

      从您的代码看来,model 是实际包含数组的数据结构。

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

      这里,coefs 不会“变成”数组,而是指向model 中的现有数组,之后它可以像真正的数组一样使用。其他变量meancovc 也是如此——它们都被分配了一个指向数组中特定位置的指针。例如:

      mean = coefs + componentsCount;
      

      使mean 指向coefs“数组”的第6 个(从componentsCount = 5 开始)元素。在此之后,mean 可以被视为从model 的第 6 个元素开始的数组。

      【讨论】:

        【解决方案5】:

        float *c = cov + 9*ci;

        c 是指向 cov 指向的任何位置的指针,加上浮点大小的 9 倍(假设标准 IEEE-754 float 为 4 个字节)。这是指针算法。

        我不确定 coefs 指向什么,但我认为它是在 model.ptr&lt;float&gt;(0); 语句中的某个位置分配的。否则,它是一个无效的指针(可能为 NULL)。

        在 C 和 C++ 中,存在指针和数组之间的区别的细分。考虑以下代码:

        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
        

        【讨论】:

        • 如果 c 是指向 cov 指向的任何位置的指针加上浮点大小的 9 倍(或者您的意思是 int?),我将如何编写想要将 ci 的实际值乘以的代码9 而不是它的字节大小?
        猜你喜欢
        • 1970-01-01
        • 2023-03-11
        • 2015-03-27
        • 1970-01-01
        • 1970-01-01
        • 2018-09-26
        • 2023-03-17
        相关资源
        最近更新 更多