【问题标题】:Why does this C code work?为什么这个 C 代码有效?
【发布时间】:2011-08-04 02:01:59
【问题描述】:

编辑:非常感谢您的回复。我现在明白了!

我正在尝试了解更多关于 C 指针的信息。修补一下,我在质疑我正在使用的两个动作之间的区别。

此代码乍一看似乎可以工作,但我不确定有什么区别,以及这两种方法中的任何一种是否在某些方面是错误的。

我想知道这两段代码有什么区别,什么时候应该传递地址,什么时候传递指向数组的指针?

有错吗?如果是这样,正确的方法是什么?

有一个简单的结构网格,很像 struct grid { int val; }(用于演示目的)

第一段代码。将指针的地址传递给数组。

    void set (mygrid *grid, int foo){
        grid->bar = foo; //should this be '*grid->bar?' But this seems to work properly.
    }

    void main(){
        int i;
        int* array;
        int max = 24;

        array = malloc(sizeof(grid) * max);

        for(i = 0; i < max; i++){
            set(&array[i], 0);
        }
    }

第二段代码。我不完全确定为什么会这样,但是编译器没有输出任何警告。 我应该像这样将指针传递给数组的开头?

    void set(mygrid *grid, int foo){
        int i; int max = 24; //so this example code compiles :P

        for(i = 0; i < max; i++){
            grid[i].bar = foo;
        }
    }

    void main(){
        int* array;
        int max = 24;

        array = malloc(sizeof(grid) * max);
        set(array, 0); //Why not &array?
    }

【问题讨论】:

  • 当心那个 malloc 的参数。它应该是malloc(sizeof(mygrid)*max)。我知道它有效,因为mygrid 正好是一整型,但它“闻起来”而且感觉很糟糕 :)
  • 哎呀!视力好。一开始我想做一个整数数组,但后来我想起了具体的例子使用了一个结构数组。以防万一它有所作为。然后我忘了编辑那个 malloc :P

标签: c pointers


【解决方案1】:

传递一个数组会衰减成一个指向数组第一个成员的指针,就像&amp;array[0]一样。

【讨论】:

    【解决方案2】:

    在您的第二个示例中,array 只是一个指针,malloc 的返回值只是您获得的内存块的起始地址。

    它不必用于数组;它可以用于存储任意sizeof(int) * max 字节的数据。数组(在 C 中)实际上只是一种很好的思考和处理被分成相等大小部分的固态内存块的方式。

    其次,您应该了解my_array[i] 的工作原理。它所做的只是获取数组数据块开始的地址(这是my_array 的实际值),然后查看存储在从那里的特定偏移量处的值。具体来说,如果my_arrayWhatEver 的(组成)类型,那么它将访问从my_array + i*sizeof(WhatEver)my_array + (i+1)*sizeof(WhatEver) 的数据。

    在相关说明中(因为您正在学习 C),强烈建议在对它进行任何操作之前检查 malloc 的返回不是 NULL

    我不是 C 大师,但我也在努力提高我的理解,所以如果这不正确,请发表评论或编辑我的答案,以便我从错误中吸取教训 :)

    【讨论】:

    • 啊。我对它的工作原理有一个模糊的理解,但这很清楚。我主要对语法和错误语法可能导致的错误感到困惑。
    • 对 NULL 指针也有很好的建议。虽然,考虑到我正在编写一个没有关键功能的小型应用程序,但内存不足的可能性应该很小。除非它是关键部分,否则真的值得检查它们吗?
    • 我一直听说,经常检查是很重要的,因为你无法预测幕后发生的事情来获得记忆(这应该是一个好习惯)。 Wikipedia seems to agree。另一方面,answers to this question 似乎表明它不是那么明确,因为它可能不是直接有用的,但它不会受到伤害。我想如果你想快速失败或养成好习惯,那就检查一下,否则考虑平台。
    • 好吧,我碰巧同意那里的许多海报。如果我们达到了系统无法为小整数数组保留空间的程度,则系统已经不稳定或负载不足,甚至失败。绝对不是使用我的应用程序的环境。由于我的应用程序只是一个按需工具,因此我最好在出现这种情况时强制退出。没有必要让它对抗内存不足的情况。我将在 malloc 函数中添加检查,并在不应该找到 NULL 时退出。
    【解决方案3】:

    在你的第一段代码中

    grid-&gt;bar(*grid).bar 相同

    。并且使用数组的名称是指它的基地址。所以写array 等价于&amp;array[0]

    &array[i] is equivalent to array+i
    array[i] is equivalent to *(array +i)
    

    在你的第二段代码中,我不明白为什么没有错误,因为在你的函数集中你没有声明 max 并且我也没有看到全局 max 变量。 同样在您使用的第二段代码中 set(array,0) 因为数组已经是一个整数指针(参见声明 int * array)。据我了解,mygrid 不是结构,而是第二个示例中的结构数组

    【讨论】:

    • 哎呀,我的错,我把它写成伪代码,我的重点是指针的使用,对不起!所以因为array指向的是int,所以传递指针和传递起始地址是一样的,对吧?
    • @roger_rales yes 传递指针和传递int的起始地址是一样的
    【解决方案4】:

    在 C 中,数组与指针几乎相同。对我来说,这并不奇怪,因为它是我学习的较早的编程语言之一,但如果您来自高级语言,其中数组是不同类型的对象,那么它可能会让人觉得很奇怪。

    【讨论】:

    • 我问是因为在第一个例子中,我读到我必须做类似 a(int* a){ a = 3; }。然而,试图让我上面的例子 *grid->bar = foo 而不是没有 * 符号,它会导致这个错误:invalid type argument of unary ‘’ (have ‘int’)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    相关资源
    最近更新 更多