【问题标题】:Dynamic Array Creation in C using pointers with Answer使用带有答案的指针在 C 中创建动态数组
【发布时间】:2016-11-23 10:50:04
【问题描述】:

这是用 C 创建动态数组的示例代码。我正在寻找简单的动态数组,但找不到简单的。实现了我自己的版本。欢迎提出任何建议。

#include <stdio.h>
#include <stdlib.h>

const int MAX_LENGTH_INC=5;

int main(void)
{

    int *ptr,i;
    int maximum_array_size = 1;
    int index=0;
    ptr = malloc(MAX_LENGTH_INC * sizeof(int));

    printf("Address of previously allocated memory: ");
    for(i = 0; i < 8; i++) // incrementing upto maximum of size 8
    {
       //printf("\n Pointer is:%u\t",ptr + i);
       //printf("\nindex is: %d",index);
       ptr[index] = i*2; 
       //printf("\nValue :%d\t",ptr[index]);

       index++;
       if(index == maximum_array_size)
       {
            //printf("\n Array reached its limit");
            ptr= realloc(ptr,sizeof(int)*MAX_LENGTH_INC);
            maximum_array_size = maximum_array_size + MAX_LENGTH_INC;
       }
    }
    for(i=0;i<index;i++)
        printf("\n Array Value is %d ",ptr[i]);
    free(ptr);

  return 0;

}

【问题讨论】:

标签: c arrays dynamic


【解决方案1】:

好的,这里有一些问题,让我一步一步地挖掘它们。

#include <stdio.h>
#include <stdlib.h>

const int MAX_LENGTH_INC=1;

虽然 C 中有一个 const 关键字,但我建议不要使用它来定义这样的常量。相反,只需像这样使用#define:

#define MAX_LENGTH_INC 1

不过,const int MAX_LENGTH_INC = 1; 没有错,喜欢的话可以留着。

int main(void)
{

正确。替代方案:int main(int argc, char * argv[]) {。这样,程序的调用者可以传递命令行参数。在他的程序中,显然你不需要它,所以void就可以了。

    int *ptr,i;
    int maximum_array_size = 1;

所以,请记住:这是您的 当前 数组大小。我猜你实际上想从MAX_LENGTH_INC 开始,所以最好写:

    int maximum_array_size = MAX_LENGTH_INC;

这样,如果您增加MAX_LENGTH_INC,您也会增加第一次分配的大小,而不仅仅是后续分配的大小。

    int index=0;
    ptr = (int*) malloc(MAX_LENGTH_INC * sizeof(int));

已经注意到一条评论:不要转换 malloc 的返回值。另外:你应该在这里使用变量maximum_array_size

    ptr = malloc(maximum_array_size * sizeof(int));

使用sizeof(int) 是C 中很常见的风格,在这里需要注意:sizeof 不是函数而是运算符。所以sizeof int 也是有效的。 /编辑:见评论

    printf("Address of previously allocated memory: ");
    for(i = 0; i < 8; ++i)
    {
        //printf("\n Pointer is:%u\t",ptr + i);
        //printf("\nindex is: %d",index);
        ptr[index] = i*2; 
        //printf("\nValue :%d\t",ptr[index]);

        index++;
        if(index == maximum_array_size)
        {
             //printf("\n Array reached its limit");

你的逻辑问题来了:

             ptr=(int *)realloc(ptr,sizeof(int)*MAX_LENGTH_INC);
             maximum_array_size = maximum_array_size + MAX_LENGTH_INC;

你总是用realloc 数组来保存MAX_LENGTH_INC 元素。那时你记得,它应该已经长大,但你实际上并没有长大。所以,首先,交换两行,然后像上面的 malloc 调用一样,在 realloc 调用中使用变量。

             maximum_array_size = maximum_array_size + MAX_LENGTH_INC;
             ptr = realloc(ptr, maximum_array_size * sizeof(int));

加法maximum_array_size = maximum_array_size + MAX_LENGTH_INC;可以写成maximum_array_size += MAX_LENGTH_INC;。这实际上有助于阅读代码,因为现在很清楚,MAX_LENGTH_INC 的值将被添加到 maximum_array_size

然后你应该决定是写sizeof(int) * num还是num * sizeof(int)。我相信,num * sizeof(int) 更合乎逻辑,因为你有 20 个 int 而不是 int 20s ;)

现在评论中的另一个建议是:每次迭代递增 1 对于长循环来说真的很慢。所以每次迭代最好将缓冲区大小加倍:

             maximum_array_size *= 2;
             ++maximum_array_size; // not exactly needed, I like it this way

现在,您可能会浪费一点缓冲区,但最多会浪费 50%。当然,你应该添加一个新变量:num_array_elements,因为maximum_array_size 不再计算元素的数量。

        }
    }
    for(i=0;i<sizeof(ptr);i++)
        printf("\n Array Value is %d ",ptr[i]);

再次有评论告诉它:sizeof(ptr) 在这里绝对是错误的。原因是:ptr 是一个指针。并且指针的大小总是相同的(即 8 个字节),而不管它指向的内存块的大小。您可能想在此处使用新变量 num_array_elements

然后,即使对于像这里这样的单行语句,您也应该添加大括号。时间到了,您添加另一行并忘记添加大括号,从而产生很难找到的错误。所以:

    for (i = 0; i < num_array_elements; i++) {
        printf("\n Array Value is %d ", ptr[i]);
    }

另外,如您所见,我添加了一些空格。空格使您的代码更容易阅读。像forif 这样的控制流关键字通常用后面的空格编写,函数调用没有。语言无关紧要,但它是被广泛采用的风格。

    free(ptr);

    return 0;
}

休息似乎很好。所以,还没有为您做:实际添加并实现变量num_array_elements,并可能将maximum_array_size 重命名为array_sizemaximum_array_elements。此外,写max 而不是maximum 也被广泛采用,例如写num 而不是number

【讨论】:

  • sizeof 2 工作正常,但 sizeof int 无法编译。表达式只能省略括号,类型不能。
  • 不管怎样,现在我知道了,为什么人们总是坚持写括号。
  • 括号还有另一个原因:sizeof 2 * 3 + 4sizeof(2) * 3 + 4 或同等的4 + 3 * sizeof(2) 更难阅读。现在想象所有这些数字本身就是表达式。例如,我会在我自己的可重用动态数组类型的增长实现中写arr-&gt;cap * 2 * sizeof(*arr-&gt;data)
  • @ChronoKitsune 计算一个类型的大小可能更容易解释,sizeof 的参数是该类型的强制转换表达式。 2(int) 都是表达式,但只有后者是强制转换,当然强制转换是用括号写的。我还强烈建议在sizeof 和它的参数之间留一个空格,因为它不是一个函数
  • @unwind 非常正确,虽然转换表达式通常用于将数据转换为不同的类型,因此将操作视为具有计算机科学课程之外的大小是很奇怪的......你'还正确的是,sizeof 与其参数之间应该有一个空格。这实际上是我思考分配方式的副产品。对我来说,分配的每个项目的大小在视觉上相当于背景噪音:必要但需要较少关注。我正在分配 N 个项目,这是重要的部分。也许这是我的错,但它还没有让我失望! :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 2017-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
相关资源
最近更新 更多