Related
I am trying to create a subtract function using pointers for 2d array but when I run it I get
expression must have pointer-to-object type but it has type "int"C/C++(142)
Can anybody explain why i'm getting this error and what is a better way around this?
this is my code
Function to read array
int *readMatrix(int *arr)
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
printf("row %d, col %d: ", i + 1, j + 1);
scanf("%d", &arr[i * 4 + j]);
}
}
printf("\n");
return arr;
}
Function to subtract 2 2d arrays
int *subM(int *arrA, int*arrB, int *arrC){
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
&arrC[i][j] = &arrA[i][j] - &arrB[i][j]; //code where I am getting error
}
}
return arrC;
}
Main Function
int main()
{
int arrA[3][4];
int arrB[3][4];
int arrC[3][4];
readMatrix(&arrA[3][4]);
readMatrix(&arrB[3][4]);
subM(&arrA[3][4],&arrB[3][4],&arrC[3][4]);
return 0;
}
I am new to StackOverflow. I'm sorry if I can't express myself that well, but I think I found the solution to your problem.
Let's look at this step-by-step.
When passing an array to a function, you do not need to write the subscripts.
That means that instead of this:
readMatrix(&arrA[3][4]);
Just write this:
readMatrix(arrA);
You can (actually, should) also remove the pointer operator (&) because when only the array name is used, it acts as a pointer automatically.
Let's now take a look at the definition of readMatrix.
int *readMatrix(int *arr)
Using pointers for multi-dimensional arrays is okay, but the compiler would spit out a lot of warnings.
The most standard way is using subscripts in the definition of the function:
int *readMatrixStandard(int arr[3][4])
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
printf("row %d, col %d: ", i + 1, j + 1);
scanf("%d", &arr[i][j]);
}
}
printf("\n");
return arr;
}
The subscripts in subM
For your case, there are two ways to access a multi-dimensional array.
Either tell the compiler that this function takes an multi-dimensional array:
Instead of this:
int *subM(int *arrA, int*arrB, int *arrC)...
Do this:
int *subM(int arrA[3][4], int arrB[3][4], int arrC[3][4])...
The code would then look something like this:
int *subMMultiDimension(int arrA[3][4], int arrB[3][4], int arrC[3][4]){
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
arrC[i][j] = arrA[i][j] - arrB[i][j]; //code where I am getting error
printf("%5d", arrC[i][j]);
}
puts(""); // for newline
}
return arrC;
}
Or use some pointer magic that is exclusive to C/C++ :) (not to be combined with the solution above)
Instead of this:
int *subM(int *arrA, int*arrB, int *arrC){
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
&arrC[i][j] = &arrA[i][j] - &arrB[i][j]; //code where I am getting error
}
}
return arrC;
}
Try this:
int *subM(int *arrA, int *arrB, int *arrC){
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
arrC[i * 4 + j] = arrA[i * 4 + j] - arrB[i * 4 + j]; //code where I am getting error
}
}
return arrC;
}
Use one of the ways, but the first one seems to be more standard because the compiler doesn't throw warnings on the first one.
Return value
You probably see where this is going. I'm just slapping on the code now.
Instead of:
return arr;
return arrC;
I prefer this for less warnings:
return arr[0];
return arrC[0];
The reason is simple. It points pratically to the same address, but it lets the compiler keep the mouth shut.
I think that this was it. The final code would look like this:
#include <stdio.h>
int * readMatrixStandard(int arr[3][4])
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
printf("row %d, col %d: ", i + 1, j + 1);
scanf("%d", &arr[i][j]);
}
}
printf("\n");
return arr[0];
}
int * subMMultiDimension(int arrA[3][4], int arrB[3][4], int arrC[3][4])
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
//printf("row %d, col %d: ", i + 1, j + 1);
arrC[i][j] = arrA[i][j] - arrB[i][j]; //code where I am getting error
printf("%5d", arrC[i][j]);
}
puts(""); // for newline
}
return arrC[0];
}
int main(void) // I recommend to always write void here if you are not using
// an old compiler
{
int arrA[3][4];
int arrB[3][4];
int arrC[3][4];
readMatrixStandard(arrA);
readMatrixStandard(arrB);
subMMultiDimension(arrA,arrB,arrC);
return 0;
}
Compiles nicely without warnings.
These code snippets are just my recommendations. If you want to know the most standard way to do something in C, you will probably have to look it up. A good book is also recommended. For instance, I learnt C with C Primer Plus by Stephen Prata. A great book with a lot of examples and illustrations to help you understand the situation.
Sorry again for my English. Guess there is still a long way to go.
If I missed anything or made a mistake somewhere, please let me know.
Edit: It's Stephen Prata, not Stephan ;)
By definition of the subscript operator [], the expression
A[B]
is equivalent to:
*(A + B)
Therefore,
A[B][C]
is equivalent to:
*( *(A+B) + C )
If you apply this to the line
&arrC[i][j] = &arrA[i][j] - &arrB[i][j];
it is equivalent to:
&*( *(arrC+i) + j ) = &*( *(arrA+i) + j ) - &*( *(arrB+i) + j );
The expression
&*( *(arrC+i) + j ) )
is invalid, for the following reason:
The sub-expression
*(arrC+i)
has type int, because dereferencing an int * yields an int. Therefore, the sub-expression
*(arrC+i) + j
will also evaluate to an int.
After evaluation that sub-expression, you then attempt to dereference that int using the * operator, which is illegal. Only pointer types can be dereferenced.
The sub-expressions
*( *(arrA+i) + j )
and
*( *(arrB+i) + j )
have exactly the same problem. You are also dereferencing an int in both of these expressions.
The actual problem is that you declared the function subM with the following parameters:
int *subM(int *arrA, int *arrB, int *arrC)
In C, arrays are usually passed to functions by passing a (possibly decayed) pointer to the first element of the (outer) array.
The parameter type int * would therefore be correct if you were passing 1D arrays to the function, but it is incorrect for 2D arrays. This is because a pointer to the first element of the outer array of a 2D int array has the type int (*)[4] in your case, i.e. a pointer to a 1D array of 4 int elements. However, you are instead passing a pointer to a single int object (not an array), so you are passing the wrong type of pointer.
Therefore, you should change the parameter types to the following:
int *subM( int (*arrA)[4], int (*arrB)[4], int (*arrC)[4] )
It may be clearer to write this the following way:
int *subM( int arrA[3][4], int arrB[3][4], int arrC[3][4] )
Both lines are equivalent, because arrays decay to pointers when used as function parameters.
Also, you should change the way you are calling the function. You should change the line
subM(&arrA[3][4],&arrB[3][4],&arrC[3][4]);
to:
subM( arrA[3], arrB[3], arrC[3] );
Due to array to pointer decay, this line is equivalent to:
subM( &arrA[3][0], &arrB[3][0], &arrC[3][0] );
Several issues ...
readMatrix uses an int *arr arg [correctly]. But, we want this to be compatible with sumM
sumM uses int * args, but tries to use dereference them using 2D array syntax.
In sumM, using (e.g.) &arr[i][j] is the address of the element and not its value [which is what we want].
In main, we're passing (e.g.) &arr[3][4]. This points past the end of the array, so this is UB (undefined behavior). We want to pass the start address of the array (e.g. arr or &arr[0][0]).
No need to pass back pointers to the resultant arrays because the caller passes in the addresses as args.
Here is the refactored code. It is annotated:
#include <stdio.h>
// Function to read array
#if 0
int *
readMatrix(int *arr)
#else
void
readMatrix(int arr[3][4])
#endif
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j) {
printf("row %d, col %d: ", i + 1, j + 1);
#if 0
scanf("%d", &arr[i * 4 + j]);
#else
scanf("%d", &arr[i][j]);
#endif
}
}
printf("\n");
#if 0
return arr;
#endif
}
// Function to subtract 2 2d arrays
#if 0
int *
subM(int *arrA, int *arrB, int *arrC)
#else
void
subM(int arrA[3][4], int arrB[3][4], int arrC[3][4])
#endif
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j) {
// printf("row %d, col %d: ", i + 1, j + 1);
// NOTE/BUG: we want to use the _values_ and _not_ the _addresses_ of the
// array elements
#if 0
&arrC[i][j] = &arrA[i][j] - &arrB[i][j];
#else
arrC[i][j] = arrA[i][j] - arrB[i][j];
#endif
}
}
// NOTE/BUG: since caller passed in the array, it knows where it is
#if 0
return arrC;
#endif
}
// Main Function
int
main(void)
{
int arrA[3][4];
int arrB[3][4];
int arrC[3][4];
// NOTE/BUG: doing (e.g.) &arrA[3][4] points past the _end_ of the 2D array
// and, so, is UB (undefined behavior) -- we want to pass the start address
#if 0
readMatrix(&arrA[3][4]);
readMatrix(&arrB[3][4]);
subM(&arrA[3][4], &arrB[3][4], &arrC[3][4]);
#else
readMatrix(arrA);
readMatrix(arrB);
subM(arrA, arrB, arrC);
#endif
return 0;
}
In the above code, I've used cpp conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Note: this can be cleaned up by running the file through unifdef -k
I am having trouble with assigning a return value of a function in heap part of the program. When I tried it in main, it gives an error "Segmentation fault". I believe it is because of the size of my array, which is the return value that I mentioned earlier because when I make my max_size smaller, the code works correctly (I think up to 45000). When I call the function in main, it uses the memory of stack, which is much smaller than memory of heap. Therefore I tried to call the function in heap and make the assignment in there but the compiler gave an error
deneme.c:6:15: error: initializer element is not constant
int *primes = listPrimes(1000000, &size);
After that I did some research and found out that stack is 8 MB memory, which is around 8000000 bytes. Then I estimated my array size as using the prime number theorem (up to 1000000, there are approximately 200000 primes) and sizeof(int) = 4 bit value so it gives 100000 bytes, which is much less than 8 MB. Therefore I have two questions in mind:
1. Why the compiler gives segmentation fault error although my array size is not too large?
2. How can I make the assigment in heap instead of main in order to avoid this problem?
Here is my code:
#include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int *listPrimes(int max_size, int *size) {
*size = 1;
int *result = malloc(*size * sizeof(int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc(max_size*sizeof(int));
for (i = 0; i < max_size; i++) {
nums[i] = i;
}
result[0] = 2;
int j = 2;
while (j < max_size) {
int k = j;
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
if (j == 2) {
j++;
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
else {
j += 2;
if (nums[j] != 0) {
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
}
}
return result;
}
and main function:
#include <stdio.h>
#include <stdlib.h>
#include "mathlib.h"
int size = 0;
int *primes = listPrimes(1000000, &size);
int main() {
printf("size = %d\n", size);
for (int i = 0; i < size; i++) {
printf("%d th prime is %d\n", i+1, primes[i]);
}
free(primes);
return 0;
}
Use unsigned int for j, k and max_size in listPrimes and it works properly . Below is the tested code:
// #include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int size = 0;
int *
listPrimes (unsigned int max_size, int *size)
{
*size = 1;
int *result = malloc (*size * sizeof (int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc (max_size * sizeof (int));
for (i = 0; i < max_size; i++)
{
nums[i] = i;
}
result[0] = 2;
unsigned int j = 2;
while (j < max_size)
{
unsigned int k = j;
while (j * k <max_size)
{
nums[j * k] = 0;
k++;
}
if (j == 2)
{
j++;
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
else
{
j += 2;
if (nums[j] != 0)
{
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
}
}
free(nums);
return result;
}
int
main ()
{
int *primes = listPrimes (1000000, &size);
printf ("size = %d\n", size);
for (int i = 0; i < size; i++)
{
printf ("%d th prime is %d\n", i + 1, primes[i]);
}
free (primes);
return 0;
}
nums is allocated to have max_size elements, so the index of its last element is max-size-1.
This loop:
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
may access an element with index j*k that equals max_size, thus writing beyond the end of the array. The loop should be limited to j*k < max_size.
Regarding your second question, the size of the result array is determined while finding the primes and is not readily calculable in advance, so it cannot easily be allocated prior to calling listPrimes. It could be done by evaluating the prime-counting function, but that is likely more than you want to do for this project.
I want to print kk[i].data[j] but it is not printing at all.
intarr_save_binary is returning 2. I expect to get 0.
int k = sizeof(kk) / sizeof(kk[0]); gives 0. I'm expecting to get 5.
Did I properly allocate the memory?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int len;
int *data;
}intarr_t;
#define MAX 5
intarr_t* intarr_create(unsigned int len) {
intarr_t* new_intarr = (intarr_t*)malloc(sizeof(intarr_t));
if (!new_intarr) return NULL;
new_intarr->data = (int*)malloc(len * sizeof(int));
new_intarr->len = len;
return new_intarr;
}
int intarr_save_binary(intarr_t* ia, const char* filename) {
if (!ia) return 1;
if (!ia->data) return 2;
FILE* f = fopen(filename, "w");
if (!f) return 3;
if (fwrite(&ia->len, sizeof(ia->len), 1, f) == 1) {
fprintf(f, "%d ", ia->len);
}
else {
return 4;
}
if (fwrite(ia->data, sizeof(ia->data), ia->len, f) == ia->len) {
fclose(f);
return 0;
}
else {
fclose(f);
return 5;
}
}
int main() {
intarr_t *ia = (intarr_t*)malloc(MAX*sizeof(intarr_t));
int i;
int j;
for (j = 0; j < MAX; j++) {
ia[j].len = j + 1;
}
for (j = 0; j < MAX; j++) {
ia[j].data = (int*)malloc(ia[j].len * sizeof(int));
}
for (j = 0; j < MAX; j++) {
for (i = 0; i < ia[j].len; i++) {
ia[j].data = (i + 1) * j;
}
}
char name[20] = "myfile.txt";
int d;
printf("%d \n", intarr_save_binary(ia, name));
intarr_t *kk;
kk = intarr_create(MAX);
int k = sizeof(kk) / sizeof(kk[0]);
printf("%d\n",k);
for (j = 0; j < k; j++) {
for (i = 0; i < kk[j].len; i++) {
printf("%d: %d\n", i, kk[j].data[i]);
}
printf("\n");
}
free(kk);
return 0;
}
intarr_save_binary is returning 2. I expect to get 0.
for (j = 0; j < MAX; j++) {
for (i = 0; i < ia[j].len; i++) {
ia[j].data = (i + 1) * j;
}
}
This zeroes ia[0].data on the very first pass through the double loop. (ia[0].data = (0 + 1) * 0 gives 0).
Thus ia->data is 0, and !ia->data is true, making the function return 2.
int k = sizeof(kk) / sizeof(kk[0]); gives 0. I'm expecting to get 5.
You obviously expect sizeof kk to give the total amount of memory allocated for kk.
And that is what you get, actually -- the total amount of memory allocated for intarr_t *, which is the type of kk at that point. That most likely results in 4 or 8, depending on your architecture. What it is not is whatever len * sizeof(int) resulted in when you called intarr_create(). As #BoPersson commented, if you allocate the memory yourself, you have to remember yourself how much you allocated.
The sizeof kk / sizeof kk[0] "trick" only works if kk actually is an array, i.e. if it has been declared as such within the scope of you using the sizeof operator on it so the compiler can "see" its size.
So, as you have an int and an int * in your struct kk[0], which together are very likely to require more memory than an intarr_t *, the integer division results in 0.
You might also take note that free() is not recursive. With free(kk), you are leaking all the memory you allocated for all the data members. For every malloc(), there needs to be a corresponding free(). (And it does matter even if the program ends right after that one free(), as not all operating systems can / will protect you from this error.)
I tried checking the addresses and its all looking normal, printing works and everything else works as well.
But when it tries to free the memory, the program crashes.
CODE:
#include <stdio.h>
#include <stdlib.h>
#define FIRST_DIM 2
#define SECOND_DIM 3
#define THIRD_DIM 2
#define TOTAL 12
void getNums(float* pArr);
void sortArr(float* pArr);
void printArr(float* pArr);
int main(void)
{
// Variable assignment
unsigned int i = 0, j = 0;
float*** pppArr = NULL;
// Memory assignment
pppArr = (float***)calloc(FIRST_DIM, sizeof(float**));
if (!(pppArr))
{
printf("Failed Allocating Memory..\n");
system("PAUSE");
return 1;
}
for (i = 0; i < FIRST_DIM; i++)
{
*(pppArr + i) = (float**)calloc(SECOND_DIM, sizeof(float*));
if (!(*(pppArr + i)))
{
printf("Failed Allocating Memory..\n");
system("PAUSE");
return 1;
}
}
for (i = 0; i < FIRST_DIM; i++)
{
for (j = 0; j < SECOND_DIM; j++)
{
*(*(pppArr + i) + j) = (float*)calloc(THIRD_DIM, sizeof(float));
if (!(*(*(pppArr + i) + j)))
{
printf("Failed Allocating Memory..\n");
system("PAUSE");
return 1;
}
printf("%p && %d\n", *(*(pppArr + i) + j), **(*(pppArr + i) + j));
}
}
printf("ASD");
// Getting numbers, sorting them and printing them out
getNums(**pppArr);
sortArr(**pppArr);
printArr(**pppArr);
// End of program
// Releasing memory
for (i = 0; i < FIRST_DIM; i++)
{
for (j = 0; j < SECOND_DIM; j++)
{
free(*(*(pppArr + i) + j));
}
}
for (i = 0; i < FIRST_DIM; i++)
{
printf("%p\n", *(pppArr + i));
free(*(pppArr + i));
}
free(pppArr);
system("pause");
return 0;
}
/* This function gets values for the given array from the user */
void getNums(float* pArr)
{
unsigned int i = 0;
for (i = 0; i < TOTAL; i++)
{
printf("Enter Number %d: ", i);
scanf("%f", pArr + i);
getchar();
}
}
/* This function prints out the given array */
void printArr(float* pArr)
{
unsigned int i = 0;
for (i = 0; i < TOTAL; i++)
{
printf("Number %d: %.2f\n", i, *(pArr + i));
}
}
/* This function sorts the given array from lowest to highest*/
void sortArr(float* pArr)
{
unsigned int i = 0, j = 0;
float temp = 0;
for (i = 0; i < TOTAL; i++)
{
for (j = 0; j < TOTAL - 1; j++)
{
if (*(pArr + j) > *(pArr + j + 1))
{
temp = *(pArr + j);
*(pArr + j) = *(pArr + j + 1);
*(pArr + j+ 1) = temp;
}
}
}
}
is there something im missing?
When you use pointers and dynamic allocation, the memory you allocate will most likely not be contiguous, but you will get separate memory areas for each allocation. That means when you treat it as one large contiguous memory area in your functions you exhibit undefined behavior.
An actual array, like
float arr[FIRST_DIM][SECOND_DIM][THIRD_DIM];
Now that will be contiguous.
See e.g. this old answer of mine for a more "graphical" explanation of the difference between arrays of arrays, and pointers to pointers.
This code is indexing out of bounds rather severely. The memory allocated for pppArr has three levels of indirection. It is not a multi-dimensional array (i.e., not an array of arrays), but is a pointer to an array of pointers to arrays of pointers. Three levels of indirection. There are 6 separate float slices, each with 2 contiguous elements (i.e., THIRD_DIM).
When calling getNums, sortArr, and printArr, you are passing **pppArr. This is equivalent to passing pppArr[0][0], which points to a single 2-element sequence of float values. The functions may only access THIRD_DIM elements, i.e. 2. Instead, they are trying to access 12 elements (i.e., TOTAL), which of course corrupts memory and leads to undefined behavior.
As far as I can tell, it looks like you're trying to access the storage as a single one-dimensional array. If so, then the easiest way to fix it is to eliminate 2 levels of indirection, and get rid of FIRST_DIM, SECOND_DIM, and THIRD_DIM, and just allocate a single, flat array with LENGTH elements. The pointer would have type float *.
So.. I have something like this. It is supposed to create arrays with 10, 20, 50 100 .. up to 5000 random numbers that then sorts with Insertion Sort and prints out how many comparisions and swaps were done .. However, I am getting a runtime exception when I reach 200 numbers large array .. "Access violation writing location 0x00B60000." .. Sometimes I don't even reach 200 and stop right after 10 numbers. I have literally no idea.
long *arrayIn;
int *swap_count = (int*)malloc(sizeof(int)), *compare_count = (int*)malloc(sizeof(int));
compare_count = 0;
swap_count = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
compare_count = 0;
swap_count = 0;
free(arrayIn);
}
}
}
EDIT: ok with this free(arrayIn); I get this " Stack cookie instrumentation code detected a stack-based buffer overrun." and I get nowhere. However without it it's "just" "Access violation writing location 0x00780000." but i get up to 200numbers eventually
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
arr[i] = (RAND_MAX + 1)*rand() + rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
I am sure your compiler told you what was wrong.
You are passing a long** to a function that expects a int* at the line
fill_array(&arrayIn, n);
function prototype is
void fill_array(int *arr, int n)
Same problem with the other function. From there, anything can happen.
Always, ALWAYS heed the warnings your compiler gives you.
MAJOR EDIT
First - yes, the name of an array is already a pointer.
Second - declare a function prototype at the start of your code; then the compiler will throw you helpful messages which will help you catch these
Third - if you want to pass the address of a simple variable to a function, there is no need for a malloc; just use the address of the variable.
Fourth - the rand() function returns an integer between 0 and RAND_MAX. The code
a[i] = (RAND_MAX + 1) * rand() + rand();
is a roundabout way of getting
a[i] = rand();
since (RAND_MAX + 1) will overflow and give you zero... If you actually wanted to be able to get a "really big" random number, you would have to do the following:
1) make sure a is a long * (with the correct prototypes etc)
2) convert the numbers before adding / multiplying:
a[i] = (RAND_MAX + 1L) * rand() + rand();
might do it - or maybe you need to do some more casting to (long); I can never remember my order of precedence so I usually would do
a[i] = ((long)(RAND_MAX) + 1L) * (long)rand() + (long)rand();
to be 100% sure.
Putting these and other lessons together, here is an edited version of your code that compiles and runs (I did have to "invent" a print_array) - I have written comments where the code needed changing to work. The last point above (making long random numbers) was not taken into account in this code yet.
#include <stdio.h>
#include <stdlib.h>
// include prototypes - it helps the compiler flag errors:
void fill_array(int *arr, int n);
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count);
void print_array(int *arr, int n, int *swap_count, int *compare_count);
int main(void) {
// change data type to match function
int *arrayIn;
// instead of mallocing, use a fixed location:
int swap_count, compare_count;
// often a good idea to give your pointers a _p name:
int *swap_count_p = &swap_count;
int *compare_count_p = &compare_count;
// the pointer must not be set to zero: it's the CONTENTs that you set to zero
*compare_count_p = 0;
*swap_count_p = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count_p, compare_count_p);
print_array(arrayIn, n, swap_count_p, compare_count_p);
swap_count = 0;
compare_count = 0;
free(arrayIn);
}
}
}
return 0;
}
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
// arr[i] = (RAND_MAX + 1)*rand() + rand(); // causes integer overflow
arr[i] = rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
void print_array(int *a, int n, int* sw, int *cc) {
int ii;
for(ii = 0; ii < n; ii++) {
if(ii%20 == 0) printf("\n");
printf("%d ", a[ii]);
}
printf("\n\nThis took %d swaps and %d comparisons\n\n", *sw, *cc);
}
You are assigning the literal value 0 to some pointers. You are also mixing "pointers" with "address-of-pointers"; &swap_count gives the address of the pointer, not the address of its value.
First off, no need to malloc here:
int *swap_count = (int*)malloc(sizeof(int)) ..
Just make an integer:
int swap_coint;
Then you don't need to do
swap_coint = 0;
to this pointer (which causes your errors). Doing so on a regular int variable is, of course, just fine.
(With the above fixed, &swap_count ought to work, so don't change that as well.)
As I told in the comments, you are passing the addresses of pointers, which point to an actual value.
With the ampersand prefix (&) you are passing the address of something.
You only use this when you pass a primitive type.
E.g. filling the array by passing an int. But you are passing pointers, so no need to use ampersand.
What's actually happening is that you are looking in the address space of the pointer, not the actual value the pointer points to in the end. This causes various memory conflicts.
Remove all & where you are inputting pointers these lines:
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
So it becomes:
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count, compare_count);
print_array(arrayIn, n, swap_count, compare_count);
I also note that you alloc memory for primitive types, which could be done way simpler:
int compare_count = 0;
int swap_count = 0;
But if you choose to use the last block of code, DO use &swap_count and &compare_count since you are passing primitive types, not pointers!