2013-12-07 110 views
2

我正在学习C并试图构建一个动态数组。我发现了一个很棒的教程,但我并没有完全掌握它。我现在的代码是C动态数组元素访问

typedef struct{ 
    int size; 
    int capacity; 
    char *data; 
}Brry; 

void brry_init(Brry *brry){ 
    brry->size = 0; 
    brry->capacity = 2; 
    brry->data = (char *)calloc(brry->capacity, sizeof(char)); 
} 

void brry_insert(Brry *brry, char value){ 
     brry->data[brry->size++] = value; //so do check here if I have enough memory, but checking something out 
} 

int main(void){ 
    Brry brry; 
    brry_init(&brry); 

    for (int i = 0; i < 3; i++) { 
     brry_insert(&brry, 'a'); 
    } 

    printf("%c\n", brry.data[2]); 
    return 0; 
} 

在我的主要功能我加3元到数组,但只分配给2.但是,当我打印出来它工作得很好?我期望打印一些奇怪的值。为什么这个或我做错了什么?

+1

请注意'brry.data [3]'是第四个元素。 – Novak

+0

对不起复制过去的错误 – Haagenti

+0

这是[undefined behavior](http://stackoverflow.com/a/367662/1113392) – A4L

回答

3

您正在写入未分配足够内存的缓冲区。它的工作原理不能保证。

你现在正在尝试从内存中的某些垃圾值中读取数据,谁知道,这有时会导致分段错误,其他时候你很幸运并获得一些垃圾值,并且它不会发生段错误。

写入垃圾内存将调用未定义的行为,所以最好观察它。 如果确实发生错误,它几乎总是一个段错误,是段错误的缩写。 阅读它here

通过读取数组的界限,你所做的技术称为去除一个指针。您可能还想了解更多关于here的信息。

+0

错误的方式。 如果你幸运的话,你会得到一个seg故障,并且知道你现在已经站起来而不是“有效”了,并且有人在路上会有某种致命的错误,可能会导致该公司数百万美元由于工资损失,维修/重新设计费用等造成的损失。 – ciphermagi

+0

@JonahNelson是的,有时候你会很幸运知道。但是我们希望OP从中学到一些东西。 – edwardmp

1

是的,你的确在写入一个两元素数组的第三个元素。这意味着您的程序将显示未定义的行为,您无法保证将发生什么。在你的情况下,你很幸运,该计划“工作”,但你可能并不总是如此幸运。

1

试图读取/写入数组的末尾会导致未定义的行为。究竟发生了什么取决于几个你无法预测或控制的因素。有时候,它似乎无需抱怨即可成功读取和/或写入。其他时候,它可能会导致程序崩溃并且非常有效。

关键的是你永远不应该尝试使用或依赖未定义的行为。不幸的是,这是一个常见的菜鸟错误,认为它会一直工作,因为一次测试成功了。这绝对不是这种情况,迟早会造成灾难。