[C] Implementing dynamic array objects in C language programming

Source: Internet
Author: User

For people accustomed to programming in high-level languages, one of the biggest headaches with programming in C is the need to determine the array length in advance using arrays.

The C language itself does not provide a dynamic array of such data structures, this article will demonstrate how to implement an object in C language programming as a dynamic array.

  /* Author: [email protected] */

Basic C-Array

  

The C language program declares a basic array as follows:

int Main () {    //  declares an array containing 3,000 integers    int my_array[];}

The above code does two things:

open up memory space in the stack area. It is precisely in the stack space of the function main that it opens up a memory space of * sizeof (int) bytes. The memory space opened in this way is automatically freed when the program runs to the end of the current chunk (the bottom of the main function for this example).

Create a pointer to the newly opened memory area and assign the pointer to the variable My_array save. We can access the members of the array by means of the subscript, for example, my_array[271] can access to a No. 272 member. You can also access the members of the array in another way, i.e. * (My_array + 271).

It can be seen that the essence of the C language array is memory management operations, subscript index is just a syntactic sugar.

The C language array has two fog zones:

It is difficult to automatically enlarge the array as the data increases. The fact is that you can use the ReAlloc function to expand the size of the array that opens up the heap, and of course we want an array object that can be resized automatically.

you can index to areas outside the bounds of the array. since the C language does not check the bounds of the array, that is, you do have access to the memory addresses of areas beyond the bounds of the array, such as my_array[5000], which is syntactically feasible. Because the subscript index is just a syntactic sugar, what it actually does is move backwards 5,000 times from the pointer My_array and read the data saved by the memory address it's parked in. When you index an area outside the bounds of the data, it is equivalent to reading the contents of the unallocated memory, but this is not what you really want, and it can have potentially serious consequences.

If we can tolerate some of the speed and memory space sacrifices, then we can implement some kind of data structure as the so-called "dynamic array". We refer to this data structure as a Vector, but this data structure does not solve all of the problems we encountered in the operation of the set, it is suitable for appending members, but not suitable for inserting and deleting operations, if you need a large number of insertions and deletions, linked lists such data structure to meet your needs, But the list also has its problems, and we're not doing much discussion here.

Defining Vector Objects

  

In this article we will create a "dynamic array" that holds integers, and let's name this data structure a Vector. First we use a header file Vector.h to define the data structure vector:

//First, define a constant that represents the initial size of an array object inside the Vector. #defineVector_initial_capacity 100//Vector for defining data Structurestypedefstruct {    intSize//Array in length    intcapacity;//maximum usable length of array    int*data;//the array object used to hold the integer object} Vector;//The function is responsible for initializing a Vector object with an initial array of length 0 and a maximum length of vector_initial_capacity.
Open up the appropriate memory space for the underlying array to use, with a space size of vector->capacity * sizeof (int) bytes. voidVector_init (Vector *vector);//The function is responsible for appending the members of the integer type to the Vector object. If the underlying array is full, the underlying array volume is enlarged to hold the new member.
voidVector_append (Vector *vector,intvalue);//returns the value saved by the vector at the specified position. If the specified position is less than 0 or greater than vector->size-1, an exception is returned. intVector_get (Vector *vector,intindex);//saves the specified value to the specified location, and if the specified position is greater than vector->size, automatically double the array volume inside the vector until the specified number of positions can be accommodated.
The enlarged array is used in the middle of 0 to fill those empty positions. voidVector_set (Vector *vector,intIndexintvalue);
//doubles the volume of the vector's internal array.
Because the overhead of changing the volume of an array is very large, a doubling strategy is used to avoid frequent changes to the array volume. voidVector_double_capacity_if_full (Vector *vector);//frees the memory space used by the array inside the vector. voidVector_free (Vector *vector);

Implementing Vector Objects

The following code (VECTOR.C) shows how to implement the vector data structure:

#include <stdio.h>#include<stdlib.h>#include"Vector.h"voidVector_init (Vector *vector) {    //initializes the size and capacity. Vector->size =0; Vector->capacity =vector_initial_capacity; //Request memory space for the vector internal data array ObjectVector->data = malloc (sizeof(int) * vector->capacity);}voidVector_append (Vector *vector,intvalue) {    //Ensure that there is currently enough memory space available. vector_double_capacity_if_full (vector); //appends an integer to the tail of the array. vector->data[vector->size++] =value;}intVector_get (Vector *vector,intindex) {    if(Index >= vector->size | | Index <0) {printf ("Index%d out of bounds for vector of size%d\n", Index, vector->size); Exit (1); }       returnVector->Data[index];}voidVector_set (Vector *vector,intIndexintvalue) {    //use 0 padding to idle in memory space.      while(Index >= vector->size) {vector_append (vector,0); }       //saves the specified integer at the specified array location. Vector->data[index] =value;}voidVector_double_capacity_if_full (Vector *vector) {    if(Vector->size >= vector->capacity) {        //The size of the multiply group. Vector->capacity *=2; Vector->data = ReAlloc (Vector->data,sizeof(int) * vector->capacity); }   }voidVector_free (Vector *vector) {Free (vector-data);}

Using Vector objects

The following code (VECTOR-USAGE.C) shows how to use the vector object:

#include <stdio.h>#include"Vector.h"intMain () {//declares a new Vector object and initializes it. vector vector;
Vector_init (&vector); //Initializes an internal array of vectors to hold up to 100 integers.
Now we will save 150 integers into the vector object.
Vector automatically expands the internal array volume by up to 200 integers, but only 150 locations are used.
inti; for(i = $; i > -; i--) {vector_append (&vector, i); } //we specify that an integer of 99999 is saved in the No. 251 position.
The vector automatically doubles the internal array volume to 400 positions and puts 99999 in the No. 251 position.
In addition, all positions between the 151th to No. 250 are filled with 0. Vector_set (&vector, -,99999); //reads the integer value of the 28th position, where the integer should be 173. printf"heres the value at:%d\n", Vector_get (&vector, -)); //traverse the current vector internal array for all actual in-use locations. for(i =0; i < vector.size; i++) {printf ("vector[%d] =%d\n", I, Vector_get (&vector, i)); } //releases the inner array of the vector object. Vector_free (&vector);}

The above code we use the vector data structure as a dynamic array, the first vector size (size) is 100 integer capacity, then we added 150 integers, and then we add an integer 99999 in the No. 251 position. Compile and run the above code:

$ gcc vector.c vector-usage.c $. /A. outheres the value at -:173vector[0] = $vector[1] =199vector[2] =198. .. vector[148] = thevector[149] =Wuyivector[ Max] =0vector[151] =0. .. vector[249] =0vector[ -] =99999

You can see that the dynamic array size is 251 integer capacity (you can actually save 400 integers), the 28th position has a value of 173, the middle position uses 0 padding, and the No. 251 position value is 99999.

The art of balance in the data structure

This article shows you how to implement an underlying data structure and understand the underlying implementation process to better understand the behavior of some high-level languages and why they can have some speed bottlenecks.

Adjusting the data structure in this article the size of the array inside the Vector is a costly operation because it needs to call the ReAlloc () function. The ReAlloc () function adjusts the size of the memory space that the pointer points to, and returns a pointer to the adjusted memory space. If the current memory area does not have enough free space to extend the current memory space, then ReAlloc () opens up a new area of memory, copies the old memory space pointed to by the pointer to the new memory space, frees up the old memory space, and returns a new memory space pointer.

So we have to do a very expensive copy operation if we encounter the current memory area not enough to extend our array. In order to reduce the likelihood of this situation, each time we expand the memory space is always doubled to open up new memory space, this strategy brings the side effect is likely to create a waste of memory space, this is a memory space and speed of the balance.

In addition, the data structure implemented in this article can only hold integer type objects. If the array used in our data structure holds pointers to empty objects instead of integers, then we can save any type of value. But then, every time we read the data stored in the structure, we encounter the bottleneck caused by the solution pointer, which is another balance between flexibility and performance.

Ref.:

1. Implementing a dynamically sized array in C

[C] Implementing dynamic array objects in C language programming

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.