I have a char array
char *data[]= {"11", "22", "33", "44", "55"};
How can I add some extra items to it in the end? data[]="66";
I'd like a dynamic array in C.
Thanks
Arrays created using the [] syntax are not dynamic, the length is set at compile-time and cannot change.
UPDATE: Actually, C99 adds so-called "variable-length arrays", which can get their length at run-time. After they've been initialized, however, they can't shrink or expand so the below still applies.
However, an array is trivially expressed when you have pointers: an array can be represented as a pointer to the first element, and a length.
So, you can create a new array by dynamically allocating memory using malloc():
size_t array_length = 3;
int *array = malloc(array_length * sizeof *array);
if(array != NULL)
{
array[0] = 11;
array[1] = 22;
array[2] = 33;
}
You cannot use the {} list of elements here, that's only usable when initializing arrays declared using the [] syntax.
To grow the array, you can use the realloc() function to re-allocate the memory and copy the old values over:
size_t new_length = array_length + 1;
int *bigger_array = realloc(array, new_length * sizeof *bigger_array);
if(bigger_array != NULL)
{
bigger_array[new_length - 1] = 44;
/* We have successfully grown the allocation, remember the new address. */
array = bigger_array;
array_length = new_length;
}
Note that every time you call malloc() (or realloc()), it can return NULL if it failed to allocate the requested block. That's why the if statements are needed. I cut the initial size down a bit from your example to reduce the number of assignment-lines needed, to make the example shorter.
To make the above more efficient, typical dynamical array code uses two length values: one for the actual array (how many values are in the array right now) and one for the memory (how many values to we have room to store). By making the latter value grow in chunks, the total number of memory allocations can be cut down a bit, at the cost of some memory of course.
vc_vector
vc_vector* vector = vc_vector_create(0, sizeof(const char *), NULL);
vc_vector_push_back(vector, "11");
vc_vector_push_back(vector, "22");
vc_vector_push_back(vector, "33");
for (int i = 0; i < vc_vector_count(vector); ++i) {
printf("%s ", (const char*)vc_vector_at(vector, i));
}
// output: 11 22 33
vc_vector_release(vector);
Here is a macro based solution for a dynamic array in C with a very nice syntax to use. Works for any data type.
#include <stdio.h>
#include <stdlib.h>
#include <wondermacros/array/dynamic_array.h>
int main()
{
int* elems = NULL; /* Initialize a dynamic array. */
W_DYNAMIC_ARRAY_PUSH(elems, 1, 2, 3, 4); /* Push some elements. */
/* Iterate all elements. */
W_DYNAMIC_ARRAY_FOR_EACH(int, e, elems) {
printf("%d\n", e);
}
W_DYNAMIC_ARRAY_FREE(elems); /* Free the array only this way since there is a hidden header. */
}
The library uses Boost pre-processor library so Boost library needs to be there at build time.
Related
So, I have this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void remove_element(int* array, int sizeOfArray, int indexToRemove)
{
int* temp = malloc((sizeOfArray - 1) * sizeof(int*)); // allocate an array with a size 1 less than the current one
memcpy(temp, array, indexToRemove - 1); // copy everything BEFORE the index
memcpy(temp+(indexToRemove * sizeof(int*)), temp+((indexToRemove+1) * sizeof(int*)), sizeOfArray - indexToRemove); // copy everything AFTER the index
free (array);
array = temp;
}
int main()
{
int howMany = 20;
int* test = malloc(howMany * sizeof(int*));
for (int i = 0; i < howMany; ++i)
(test[i]) = i;
printf("%d\n", test[16]);
remove_element(test, howMany, 16);
--howMany;
printf("%d\n", test[16]);
return 0;
}
It's reasonably self-explanatory, remove_element removes a given element of a dynamic array.
As you can see, each element of test is initialised to an incrementing integer (that is, test[n] == n). However, the program outputs
16
16
.
Having removed an element of test, one would expect a call to to test[n] where n >= the removed element would result in what test[n+1] would have been before the removal. So I would expect the output
16
17
. What's going wrong?
EDIT: The problem has now been solved. Here's the fixed code (with crude debug printfs), should anyone else find it useful:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int remove_element(int** array, int sizeOfArray, int indexToRemove)
{
printf("Beginning processing. Array is currently: ");
for (int i = 0; i < sizeOfArray; ++i)
printf("%d ", (*array)[i]);
printf("\n");
int* temp = malloc((sizeOfArray - 1) * sizeof(int)); // allocate an array with a size 1 less than the current one
memmove(
temp,
*array,
(indexToRemove+1)*sizeof(int)); // copy everything BEFORE the index
memmove(
temp+indexToRemove,
(*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove)*sizeof(int)); // copy everything AFTER the index
printf("Processing done. Array is currently: ");
for (int i = 0; i < sizeOfArray - 1; ++i)
printf("%d ", (temp)[i]);
printf("\n");
free (*array);
*array = temp;
return 0;
}
int main()
{
int howMany = 20;
int* test = malloc(howMany * sizeof(int*));
for (int i = 0; i < howMany; ++i)
(test[i]) = i;
printf("%d\n", test[16]);
remove_element(&test, howMany, 14);
--howMany;
printf("%d\n", test[16]);
return 0;
}
I see several issues in the posted code, each of which could cause problems:
returning the new array
Your function is taking an int* array but then you are trying to swap it with your temp variable at the end prior to returning the new array. This will not work, as you are simply replacing the local copy of int* array which will disappear after you return from the function.
You either need to pass your array pointer in as an int**, which would allow you to set the actual pointer to the array in the function, or, I would suggest just returning a value
of int* for your function, and returning the new array.
Also, as mentioned in this answer, you really don't even need to reallocate when deleting an element from the array, since the original array is big enough to hold everything.
size and offset calculations
You are using sizeof(int*) for calculating the array element size. This may work for some types, but, for instance, for a short array sizeof(short*) does not work. You don't want the size of the pointer to the array, you want the size of the elements, which for your example should be sizeof(int) although it may not cause problems in this case.
Your length calculation for the offsets into the arrays looks ok, but you're forgetting to multiply the number of elements by the element size for the size parameter of the memcpy. e.g. memcpy(temp, array, indexToRemove * sizeof(int));.
Your second call to memcpy is using temp plus the offset as the source array, but it should be array plus the offset.
Your second call to memcpy is using sizeOfArray - indexToRemove for the number of elements to copy, but you should only copy SizeOfArray - indexToRemove - 1 elements (or (sizeOfArray - indexToRemove - 1) * sizeof(int) bytes
Wherever you are calculating offsets into the temp and array arrays, you don't need to multiply by sizeof(int), since pointer arithmetic already takes into account the size of the elements. (I missed this at first, thanks to: this answer.)
looking at incorrect element
You are printing test[16] (the 17th element) for testing, but you are removing the 16th element, which would be test[15].
corner cases
Also (thanks to this answer) you should handle the cases where indexToRemove == 0 and indexToRemove == (sizeOfArray - 1), where you can do the entire removal in one memcpy.
Also, you need to worry about the case where sizeOfArray == 1. In that case perhaps either allocate a 0 size block of memory, or return null. In my updated code, I chose to allocate a 0-size block, just to differentiate between an array with 0 elements vs. an unallocated array.
Returning a 0-size array also means there are no additional changes necessary to the code, because the conditions before each memcpy to handle the first two cases mentioned will prevent either memcpy from taking place.
And just to mention, there's no error handling in the code, so there are implicit preconditions that indexToRemove is in bounds, that array is not null, and that array has the size passed as sizeOfArray.
example updated code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* remove_element(int* array, int sizeOfArray, int indexToRemove)
{
int* temp = malloc((sizeOfArray - 1) * sizeof(int)); // allocate an array with a size 1 less than the current one
if (indexToRemove != 0)
memcpy(temp, array, indexToRemove * sizeof(int)); // copy everything BEFORE the index
if (indexToRemove != (sizeOfArray - 1))
memcpy(temp+indexToRemove, array+indexToRemove+1, (sizeOfArray - indexToRemove - 1) * sizeof(int)); // copy everything AFTER the index
free (array);
return temp;
}
int main()
{
int howMany = 20;
int* test = malloc(howMany * sizeof(int));
for (int i = 0; i < howMany; ++i)
test[i] = i;
printf("%d\n", test[16]);
test = remove_element(test, howMany, 16);
--howMany;
printf("%d\n", test[16]);
free(test);
return 0;
}
a few words on memory management/abstract data types
Finally, something to consider: there are possible issues both with using malloc to return memory to a user that is expected to be freed by the user, and with freeing memory that a user malloced. In general, it's less likely that memory management will be confusing and hard to handle if you design your code units such that memory allocation is handled within a single logical code unit.
For instance, you might create an abstract data type module that allowed you to create an integer array using a struct that holds a pointer and a length, and then all manipulation of that data goes through functions taking the structure as a first parameter. This also allows you, except within that module, to avoid having to do calculations like elemNumber * sizeof(elemType). Something like this:
struct MyIntArray
{
int* ArrHead;
int ElementSize;
// if you wanted support for resizing without reallocating you might also
// have your Create function take an initialBufferSize, and:
// int BufferSize;
};
void MyIntArray_Create(struct MyIntArray* This, int numElems /*, int initBuffSize */);
void MyIntArray_Destroy(struct MyIntArray* This);
bool MyIntArray_RemoveElement(struct MyIntArray* This, int index);
bool MyIntArray_InsertElement(string MyIntArray* THis, int index, int Value);
etc.
This is a basically implementing some C++-like functionality in C, and it's IMO a very good idea, especially if you are starting from scratch and you want to create anything more than a very simple application. I know of some C developers that really don't like this idiom, but it has worked well for me.
The nice thing about this way of implementing things is that anything in your code that was using the function to remove an element would not ever be touching the pointer directly. This would allow several different parts of your code to store a pointer to your abstract array structure, and when the pointer to the actual data of the array was reallocated after the element was removed, all variables pointing to your abstract array would be automatically updated.
In general, memory management can be very confusing, and this is one strategy that can make it less so. Just a thought.
You don't actually change the passed pointer. You're only changing your copy of array.
void remove_element(int* array, int sizeOfArray, int indexToRemove)
{
int* temp = malloc((sizeOfArray - 1) * sizeof(int*));
free (array); /* Destroys the array the caller gave you. */
array = temp; /* Temp is lost. This has **no effect** for the caller. */
}
So after the function the array still points to where it used to point BUT, you've also freed it, which adds insult to injury.
Try something like this:
void remove_element(int **array, int sizeOfArray, int indexToRemove)
^^
{
int *temp = malloc((sizeOfArray - 1) * sizeof(int*));
/* More stuff. */
free(*array);
*array = temp;
}
There is also a C FAQ: Change passed pointer.
#cnicutar is right (+1), but also, you write:
memcpy(temp+(indexToRemove * sizeof(int*)), temp+((indexToRemove+1) * sizeof(int*)), sizeOfArray - indexToRemove); // copy everything AFTER the index
while it should be:
memmove(temp+(indexToRemove), temp+(indexToRemove+1), sizeOfArray - indexToRemove); // copy everything AFTER the index
Since the multiplication by the size of int* is done by the compiler (that's pointer arithmetic)
Also, when moving overlaying memory areas, use memmove and not memcpy.
Further: the second argument to your second memcpy call should be based on array, not on temp, right? And shouldn't you be mallocing and copying based on sizeof int and not based on sizeof int*, since your arrays store integers and not pointers? And don't you need to multiply the number of bytes you're copying (the last argument to memcpy) by sizeof int as well?
Also, watch the case where indexToRemove == 0.
There are a few problems with that code :
(a) When allocating memory, you need to make sure to use the correct type with sizeof. For an array of int eg., you allocate a memory block with a size that is a multiple of sizeof(int). So :
int* test = malloc(howMany * sizeof(int*));
should be :
int* test = malloc(howMany * sizeof(int));
(b) You don't free the memory for the array at the end of main.
(c) memcpy takes the amount of bytes to copy as the third parameter. So, you need to again make sure to pass a multiple of sizeof(int). So :
memcpy(temp, array, cnt);
should be :
memcpy(temp, array, cnt * sizeof(int));
(d) when copying items from the old array to the new array, make sure to copy the correct data. For example, there are indexToRemove items before the item at index indexToRemove, not one less. Similarly, you'll need to make sure that you copy the correct amount of items after the item that needs to be removed.
(e) When incrementing a pointer, you don't need to multiply with sizeof(int) - that's done implicitly for you. So :
temp + (cnt * sizeof(int))
should really be :
temp + cnt
(f) In your remove_element function, you assign a value to the local variable array. Any changes to local variables are not visible outside of the function. So, after the call to remove_element ends, you won't see the change in main. One way to solve this, is to return the new pointer from the function, and assign it in main :
test = remove_element(test, howMany, 16);
All the other answers make good points about the various problems/bugs in the code.
But, why reallocate at all (not that the bugs are all related to reallocation)? The 'smaller' array will fit fine in the existing block of memory:
// Note: untested (not even compiled) code; it also doesn't do any
// checks for overflow, parameter validation, etc.
int remove_element(int* array, int sizeOfArray, int indexToRemove)
{
// assuming that sizeOfArray is the count of valid elements in the array
int elements_to_move = sizeOfArray - indexToRemove - 1;
memmove( &array[indexToRemove], &array[indexToRemove+1], elements_to_move * sizeof(array[0]));
// let the caller know how many elements remain in the array
// of course, they could figure this out themselves...
return sizeOfArray - 1;
}
I am learning C language. I want to know the size of an array inside a function. This function receive a pointer pointing to the first element to the array. I don't want to send the size value like a function parameter.
My code is:
#include <stdio.h>
void ShowArray(short* a);
int main (int argc, char* argv[])
{
short vec[] = { 0, 1, 2, 3, 4 };
short* p = &vec[0];
ShowArray(p);
return 0;
}
void ShowArray(short* a)
{
short i = 0;
while( *(a + i) != NULL )
{
printf("%hd ", *(a + i) );
++i;
}
printf("\n");
}
My code doesn't show any number. How can I fix it?
Thanks.
Arrays in C are simply ways to allocate contiguous memory locations and are not "objects" as you might find in other languages. Therefore, when you allocate an array (e.g. int numbers[5];) you're specifying how much physical memory you want to reserve for your array.
However, that doesn't tell you how many valid entries you have in the (conceptual) list for which the physical array is being used at any specific point in time.
Therefore, you're required to keep the actual length of the "list" as a separate variable (e.g. size_t numbers_cnt = 0;).
I don't want to send the size value like a function parameter.
Since you don't want to do this, one alternative is to use a struct and build an array type yourself. For example:
struct int_array_t {
int *data;
size_t length;
};
This way, you could use it in a way similar to:
struct int_array_t array;
array.data = // malloc for array data here...
array.length = 0;
// ...
some_function_call(array); // send the "object", not multiple arguments
Now you don't have to write: some_other_function(data, length);, which is what you originally wanted to avoid.
To work with it, you could simply do something like this:
void display_array(struct int_array_t array)
{
size_t i;
printf("[");
for(i = 0; i < array.length; ++i)
printf("%d, ", array.data[i]);
printf("]\n");
}
I think this is a better and more reliable alternative than another suggestion of trying to fill the array with sentinel values (e.g. -1), which would be more difficult to work with in non-trivial programs (e.g. understand, maintain, debug, etc) and, AFAIK, is not considered good practice either.
For example, your current array is an array of shorts, which would mean that the proposed sentinel value of -1 can no longer be considered a valid entry within this array. You'd also need to zero out everything in the memory block, just in case some of those sentinels were already present in the allocated memory.
Lastly, as you use it, it still wouldn't tell you what the actual length of your array is. If you don't track this in a separate variable, then you'll have to calculate the length at runtime by looping over all the data in your array until you come across a sentinel value (e.g. -1), which is going to impact performance.
In other words, to find the length, you'd have to do something like:
size_t len = 0;
while(arr[len++] != -1); // this is O(N)
printf("Length is %u\n", len);
The strlen function already suffers from this performance problem, having a time-complexity of O(N), because it has to process the entire string until it finds the NULL char to return the length.
Relying on sentinel values is also unsafe and has produced countless bugs and security vulnerabilities in C and C++ programs, to the point where even Microsoft recommends banning their use as a way to help prevent more security holes.
I think there's no need to create this kind of problem. Compare the above, with simply writing:
// this is O(1), does not rely on sentinels, and makes a program safer
printf("Length is %u\n", array.length);
As you add/remove elements into array.data you can simply write array.length++ or array.length-- to keep track of the actual amount of valid entries. All of these are constant-time operations.
You should also keep the maximum size of the array (what you used in malloc) around so that you can make sure that array.length never goes beyond said limit. Otherwise you'd get a segfault.
One way, is to use a terminator that is unique from any value in the array. For example, you want to pass an array of ints. You know that you never use the value -1. So you can use that as your terminator:
#define TERM (-1)
void print(int *arr)
{
for (; *arr != TERM; ++arr)
printf("%d\n", *arr);
}
But this approach is usually not used, because the sentinel could be a valid number. So normally, you will have to pass the length.
You can't use sizeof inside of the function, because as soon as you pass the array, it decays into a pointer to the first element. Thus, sizeof arr will be the size of a pointer on your machine.
#include <stdio.h>
void ShowArray(short* a);
int main (int argc, char* argv[])
{
short vec[] = { 0, 1, 2, 3, 4 };
short* p = &vec[0];
ShowArray(p);
return 0;
}
void ShowArray(short* a)
{
short i = 0;
short j;
j = sizeof(*a) / sizeof(short);
while( i < j )
{
printf("%hd ", *(a + i) );
++i;
}
printf("\n");
}
Not sure if this will work tho give it a try (I don't have a pc at the moment)
In the C language, is there a way to automatically grow an array.
For example:
int arr [100] [10];
If the array is full is it possible to have it "automatically" become larger? Or is that only possible if you're using C++. How would you write this in C?
There is no such feature in C: you have to declare the array using pointers, detect the "array is full" condition manually, call malloc, make a copy into an extended array, and free the original one. Even the variable-length arrays would not work, because they let you set their size only once per the array lifetime.
In C++, you can use std::vector<std::vector<int> > instead of a plain array. You still need to detect the "array is full" condition, but the std::vector<T> container takes care of all re-allocations and extensions on resizing for you.
"automatic" growth of any array in C is not possible. If you declare an array statically:
int arr[10];
you have however many memory locations as you indicated. If you want to be able to change it during runtime you need to declare it dynamically using malloc() and make it larger using realloc()
A quick example for you:
int main(void){
int input, count = 0, length = 2;
int * arr = malloc(sizeof(int) * length); // array of size 2
while((input = getchar()) != 'q') //get input from the user
{
getchar(); //get rid of newlines
arr[count] = input;
if(count + 1 == length){ // if our array is running out of space
arr = realloc(arr, length * length); // make it twice as big as it was
length *= length;
}
count++;
}
for(length = 0; length < count; length++) // print the contents
printf("%d\n", arr[length]);
free(arr);
return 0;
}
how can i define an array in c which works like vector? This array should take any amount of values. It can take 0 values or 10 values or 100 values.
The code below works but gives me a runtime error that stack was corrupted.
int i = 0;
int* aPtr = &i;
int* head = aPtr;
for(i=0;i<6;i++){
(*aPtr)=i;
aPtr++;
}
Similarly how can i use char* str to take any amount of characters followed by null character in end to make a string?
Practice for interviews :)
There are many ways to do this in C, depending on your requirements, but you said "any number of values" (which usually means as many as will fit in memory). That's commonly done using realloc to grow the size of an array dynamically. You'll need to keep some bookkeeping information too on the size of the array as it grows.
void
store (vector_t * v, int idx, int value)
{
if (v->size < idx) {
v->size = idx * 2;
v->data = realloc(v->data, v->size);
}
v->data[idx] = value;
}
This being tagged "homework", I've left some details to fill in such as the definition of vector_t.
In Your for loop , after the first iteration, you are trying to access aPtr which points to a memory location which was not declared or reserved before. In the first iteration, the int i did the memory allocation for you.
What you could do though would be to initally allocate the memory required using malloc .
Once this memory is allocated , and if you walk through only the allocated stack space, you wont come across a run time error.
PS:Your code does not work if it just compiles. Any program may contain run time as well as compile time errors. Your code sample is a very common example of run-time error.
This isn't too difficult. The important thing to remember is that you will need to initially allocate memory for your array using malloc(...) or calloc(...). After that you can easily allocate (or deallocate) memory as items are added or removed. The method for dynamically adding or removing memory (which is used to store the items in the array) is realloc(...). The wiki page for C Dynamic Memory Allocation is actually pretty informative. I've provided an example below showing how to initially allocate a char* array, then increase the size and decrease the size.
#include "stdio.h"
#include "stdlib.h"
int main()
{
char *myDynamicString;
/* allocate initial memory */
myDynamicString = (char *)malloc(sizeof(char) * 2);
myDynamicString[1] = '\0';
/* set values */
myDynamicString[0] = 'A';
/* prints: A */
printf("String: %s\n", myDynamicString);
/* make string bigger */
myDynamicString = (char *)realloc(myDynamicString, sizeof(char) * 6);
myDynamicString[5] = '\0';
/* set values */
myDynamicString[1] = 'P';
myDynamicString[2] = 'P';
myDynamicString[3] = 'L';
myDynamicString[4] = 'E';
/* prints: APPLE */
printf("Bigger String: %s\n", myDynamicString);
/* make string smaller */
myDynamicString = (char *)realloc(myDynamicString, sizeof(char) * 3);
myDynamicString[2] = '\0';
/* set values */
myDynamicString[1] = 'Z';
/* prints: AZ */
printf("Smaller String: %s\n", myDynamicString);
/* don't forget to release the memory */
free(myDynamicString);
return 0;
}
So, I have this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void remove_element(int* array, int sizeOfArray, int indexToRemove)
{
int* temp = malloc((sizeOfArray - 1) * sizeof(int*)); // allocate an array with a size 1 less than the current one
memcpy(temp, array, indexToRemove - 1); // copy everything BEFORE the index
memcpy(temp+(indexToRemove * sizeof(int*)), temp+((indexToRemove+1) * sizeof(int*)), sizeOfArray - indexToRemove); // copy everything AFTER the index
free (array);
array = temp;
}
int main()
{
int howMany = 20;
int* test = malloc(howMany * sizeof(int*));
for (int i = 0; i < howMany; ++i)
(test[i]) = i;
printf("%d\n", test[16]);
remove_element(test, howMany, 16);
--howMany;
printf("%d\n", test[16]);
return 0;
}
It's reasonably self-explanatory, remove_element removes a given element of a dynamic array.
As you can see, each element of test is initialised to an incrementing integer (that is, test[n] == n). However, the program outputs
16
16
.
Having removed an element of test, one would expect a call to to test[n] where n >= the removed element would result in what test[n+1] would have been before the removal. So I would expect the output
16
17
. What's going wrong?
EDIT: The problem has now been solved. Here's the fixed code (with crude debug printfs), should anyone else find it useful:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int remove_element(int** array, int sizeOfArray, int indexToRemove)
{
printf("Beginning processing. Array is currently: ");
for (int i = 0; i < sizeOfArray; ++i)
printf("%d ", (*array)[i]);
printf("\n");
int* temp = malloc((sizeOfArray - 1) * sizeof(int)); // allocate an array with a size 1 less than the current one
memmove(
temp,
*array,
(indexToRemove+1)*sizeof(int)); // copy everything BEFORE the index
memmove(
temp+indexToRemove,
(*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove)*sizeof(int)); // copy everything AFTER the index
printf("Processing done. Array is currently: ");
for (int i = 0; i < sizeOfArray - 1; ++i)
printf("%d ", (temp)[i]);
printf("\n");
free (*array);
*array = temp;
return 0;
}
int main()
{
int howMany = 20;
int* test = malloc(howMany * sizeof(int*));
for (int i = 0; i < howMany; ++i)
(test[i]) = i;
printf("%d\n", test[16]);
remove_element(&test, howMany, 14);
--howMany;
printf("%d\n", test[16]);
return 0;
}
I see several issues in the posted code, each of which could cause problems:
returning the new array
Your function is taking an int* array but then you are trying to swap it with your temp variable at the end prior to returning the new array. This will not work, as you are simply replacing the local copy of int* array which will disappear after you return from the function.
You either need to pass your array pointer in as an int**, which would allow you to set the actual pointer to the array in the function, or, I would suggest just returning a value
of int* for your function, and returning the new array.
Also, as mentioned in this answer, you really don't even need to reallocate when deleting an element from the array, since the original array is big enough to hold everything.
size and offset calculations
You are using sizeof(int*) for calculating the array element size. This may work for some types, but, for instance, for a short array sizeof(short*) does not work. You don't want the size of the pointer to the array, you want the size of the elements, which for your example should be sizeof(int) although it may not cause problems in this case.
Your length calculation for the offsets into the arrays looks ok, but you're forgetting to multiply the number of elements by the element size for the size parameter of the memcpy. e.g. memcpy(temp, array, indexToRemove * sizeof(int));.
Your second call to memcpy is using temp plus the offset as the source array, but it should be array plus the offset.
Your second call to memcpy is using sizeOfArray - indexToRemove for the number of elements to copy, but you should only copy SizeOfArray - indexToRemove - 1 elements (or (sizeOfArray - indexToRemove - 1) * sizeof(int) bytes
Wherever you are calculating offsets into the temp and array arrays, you don't need to multiply by sizeof(int), since pointer arithmetic already takes into account the size of the elements. (I missed this at first, thanks to: this answer.)
looking at incorrect element
You are printing test[16] (the 17th element) for testing, but you are removing the 16th element, which would be test[15].
corner cases
Also (thanks to this answer) you should handle the cases where indexToRemove == 0 and indexToRemove == (sizeOfArray - 1), where you can do the entire removal in one memcpy.
Also, you need to worry about the case where sizeOfArray == 1. In that case perhaps either allocate a 0 size block of memory, or return null. In my updated code, I chose to allocate a 0-size block, just to differentiate between an array with 0 elements vs. an unallocated array.
Returning a 0-size array also means there are no additional changes necessary to the code, because the conditions before each memcpy to handle the first two cases mentioned will prevent either memcpy from taking place.
And just to mention, there's no error handling in the code, so there are implicit preconditions that indexToRemove is in bounds, that array is not null, and that array has the size passed as sizeOfArray.
example updated code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int* remove_element(int* array, int sizeOfArray, int indexToRemove)
{
int* temp = malloc((sizeOfArray - 1) * sizeof(int)); // allocate an array with a size 1 less than the current one
if (indexToRemove != 0)
memcpy(temp, array, indexToRemove * sizeof(int)); // copy everything BEFORE the index
if (indexToRemove != (sizeOfArray - 1))
memcpy(temp+indexToRemove, array+indexToRemove+1, (sizeOfArray - indexToRemove - 1) * sizeof(int)); // copy everything AFTER the index
free (array);
return temp;
}
int main()
{
int howMany = 20;
int* test = malloc(howMany * sizeof(int));
for (int i = 0; i < howMany; ++i)
test[i] = i;
printf("%d\n", test[16]);
test = remove_element(test, howMany, 16);
--howMany;
printf("%d\n", test[16]);
free(test);
return 0;
}
a few words on memory management/abstract data types
Finally, something to consider: there are possible issues both with using malloc to return memory to a user that is expected to be freed by the user, and with freeing memory that a user malloced. In general, it's less likely that memory management will be confusing and hard to handle if you design your code units such that memory allocation is handled within a single logical code unit.
For instance, you might create an abstract data type module that allowed you to create an integer array using a struct that holds a pointer and a length, and then all manipulation of that data goes through functions taking the structure as a first parameter. This also allows you, except within that module, to avoid having to do calculations like elemNumber * sizeof(elemType). Something like this:
struct MyIntArray
{
int* ArrHead;
int ElementSize;
// if you wanted support for resizing without reallocating you might also
// have your Create function take an initialBufferSize, and:
// int BufferSize;
};
void MyIntArray_Create(struct MyIntArray* This, int numElems /*, int initBuffSize */);
void MyIntArray_Destroy(struct MyIntArray* This);
bool MyIntArray_RemoveElement(struct MyIntArray* This, int index);
bool MyIntArray_InsertElement(string MyIntArray* THis, int index, int Value);
etc.
This is a basically implementing some C++-like functionality in C, and it's IMO a very good idea, especially if you are starting from scratch and you want to create anything more than a very simple application. I know of some C developers that really don't like this idiom, but it has worked well for me.
The nice thing about this way of implementing things is that anything in your code that was using the function to remove an element would not ever be touching the pointer directly. This would allow several different parts of your code to store a pointer to your abstract array structure, and when the pointer to the actual data of the array was reallocated after the element was removed, all variables pointing to your abstract array would be automatically updated.
In general, memory management can be very confusing, and this is one strategy that can make it less so. Just a thought.
You don't actually change the passed pointer. You're only changing your copy of array.
void remove_element(int* array, int sizeOfArray, int indexToRemove)
{
int* temp = malloc((sizeOfArray - 1) * sizeof(int*));
free (array); /* Destroys the array the caller gave you. */
array = temp; /* Temp is lost. This has **no effect** for the caller. */
}
So after the function the array still points to where it used to point BUT, you've also freed it, which adds insult to injury.
Try something like this:
void remove_element(int **array, int sizeOfArray, int indexToRemove)
^^
{
int *temp = malloc((sizeOfArray - 1) * sizeof(int*));
/* More stuff. */
free(*array);
*array = temp;
}
There is also a C FAQ: Change passed pointer.
#cnicutar is right (+1), but also, you write:
memcpy(temp+(indexToRemove * sizeof(int*)), temp+((indexToRemove+1) * sizeof(int*)), sizeOfArray - indexToRemove); // copy everything AFTER the index
while it should be:
memmove(temp+(indexToRemove), temp+(indexToRemove+1), sizeOfArray - indexToRemove); // copy everything AFTER the index
Since the multiplication by the size of int* is done by the compiler (that's pointer arithmetic)
Also, when moving overlaying memory areas, use memmove and not memcpy.
Further: the second argument to your second memcpy call should be based on array, not on temp, right? And shouldn't you be mallocing and copying based on sizeof int and not based on sizeof int*, since your arrays store integers and not pointers? And don't you need to multiply the number of bytes you're copying (the last argument to memcpy) by sizeof int as well?
Also, watch the case where indexToRemove == 0.
There are a few problems with that code :
(a) When allocating memory, you need to make sure to use the correct type with sizeof. For an array of int eg., you allocate a memory block with a size that is a multiple of sizeof(int). So :
int* test = malloc(howMany * sizeof(int*));
should be :
int* test = malloc(howMany * sizeof(int));
(b) You don't free the memory for the array at the end of main.
(c) memcpy takes the amount of bytes to copy as the third parameter. So, you need to again make sure to pass a multiple of sizeof(int). So :
memcpy(temp, array, cnt);
should be :
memcpy(temp, array, cnt * sizeof(int));
(d) when copying items from the old array to the new array, make sure to copy the correct data. For example, there are indexToRemove items before the item at index indexToRemove, not one less. Similarly, you'll need to make sure that you copy the correct amount of items after the item that needs to be removed.
(e) When incrementing a pointer, you don't need to multiply with sizeof(int) - that's done implicitly for you. So :
temp + (cnt * sizeof(int))
should really be :
temp + cnt
(f) In your remove_element function, you assign a value to the local variable array. Any changes to local variables are not visible outside of the function. So, after the call to remove_element ends, you won't see the change in main. One way to solve this, is to return the new pointer from the function, and assign it in main :
test = remove_element(test, howMany, 16);
All the other answers make good points about the various problems/bugs in the code.
But, why reallocate at all (not that the bugs are all related to reallocation)? The 'smaller' array will fit fine in the existing block of memory:
// Note: untested (not even compiled) code; it also doesn't do any
// checks for overflow, parameter validation, etc.
int remove_element(int* array, int sizeOfArray, int indexToRemove)
{
// assuming that sizeOfArray is the count of valid elements in the array
int elements_to_move = sizeOfArray - indexToRemove - 1;
memmove( &array[indexToRemove], &array[indexToRemove+1], elements_to_move * sizeof(array[0]));
// let the caller know how many elements remain in the array
// of course, they could figure this out themselves...
return sizeOfArray - 1;
}