I'm working in C
I have a struct called Entity and I create a dynamic array of that struct. Then I try to remove one element from the array but I don't get the behaviour I want.
Here is the code I'm using:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Entity
{
int x, y;
int velX, velY;
}Entity;
int remove_element(Entity** array, int sizeOfArray, int indexToRemove)
{
int i;
printf("Beginning processing. Array is currently: ");
for (i = 0; i < sizeOfArray; ++i)
printf("%d ", (*array)[i].x);
printf("\n");
Entity* temp = malloc((sizeOfArray - 1) * sizeof(Entity)); // allocate an array with a size 1 less than the current one
memmove(
temp,
*array,
(indexToRemove+1)*sizeof(Entity)); // copy everything BEFORE the index
memmove(
temp+indexToRemove,
(*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove)*sizeof(Entity)); // copy everything AFTER the index
printf("Processing done. Array is currently: ");
for (i = 0; i < sizeOfArray - 1; ++i)
printf("%d ", (temp)[i].x);
printf("\n");
free (*array);
*array = temp;
return 0;
}
int main()
{
int i;
int howMany = 20;
Entity* test = malloc(howMany * sizeof(Entity*));
for (i = 0; i < howMany; ++i)
(test[i].x) = i;
remove_element(&test, howMany, 14);
--howMany;
return 0;
}
And the output I get :
Beginning processing. Array is currently: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Processing done. Array is currently: 0 1 2 3 4 1866386284 6 7 8 9 10 11 12 13 15 16 17 18 19
Then the program crashes at the free (*array); line.
I want my second line to be 0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19.
How could I solve my problem ?
First thing you have allocated memory space for holding 20 Enity*. Then you have dereferenced it (and the value it contained is indeterminate). This is undefined behavior. And all story ends here.
But let's analyze what you mostly wanted.
Entity* test = malloc(howMany * sizeof(Entity));
^^^^^^^
is what you wanted. Because only if you do this you will get the member elements x and so on.
Also if you are considering 0 indexing then the memmove calls should be
memmove(temp, *array, (indexToRemove)*sizeof(Entity));
memmove(temp+indexToRemove, (*array)+(indexToRemove+1),
(sizeOfArray - indexToRemove - 1)*sizeof(Entity));
These two changes will be enough to solve the problems you are facing and realizing the correct behavior. (If this is all there is in your code).
Also as per standard the main() should be declared like this in case it doesn't take any parameter int main(void). Free the dynamically allocated memory when you are done working with it. Also you should check the return value of malloc - in case it fails it returns NULL and you should handle that case.
Your offset calculations are off by one in both memmove instances. Use this instead:
// copy everything BEFORE the index
memmove(temp,
*array,
indexToRemove * sizeof(Entity));
// copy everything AFTER the index
memmove(temp + indexToRemove,
*array + indexToRemove + 1,
(sizeOfArray - indexToRemove - 1) * sizeof(Entity));
In main itself your memeory allocation is not done properly.if you are using double pointer you should allocate memory first for double pointer and than single pointer in loop one by one.
a little touch
remove element in any type of struct array
regards
int remove_element(void **input_ptr, int input_size, int index_remove, int struct_size)
{
void *temp_ptr;
temp_ptr = malloc((input_size - 1) * struct_size);
if (temp_ptr == 0)
return -1;
memmove(temp_ptr, *input_ptr, index_remove * struct_size);
memmove(temp_ptr + (index_remove * struct_size), (*input_ptr) + (index_remove + 1) * struct_size, (input_size - index_remove - 1) * struct_size);
free(*input_ptr);
*input_ptr = temp_ptr;
return 1;
}
usage example for question struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Entity
{
int x, y;
int velX, velY;
}Entity;
int remove_element(void **input_ptr, int input_size, int index_remove, int struct_size)
{
void *temp_ptr;
temp_ptr = malloc((input_size - 1) * struct_size);
if (temp_ptr == 0)
return -1;
memmove(temp_ptr, *input_ptr, index_remove * struct_size);
memmove(temp_ptr + (index_remove * struct_size), (*input_ptr) + (index_remove + 1) * struct_size, (input_size - index_remove - 1) * struct_size);
free(*input_ptr);
*input_ptr = temp_ptr;
return 1;
}
int main()
{
int i;
int howMany = 20;
Entity* test = malloc(howMany * sizeof(Entity));
for (i = 0; i < howMany; ++i)
{
(test[i].x) = i;
printf("test[%d].x = '%d'\n", i, test[i].x);
}
remove_element((void**)&test, howMany, 14, sizeof(Entity));
--howMany;
printf("Deleted index --- new array\n");
for (i = 0; i < howMany; ++i)
printf("test[%d].x = '%d'\n", i, test[i].x);
return 0;
}
Related
Just having an issue here with SIGSEV.
The role of this program is to build a matrix of n * n, which is the first command line argument, and then furthermore fills out the matrix from integers sourced from command line arguments.
The output then consists of the main diagonal of this matrix summed together
Example:
1 2 3
4 5 6
7 8 9
1 + 5 + 9 = 15
Sample input:
./file-name 3 1 2 3 4 5 6 7 8 9
Sample output:
15
However I'm very confused, as it works with all matrices under size 5, but once I go over, I get this address boundary error. Anyone know why?
Error:
fish: Job 1, './file-name 5...' terminated by signal SIGSEV (Address boundary error)
Code:
/* Description: Takes integer arguments from command line
* First argument signafies matrix's size, (n * n)
* Remaining arguments fill matrix.
* Then the main diagonal of the matrix is summed
* and outputted
* Input: Multiple integers as cmd line arguments, first signifies
* matrix size (n * n)
* Output: A single integer, the sum of the diagonals
*
*/
// Includes
#include <stdio.h>
#include <stdlib.h>
// Function Prototypes
void fill_matrix(int **matrix, int n, char **argv);
int sum_diag_matrix(int **matrix, int n);
// Main Function
int main(int argc, char **argv) {
// Take cmd line args
int n = atoi(argv[1]);
// Assign and allocate double pointer enough memory for matrix of size n
int **matrix = (int **) malloc(n * sizeof(int));
// Assign pointers inside double pointer of matrix enough memory for vector of size n
for ( int i = 0; i < n; ++i ) {
*(matrix + i) = (int *) malloc(n * sizeof(int));
}
// Call fill_matrix function to fill our matrix from cmd line args
fill_matrix(matrix, n, argv);
// Assign total to the return of our sum_diag_matrix function
int total = sum_diag_matrix(matrix, n);
// Output our total
printf("%i\n", total);
// Return 0 to signal script running correctly
return 0;
}
// Fill matrix function fills the matrix of passed size n from passed array
void fill_matrix(int **matrix, int n, char **arr) {
// Initialize element integer to keep track of what element we're on
int element = 0;
// Nested loop iterates over matrix, filling out the values from the given array
for ( int i = 0; i < n; ++i) {
for ( int j = 0; j < n; ++j) {
*(*(matrix + i) + j) = atoi(arr[element + 2]);
printf("%i\n", *(*(matrix + i) + j));
element++;
}
}
// Return nothing for void
return;
}
// Sum diag matrix function sums the main diagonal of the matrix passed of passed size n
int sum_diag_matrix(int **matrix, int n) {
// Initialize total to keep track of sum
int total = 0;
// Iterate over diagonal elements of matrix
for ( int i = 0; i < n; ++i) {
total += *(*(matrix + i) + i);
}
// Return total sum
return total;
}
I'm new to pointers and such, so I'm trying to apply them everywhere, so potentially it could be that? Regardless I'm not too sure and I'm slightly stumped.
Any help would be appreciated!
-fsanitize=address is usually a great tool in debugging these kinds of problems. Even with the input you claim works, it spots the problem:
==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000018 at pc 0x000000401284 bp 0x7fff8ff3b540 sp 0x7fff8ff3b538
WRITE of size 8 at 0x602000000018 thread T0
#0 0x401283 in main /app/example.c:28
#1 0x7fd9788e9082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
#2 0x40111d in _start (/app/output.s+0x40111d)
0x60200000001c is located 0 bytes to the right of 12-byte region [0x602000000010,0x60200000001c)
allocated by thread T0 here:
#0 0x7fd978b72bbf in malloc (/opt/compiler-explorer/gcc-12.2.0/lib64/libasan.so.8+0xbbbbf)
#1 0x40122c in main /app/example.c:25
#2 0x7fd9788e9082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
SUMMARY: AddressSanitizer: heap-buffer-overflow /app/example.c:28 in main
Shadow bytes around the buggy address:
It says that at line 28, we're exceeding the memory allocated at line 25.
int **matrix = (int **) malloc(n * sizeof(int)); // Line 25
// Assign pointers inside double pointer of matrix enough memory for vector of size n
for ( int i = 0; i < n; ++i ) {
*(matrix + i) = (int *) malloc(n * sizeof(int)); // Line 28
}
Immediately, we see you use sizeof(int) and assign to int **, which is wrong. Fixed:
int **matrix = (int **) malloc(n * sizeof(int *));
(Also, you leak the memory on exit, which isn't a problem in systems with virtual memory like your desktop PC.)
Using the following macro would would also have caught the problem.
#define MALLOC(t, n) ( (t*)malloc(sizeof(t) * n) )
#define REALLOC(p, t, n) ( (t*)realloc(p, sizeof(t) * n) )
int **matrix = MALLOC(int*, n); // Warns if `int` is used instead of `int*`.
for ( int i = 0; i < n; ++i ) {
matrix[i] = MALLOC(int, n);
}
I'm trying to make function for dynamic arrays in C but I'm not sure, if I'm solving it right way. Could you help me?
Here is my code:
int resizeArray(int array_rows, int **array[])
{
int new_rows = array_rows + 16;
int *pointer;
pointer = realloc(**array, new_rows*sizeof(int));
if (!pointer) {
free(**array);
return 0;
}
**array = pointer;
free(pointer);
return new_rows; // return new rows counter
};
some code....
/* first array definition */
int *data;
int array_rows = 16;
data = (int*)malloc(array_rows*sizeof(int));
if array is full:
array_rows = resizeArray(array_rows,&data);
Thank you very much for your reviews and tips.
EDIT:
int resizeArray(int array_rows, int **array){
int new_rows = array_rows + 16;
int *pointer;
pointer = realloc(**array, new_rows*sizeof(*pointer));
if (!pointer) {
free(**array);
return 0;
}
**array = pointer;
free(pointer);
return new_rows; // return new rows counter
}
some code....
/* first array use */
int *data;
int array_rows = 16;
data = (int*)malloc(array_rows*sizeof(*data));
if array is full:
array_rows = resizeArray(array_rows,&data);
EDIT - CODE WITH STRUCTURES:
struct MyDynamicArray {
int maximumSize = 16;
int length = 0;
int* data;
}
/* first array definition */
MyDynamicArray.data = (int*)malloc(MyDynamicArray.maximumSize*sizeof(int));
int resizeArray(int array_rows, struct MyDynamicArray)
{
int new_rows = MyDynamicArray.maxSize * 2;
int *pointer;
pointer = realloc(MyDynamicArray.data, new_rows*sizeof(int));
if (!pointer) {
free(MyDynamicArray.data);
return 0;
}
MyDynamicArray.maxSize = new_rows; // return new rows counter
};
/* usage */
resizeArray(array_rows,MyDynamicArray);
WORKING SOLUTION:
resizeArray function definition:
/**
* resize array
* - its size resize X 2
* #param max_length
* #param data
* #return
*/
int resizeArray(int max_length, int **data)
{
data = (int *) realloc(**data, max_length * 2 * sizeof(int));
max_length *= 2;
return max_length; // return new rows counter
}
FIRST ARRAY DEFINITION
int *data_i;
int max_length = 16;
int *data;
data = (int *) realloc((void *) data_i, max_length * sizeof(int));
HERE IS USAGE:
int i = 0;
for(i = 0; i < 100; i++)
{
data[i] = i;
if(i == max_length)
{
max_length = resizeArray(max_length, &data);
}
}
I hope, it's right and will help to solve someones problem.
A few things:
It very well may work, but you have pointers going crazy. The second parameter can simply be int* array (and when you call it, there is no need to reference it). This way, the call to realloc will simply take array, as will the calls to free. (and you simply have array = pointer;
You're freeing the newly allocated memory. This will cause a segfault if you try to use the array after resizing. Remove that line, memory management should be the responsibility of function.
Also, in general, dynamic arrays will resize by doubling their size. realloc is expensive, but memory these days is cheap. This noted, it may be beneficial for you to always call resizeArray whenever you write to it, and pass it the length of the array plus the amount of elements you are writing. I'm not certain what you are going to do with your new, dynamic array, but it will likely save you many headaches if you maintain something like:
struct MyDynamicArray {
int maximumSize;
int length;
int* data;
}
There are so many iterations of MyDynamicArray it's hard to discern the final approach taken. One area where there seems to be confusion is over what am I reallocating?. Here, it appears you simply have one MyDynamicArray struct and an int array data member of that struct then needs reallocating. There are a number of approaches to doing this, but a clean approach is to #define an initial array size, allocate your data array to the initial defined size, then when the number of elements reaches initial size - 1 reallocate data.
An example taking the approach is as follows. A typedef to the struct has been created to cut down on typing. Look though the code, understand what it is doing where, and drop a comment if you have additional questions:
#include <stdio.h>
#include <stdlib.h>
#define ARRSZ 5
typedef struct
{
size_t size;
int* data;
} MyDynamicArray;
int *resizeArray (int **mdata, size_t newsize)
{
int *tmp = realloc (*mdata, newsize * sizeof(int));
if (!tmp)
return NULL;
*mdata = tmp;
return *mdata;
}
int main () {
MyDynamicArray *mda = malloc (sizeof (MyDynamicArray));
mda->size = ARRSZ;
mda->data = malloc (ARRSZ * sizeof (int));
int i = 0;
int newsize = 0;
for (i = 0; i < 50; i++)
{
if (i >= mda->size - 1)
{
newsize = 2 * mda->size;
if (resizeArray (&mda->data, newsize))
mda->size = newsize;
else {
fprintf (stderr, "error: reallocation failed at mda->size: %zd\n", mda->size);
exit (EXIT_FAILURE);
}
}
mda->data[i] = i;
}
printf ("\nElements of dynamic array:\n\n");
for (i = 0; i < 50; i++)
printf (" mda->data[%2d] : %d\n", i, mda->data[i]);
if (mda->data) free (mda->data);
if (mda) free (mda);
return 0;
}
Note: you can also assign a newpointer when you realloc if for some reason that is desirable. (e.g. int *newptr = resizeArray (&mda->data, newsize);) However, for simply resizing your array resizeArray (&mda->data, newsize); is sufficient.
output:
$ ./bin/mydynarray
Elements of dynamic array:
mda->data[ 0] : 0
mda->data[ 1] : 1
mda->data[ 2] : 2
mda->data[ 3] : 3
mda->data[ 4] : 4
mda->data[ 5] : 5
mda->data[ 6] : 6
mda->data[ 7] : 7
mda->data[ 8] : 8
mda->data[ 9] : 9
mda->data[10] : 10
mda->data[11] : 11
mda->data[12] : 12
mda->data[13] : 13
mda->data[14] : 14
mda->data[15] : 15
mda->data[16] : 16
mda->data[17] : 17
mda->data[18] : 18
mda->data[19] : 19
mda->data[20] : 20
mda->data[21] : 21
mda->data[22] : 22
mda->data[23] : 23
mda->data[24] : 24
mda->data[25] : 25
mda->data[26] : 26
mda->data[27] : 27
mda->data[28] : 28
mda->data[29] : 29
mda->data[30] : 30
mda->data[31] : 31
mda->data[32] : 32
mda->data[33] : 33
mda->data[34] : 34
mda->data[35] : 35
mda->data[36] : 36
mda->data[37] : 37
mda->data[38] : 38
mda->data[39] : 39
mda->data[40] : 40
mda->data[41] : 41
mda->data[42] : 42
mda->data[43] : 43
mda->data[44] : 44
mda->data[45] : 45
mda->data[46] : 46
mda->data[47] : 47
mda->data[48] : 48
mda->data[49] : 49
I am trying to sort an array of type void, just to brush up on my void pointers and function pointers, its been a while.
Here is my main c file:
#include "hawksort.h"
#include <stdlib.h>
#define ARR_LEN 10
int compareNumbers(void*,void*);
int main (int argc, char** argv)
{
int i =0;
int* arr = malloc(sizeof(int)*ARR_LEN);
for(i = 0; i < ARR_LEN; i++){
arr[i] = ARR_LEN - i;
printf("%d\n",arr[i]);
}
printf("here\n");
hawkBubbleSort(&compareNumbers, (void*)&arr, ARR_LEN);
return 0;
}
int compareNumbers(void* a, void* b)
{
printf("%d\n", *(int*)a);
printf("%d\n", *(int*)b);
if(*(int*)a > *(int*)b)
return 1;
if(*(int*)a < *(int*)b)
return -1;
if(*(int*)a == *(int*)b)
return 0;
return 0;
}
and here is my header file containing the sorting
int hawkBubbleSort(int (*comparisonAlgo)(void*,void*), void** a, int size){
int i = 0;
printf("%d\n",*(int*)a[0]);
printf("%d\n",*(int*)a[1]);
int swapped = 1;
while(swapped == 1){
swapped = 0;
for(i = 1; i < size; i++){
if(comparisonAlgo(a[i-1],a[i]) >= 1){
printf("Bigger\n");
void* temp = a[i];
a[i] = a[i-1];
a[i-1] = temp;
swapped = 1;
}
}
}
return 1;
}
The problem is, I am getting a segmentation fault when I try to access a[1]. a[0] returns the correct number of 10. I don't know where the issue is. I have a feeling its a problem with the type sizes and incrementing through the array, although it is possible I just messed up passing arr into the hawkBubbleSort function.
Sample output:
10
9
8
7
6
5
4
3
2
1
here
10
Segmentation fault (core dumped)
Your pointer usage is incorrect. You cannot simply pass a void** and peel it apart expecting it works as a universal sequence addressing mechanism.
To build an universal sorting routine taking an arbitrary sequence and a comparison function is considerably more tedious than a straight-forward type-based sort routine. For your sort function, the following should be provided.
The base address of the sequence being sorted.
The width (or stride) of any single sequence element.
The number of elements being sorted.
The comparison function.
The library function qsort(), not coincidentally, takes these very parameters to accomplish its task, and likewise so should you. Another utility that comes in handy is a function that swaps memory from two non-overlapping regions Armed with all the above, your task becomes simply the following. I strongly advise you review it compared to your code, in particular how the pointers passed to the comparator are adjusted based on element stride. As a bonus, I optimized the bubble-sort algorithm (an oxymoron if ever there was one):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARR_LEN 10
void memswp(void *a, void *b, size_t len)
{
unsigned char *lhs = a, *rhs = b;
size_t i=0;
for (i=0;i<len;++i)
{
unsigned char tmp = lhs[i];
lhs[i] = rhs[i];
rhs[i] = tmp;
}
}
int hawkBubbleSort(void* a, size_t len, size_t elemsiz, int (*cmp)(const void*,const void*))
{
unsigned char *p = a;
size_t i=0;
int swapped = 1;
while(swapped && len-- > 0)
{
swapped = 0;
for(i = 0; i < len; ++i)
{
if(cmp(p+(i*elemsiz), p+((i+1)*elemsiz)) > 0)
{
memswp(p+(i*elemsiz), p+((i+1)*elemsiz), elemsiz);
swapped = 1;
}
}
}
return 0;
}
int compareNumbers(const void* a, const void* b)
{
int const *lhs = a, *rhs = b;
int res = (*lhs < *rhs) ? -1 : (*rhs < *lhs);
printf("cmp(%d,%d) ==> %d\n", *lhs, *rhs, res);
return res;
}
int main (int argc, char** argv)
{
int *arr = malloc(ARR_LEN * sizeof(*arr)), i;
for(i = 0; i < ARR_LEN; i++)
{
arr[i] = ARR_LEN - i;
printf("%d ",arr[i]);
}
printf("\n");
hawkBubbleSort(arr, ARR_LEN, sizeof(*arr), &compareNumbers);
for(i = 0; i < ARR_LEN; i++)
printf("%d ",arr[i]);
printf("\n");
hawkBubbleSort(arr, ARR_LEN, sizeof(*arr), &compareNumbers);
for(i = 0; i < ARR_LEN; i++)
printf("%d ",arr[i]);
printf("\n");
return 0;
}
Output
10 9 8 7 6 5 4 3 2 1
cmp(10,9) ==> 1
cmp(10,8) ==> 1
cmp(10,7) ==> 1
cmp(10,6) ==> 1
cmp(10,5) ==> 1
cmp(10,4) ==> 1
cmp(10,3) ==> 1
cmp(10,2) ==> 1
cmp(10,1) ==> 1
cmp(9,8) ==> 1
cmp(9,7) ==> 1
cmp(9,6) ==> 1
cmp(9,5) ==> 1
cmp(9,4) ==> 1
cmp(9,3) ==> 1
cmp(9,2) ==> 1
cmp(9,1) ==> 1
cmp(8,7) ==> 1
cmp(8,6) ==> 1
cmp(8,5) ==> 1
cmp(8,4) ==> 1
cmp(8,3) ==> 1
cmp(8,2) ==> 1
cmp(8,1) ==> 1
cmp(7,6) ==> 1
cmp(7,5) ==> 1
cmp(7,4) ==> 1
cmp(7,3) ==> 1
cmp(7,2) ==> 1
cmp(7,1) ==> 1
cmp(6,5) ==> 1
cmp(6,4) ==> 1
cmp(6,3) ==> 1
cmp(6,2) ==> 1
cmp(6,1) ==> 1
cmp(5,4) ==> 1
cmp(5,3) ==> 1
cmp(5,2) ==> 1
cmp(5,1) ==> 1
cmp(4,3) ==> 1
cmp(4,2) ==> 1
cmp(4,1) ==> 1
cmp(3,2) ==> 1
cmp(3,1) ==> 1
cmp(2,1) ==> 1
1 2 3 4 5 6 7 8 9 10
cmp(1,2) ==> -1
cmp(2,3) ==> -1
cmp(3,4) ==> -1
cmp(4,5) ==> -1
cmp(5,6) ==> -1
cmp(6,7) ==> -1
cmp(7,8) ==> -1
cmp(8,9) ==> -1
cmp(9,10) ==> -1
1 2 3 4 5 6 7 8 9 10
Best of luck.
I've noticed several severe mistakes in you code:
the way you pass compareNumbers. a function pointer of a function should be the name itself. you if you pass &compareNumbers, you are passing int (**)(void*,void*), which i don't think you want it.
the implmentation of compareNumbers show me that you still want to sort int in this case, but you want to make you sorting function generic. however, your sorting function has no reflection of that. so to fix it, you should have your sorting function takes another parameter, which should be the element size of the array. so the result prototype of the function should be:
int hawkBubbleSort(int (*comparisonAlgo)(void*,void*), void* arr[], int length, size_t elem_size);
the way you pass in the array. your casting is wrong. it should be (void **)arr.
I think you want the address to this int array pointer, which would be (void**) &arr.
This will pass the array by reference, and it has to be a double pointer because an array in C is already a pointer.
There is a very important rule to follow when working with void pointers: never dereference them.
The reason for this is that whenever you do pointer arithmetic in C, what happens behind the scene is that the compiler, knowing the size of the type you're working on, will replace an access like this:
int* anArray = calloc(5, sizeof(int));
int i = anArray[2]; // which, is the same as *(anArray + 2);
with the actual proper offset needed to get to that variable:
int i = anArray + 2*sizeof(int);
But if we're working with void*, the compiler cannot know the size of the type stored in the array! It will therefore move by 1 byte, the smallest memory increment.
The solution is to always cast void* to a variable with the correct type before dereferencing it.
In your case:
int hawkBubbleSort(int (*comparisonAlgo)(void*,void*), void** a, int size){
int i = 0;
int** array = (int**)a;
printf("%d\n",*(int*)array[0]);
printf("%d\n",*(int*)array[1]);
int swapped = 1;
while(swapped == 1){
swapped = 0;
for(i = 1; i < size; i++){
if(comparisonAlgo(array[i-1],array[i]) >= 1){
printf("Bigger\n");
int* temp = array[i];
array[i] = array[i-1];
array[i-1] = temp;
swapped = 1;
}
}
}
Edited with original snippet.
I am trying to malloc a char to have rows and columns with one letter in each cell. Something similar to int x[i][j] where I have i*rows and j*columns. Basically I want to make this:
|
1
222
33333
4444444
I tried with this code but it gives me an error: assignment makes an integer from pointer without a cast
A=(char**) malloc (5*sizeof(char*));
for(i=0;i<N+2;i++)`{
A[i]=(char*) malloc(7*sizeof(char));
}
for(i=0;i<3;i++){
for(j=0;j<7;j++){
left=3;
right=3;
if((j>=left)&&(j<=right)){
A[i][j]=i;
}
}
left--;
right++;
}
I would go with different approach:
#define STEPS 5
#define ARRAY_SIZE STEPS*STEPS
The size of the array in your case can be easily calculated by the formula above.
Now, you just need to allocate fixed size of bytes, and fill it. That's it. Even more, the version below will simply out-beat your version in simplicity and performance.
int i, j;
char *array;
array = malloc(ARRAY_SIZE);
for (i = 0; i < STEPS; i++)
for (j = 0; j < (i * 2 + 1); j++)
*(array + i * STEPS + j) = i + 1;
Proof.
This compiles fine for me, as long as I add this around your code snippet; note that "A" was declared as being of type "char **". It won't work if you write, say "char A[][]".
#include <stdlib.h>
int main() {
const int N = 10;
int i, j, left, right;
char **A;
/* your code */
return 0;
}
I have created a 2 d array which reads as follows
int i,j,lx,ly;// lx,ly are the row and column respectively
double** a;
a=(double**) malloc((lx+2)*sizeof(double));
a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double));
assert(a[0]);
for(i=1;i<lx+2;i++)
{
a[i]=a[i-1]+i*(ly+2);
}
// I allocate a value of 0 to all the elements in this array as below
for(i=0;i<(lx+2)*(ly+2);i++)
{
a[i]=0;
}
// I print out all my elements below
for(i=0;i<(lx+2)*(ly+2);i++)
{
printf("position %d values %d\n",i,a[i]);
}
// When I see the output , it shows me a junk value at one particular position 13. I am unable to figure that out .. ALso kindly tell me how to access rows and columns like Eg to acces 7 th column row 0 and 5th row 6 th column in terms of lx, ly as shown in my code
Your approach is definitely heading in the right general direction.
I think this:
a=(double**) malloc((lx+2)*sizeof(double));
would normally be:
a = malloc(lx * sizeof(double *));
And then without the contiguity requirement, this:
a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double));
in most programs would look like:
a[0] = malloc(ly * sizeof(double));
And finally, that last line needs to be in a loop that assigns each a[i] with it's own malloc'ed space.
However, that won't create contiguous memory. To do that you will need to do that big allocation and then divide it up for the row vector. So, instead of the second malloc in a loop, perhaps something like:
double *t = malloc(lx * ly * sizeof(double));
for (i = 0; i < lx; ++i)
a[i] = t + i * ly;
Putting it all together:
#include <stdio.h>
#include <stdlib.h>
void arrayDemo(int lx, int ly)
{
double **a;
int i, j;
a = malloc(lx * sizeof(double *));
double *t = malloc(lx * ly * sizeof(double));
for(i = 0; i < lx; ++i)
a[i] = t + i * ly;
for(i = 0; i < lx; ++i)
for(j = 0; j < ly; ++j)
a[i][j] = i*100 + j;
for(i = 0; i < lx; ++i) {
for(j = 0; j < ly; ++j)
printf(" %4.0f", a[i][j]);
printf("\n");
}
}
int main(int ac, char **av)
{
arrayDemo(atoi(av[1]), atoi(av[2]));
return 0;
}
$ cc -Wall all.c
$ ./a.out 4 7
0 1 2 3 4 5 6
100 101 102 103 104 105 106
200 201 202 203 204 205 206
300 301 302 303 304 305 306
This code allocates a 10 by 5 contiguous block of memory, initializes it with incrementing doubles, and then prints the values indexed by x and y:
#include "2d.h"
int main(void){
unsigned int x,y;
const unsigned int width = 10;
const unsigned int height = 5;
//we need an index into the x of the array
double * index[width];
//need the memory to store the doubles
unsigned int memorySizeInDoubles = width * height;
double * memory = malloc(memorySizeInDoubles * sizeof(double));
//initialize the memory with incrementing values
for(x = 0; x < memorySizeInDoubles; ++x){
memory[x] = (double) x;
}
//initialize the index into the memory
for(x = 0; x < width; ++x){
index[x] = memory + height * x;
}
//print out how we did
for(x = 0; x < width; ++x){
for(y = 0; y < height; ++y){
printf("[%u, %u]: Value = %f\n", x, y, index[x][y]);
}
}
free(memory);
return 0;
}
The 2d.h file should contain these lines:
#include <stdio.h>
#include <stdlib.h>
int main(void);
Note: The memory created is only contiguous for some definitions. The memory is logically contiguous, but not necessarily physically contiguous. If this memory is for a device driver for instance, malloc won't work.
Either you create a single dimension array
double my_array = malloc(sizeof(double) * size_x * sizeof(double) * size_y);
which you will access by
(get position x=28, y=12)
my_array[12 * size_x + 28];
or you create a 2d array like you do, but you access it with
double **my_array = (double**) malloc(15 * sizeof(double));
for(int i = 0 ; i < 25; i++)
{
my_array[i] = (double*) malloc(30 * sizeof(double));
for (int j = 0 ; j < 12; j++)
{
my_array[i][j] = 1.2;
}
}
double my_double = my_array[12][28];
In C, to have one chunk of contiguous memory, you need one malloc(), or have a statically allocated array. Since you want dynamic memory, you will need malloc(). Since you need everything to be contiguous, you will need only one call to it.
Now, what should the call look like? If I understood you correctly, you need lx times ly values, each with size sizeof(double), so you need lx*ly*sizeof(double) bytes to be allocated.
Digression: I prefer writing my malloc() calls as follows:
#include <stdlib.h> /* for malloc's prototype */
T *pt; /* for any type T */
size_t n; /* need n objects of type T */
pt = malloc(n * sizeof *pt);
Using sizeof with sizeof *pt instead of sizeof(T) offers an advantage that if the type of pt changes, you don't need to change the malloc() call. Not casting the result of malloc() is nice because then the whole malloc() call is type-agnostic, and is easier to type and read. Be sure to #include <stdlib.h> though.
So, to allocate space for n doubles, you can do:
double *pd = malloc(n * sizeof *pd);
if (pd != NULL) {
/* malloc succeeded */
} else {
/* malloc failed */
}
Now, after allocating memory, you need to be able to index it. Let's say you have lx == 2 and ly == 3. Your memory looks like:
+---+---+---+---+---+---+
pd: | 0 | 1 | 2 | 3 | 4 | 5 |
+---+---+---+---+---+---+
pd[0], pd[1] and pd[2] are the double values corresponding to the first row, pd[3] to pd[6] are the double values corresponding to the second row. You should be able to generalize this observation to translate a given x,y index pair to one number that indexes into your pd array properly.