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

为什么通过指针算术对2D数组进行索引与使用[j]括号不一样,尽管规范规定应该这样做?

  •  0
  • Michele  · 技术社区  · 1 年前

    学习C,我偶然发现 this video 的第82页 C99 specification 出现(尽管它的日期是2007年,也许是修订版?)。

    其中指出,任何使用下标对数组进行索引的表达式,例如 E1[E2] ,一个在哪里 pointer to object type 另一种是类型 integer 完全相同的 (*((E1)+(E2))) ,因为适用于的转换规则 + 操作人员也就是说, 使用指针算术与使用方括号相同 .

    我的问题是: 为什么在我的代码中似乎不是这样? 我有一个2D char数组,并将其传递给一个函数,这意味着它将隐式转换为类型 pointer to char array 。将值分配给其成员的一个操作正常工作,而另一个操作(下面代码中注释掉的操作)则不正常,而是访问看似随机的内存地址。

    int main(void) {
        char frame[S_HEIGHT][S_WIDTH];
        frame_init(frame);
        // ...
    }
    
    // ...
    
    int frame_init(char (*frame)[S_WIDTH]){
        char ch = 'M';
        for(int i = 0; i < S_HEIGHT; i++){
            for(int j = 0; j < S_WIDTH; j++){
                *(*(frame + i) + j) = ch;    // this works! and so does (frame)[i][j] of course
             // *(frame + i)[j] = ch;        // this should be equivalent, but accesses wrong addresses
            }
        }
    }
    

    当然,如果您按照规范的规则手动进行分解,您会看到

    (frame)[i][j] == *(frame + i)[j] == *(*(frame + i) + j)

    但只有第一个和第三个起作用,第二个没有。尽管它应该起作用,因为 *(frame + i) 属于类型 pointer to char ,因此它是用于下标索引的有效表达式。它编译一切。

    这是怎么回事?只是因为我使用了C的更新版本吗?我试着查一下规格,但我只能找到 this ,我要为此付出代价。没有免费的阅读规范的方法吗?

    我真的很感激那些花时间阅读和分享知识的人。我爱C,我也爱你。致以最良好的祝愿,米歇尔。

    1 回复  |  直到 1 年前
        1
  •  3
  •   KamilCuk    1 年前
    *(frame + i)[j]
    

    方法

    *((frame + i)[j])
    

    即:

    frame[i + j][0]
    

    你的意思是:

    (*(frame + i))[j]
    

    这实际上相当于:

    frame[i][j]
    

    你可能感兴趣 https://en.cppreference.com/w/c/language/operator_precedence . * 具有优先级2,但是 [] 具有优先级1。

    没有免费的阅读规范的方法吗?

    不。如果cppreference中的标准的可摄入版本还不够,那么强大的链接 https://port70.net/~nsz/c/c11/n1570.html 出现,技术上包含 草稿 C标准的。