summarizing array of void * values - c

#include <stdio.h>
#include <stdlib.h>
#define LEN 5
#define sum_mac(func,type)\
void* func (void* arr, int size)\
{\
int i;\
type *sum = (type*)malloc(sizeof(type));\
if(sum == NULL)\
{\
printf("Error\n");\
exit(1);\
}\
*sum = 0;\
for(i = 0; i<size ; i++)\
{\
*sum = *sum + *((type*)arr[i]);\
}\
return sum;\
}\
sum_mac(int_sum,int);
void *summary(void* arr, int size, void *(*func)(void*, int))
{
if (func == NULL)
return NULL;
return (*func)(arr, size);
}
int main()
{
int arr[] = { 1,2,3,4,5 };
int *sum = summary(arr, LEN, int_sum(arr, LEN));
printf("the sum is: %d ", *sum);
free(sum);
return 0;
}
I get the following error when I try to compile this code:
Error LNK2019 unresolved external symbol _int_sum referenced in function _main
When I searched possible causes for this problem I got that "a reference to a function or variable that the linker can't resolve, or find a definition for".
Can someone help me find the problem.

There is (at least) three problems:
You included the macro instanciation in the macro itself, change:
}\
sum_mac(int_sum,int);
to:
}
sum_mac(int_sum,int);
Thus sum_mac is not part of the macro.
In the macro definition, change:
*sum = *sum + *((type*)arr[i]);
to:
*sum = *sum + ((type*)arr)[i];
In the first case, you try to use indexing on void pointer type, which is not possible (void has no size). So convert arr to pointer of the right type and use arithmetic on it.
--------------EDIT-----------
Change:
int *sum = summary(arr, LEN, int_sum(arr, LEN));
to
int *sum = summary(arr, LEN, int_sum);
In the first case you call summary with the third parameter value being the result of a call to int_sum, and that result if not a function pointer but the pointer to some int. You need to pass the function pointer.
Most of your problems are due to macro usage. This bypass the type system and fool the compiler, which is never a good idea.

Problem is here:
return sum;\
}\ <---------- Remove the \
sum_mac(int_sum,int); <---- also remove the ; because this is not a statement
void *summary(void* arr, int size, void *(*func)(void*, int))
Compiler thinks that sum_mac(int_sum,int); is part of the macro definition because \ at the end of line concatenates lines. That is why sum_mac(int_sum,int); is never called.
However, this reveals another problem with operator precendence on line:
*sum = *sum + *((type*)arr[i]);\
Array access [i] has higher precedence than cast (type*), so you are trying to access void array which won't work. Also the last dereference is pointless. Line should be changed to:
*sum = *sum + ((type*)arr)[i];\
There is also third problem: You are passing calling int_sum too early. Function expects function pointer so you should only pass the pointer:
int *sum = summary(arr, LEN, int_sum); // Only pass int_sum
You should make sure that you have enabled all warnings on the compiler, since this is an error that compiler could warn you about.

The other problem is here:
int *sum = summary(arr, LEN, int_sum(arr, LEN));
The third argument of summary should be a function pointer, but int_sum(arr, LEN) is not a function pointer but it is the result of the int_sum function.
You need to write this:
int *sum = summary(arr, LEN, int_sum);

You don't declare the function you call anywhere, so the linker doesn't know what to do.
That being said, putting whole functions inside macros is not a good idea, nor to malloc single items. And the code *sum = *sum + *((type*)arr[i]); goes wildly out of bounds, because you didn't allocate an array, but use it as if it was one.
I would rewrite this from scratch. This is what you can do instead:
#include <stdio.h>
#include <stdlib.h>
int int_sum (size_t size, int arr[size])
{
int sum = 0;
for(size_t i=0; i<size; i++)
{
sum += arr[i];
}
return sum;
}
float float_sum (size_t size, float arr[size])
{
float sum = 0.0f;
for(size_t i=0; i<size; i++)
{
sum += arr[i];
}
return sum;
}
#define sum_array(arr) _Generic((arr[0]), \
int: int_sum, \
float: float_sum) (sizeof(arr)/sizeof(arr[0]), arr)
int main (void)
{
int arr[] = { 1,2,3,4,5 };
int sum = sum_array(arr);
printf("int, the sum is: %d\n", sum);
float farr[] = {1.0f, 2.0f, 3.0f};
printf("float, the sum is: %f\n", sum_array(farr));
return 0;
}
Which can be made even more generic, even without involving function pointers:
#define do_stuff(arr, stuff) _Generic((arr[0]), \
int: int_##sum, \
float: float_##sum) (sizeof(arr)/sizeof(arr[0]), arr)
int main (void)
{
int arr[] = { 1,2,3,4,5 };
int sum = do_stuff(arr, sum);
printf("int, the sum is: %d\n", sum);
float farr[] = {1.0f, 2.0f, 3.0f};
printf("float, the sum is: %f\n", do_stuff(farr, sum));
return 0;
}

Related

Cast void pointer to double without knowing its type in C

I need to write a function which takes as parameters a void pointer (representing an array) and an integer which represents the length of the array. In the function, I need to cast this void pointer into a double one. The problem is that the void pointer can represent an array of integers or floats or doubles.
So the following is obviously not working in case the void pointer represents an array of integers or floats:
void foo(void *v,int n){
double *values;
values=(double*)v;
for(i=0;i<n;i++)
printf("%f\n",values[i]);
}
so this will print the correct output:
foo((double[]){1,2,3,4},4);
and this will print a wrong output:
foo((int[]){1,2,3,4},4);
foo((float[]){1,2,3,4},4);
So... can I correctly cast the void pointer to a double one only knowing that it can be an array of integers or floats or doubles? And is it necessary to have the length of the array or I can calculate it somehow?
P.s. without using callbacks
can I correctly cast the void pointer to a double one only knowing that it can be an array of integers or floats or doubles?
No, you cannot. You need to pass the type information somehow.
And is it necessary to have the length of the array or I can calculate it somehow?
It's necessary to pass the length.
You can "hide" the information inside a struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum etype { INTEGER, FLOAT, DOUBLE };
struct data {
void *values;
size_t n;
enum etype type;
};
void foo(struct data *x) {
int *xd = x->values;
float *xf = x->values;
double *xg = x->values;
for (int k = 0; k < x->n; k++) {
switch (x->type) {
default: printf("%g ", xg[k]); break;
case FLOAT: printf("%f ", xf[k]); break;
case INTEGER: printf("%d ", xd[k]); break;
}
}
puts("");
}
int main(void) {
struct data x;
x.values = malloc(4 * sizeof(int));
((int*)(x.values))[0] = 42;
((int*)(x.values))[1] = -1;
((int*)(x.values))[2] = 0;
((int*)(x.values))[3] = 999;
x.n = 4;
x.type = INTEGER;
foo(&x);
x.values = calloc(4, sizeof(float));
x.type = FLOAT;
float tmp = 3.14159;
memcpy(((float*)(x.values))+1, &tmp, sizeof (float));
foo(&x);
free(x.values);
x.values = calloc(4, sizeof(double));
x.type = DOUBLE;
((double*)(x.values))[2] = 2.7182818;
foo(&x);
free(x.values);
}
See code running on ideone

C - Copying array in other array as output argument

I am trying understand how pointers works in C. I am trying a simple case where an array, and a pointer to array are the arguments of a function which will copy the elements of the first one in the second one.
I have written this code
#include <stdio.h>
#define TAM 32
typedef int TablaArray[32];
void copyArray(TablaArray, TablaArray*, int);
void main(){
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++){
printf("%d - %d\n", t1[i], t2[i]);
}
}
void copyArray(TablaArray t1, TablaArray *t2, int tam){
for(int i = 0; i<tam-1; i++){
printf("%d\n", t1[i]);
*t2[i] = t1[i];
}
}
I am expecting to get something like this with the printf expression:
1 - 1
2 - 2
3 - 3
4 - 4
But definitely I don't know the way... I have been looking in stackoverflow and because I am sure this trivial question is already answered... but I didn't find it...
You need to make sure you are passing two int pointers pointing to both arrays. In your code only one of the arguments is a pointer. The code below should make it more clear:
#include <stdio.h>
void copyArray(int * arr1, int * arr2, int size);
int main(void)
{
int t1[] = {1,2,3,4};
int t2[4];
copyArray(t1, t2,4);
for(int i = 0; i <= 3; i ++)
{
printf("%d - %d\n", t1[i], t2[i]);
}
return 0;
}
void copyArray(int * arr1, int * arr2, int size)
{
for(int i = 0; i < size; i++)
{
printf("%d\n", arr1[i]);
arr2[i] = arr1[i];
}
return;
}
Edit: in what you have written, a TablaArray * is a pointer to an array of 32 ints, while you need an int *
typedef int TablaArray[32];
is bad practice
The problem is connected with array to pointer decay and then with pointer arithmetics:
Pointer decay means that if you pass an array-object of type int x[32] as argument to a function, then it "decays" to a pointer like int *, which points to the first element of the integer array. So be aware that if you pass an int x[32]-object, it's actually passed by reference (the array is not copied) and you may alter the contents of the array in the function.
Now pointer arithmetics:
Incrementing a pointer (or accessing an array through array subscripting) implicitly does pointer arithmetics, and the number of bytes added to the initial value depends on the type of the object to which the pointer points:
typedef int Array10[10];
Array10 arr = { 1,2,3,4,5,6,7,8,9,0 };
int *x = arr; // arrayOfInts decays to a pointer; x points to the &arr[0]
x++; // in terms of bytes, x is incremented by sizeof(int) bytes
int i = x[3]; // gets the int-value on the address of x + 3*sizeof(int)
Array10 *arr10ptr = arr;
arr10ptr++; // in terms of bytes, x is incremented by sizeof(Array10) bytes, which is 10*sizeof(int)
arr10ptr[3]; // 3*sizeof(Array10), i.e. 3*10*sizeof(int)
Now it should be clear why a function parameter being declared as a pointer to an array of int[32] behaves different from a function parameter being declared as an int[32].
So you could correct your program as follows, now knowing that TablaArray t2 will be a reference to the underlying array anyway:
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
Hope it helps.
Compile with warnings enabled. If you used gcc -Wall -Werror, you would get the following errors:
luis.c:10:6: error: return type of ‘main’ is not ‘int’ [-Werror=main]
void main(){
^~~~
luis.c: In function ‘main’:
luis.c:15:19: error: passing argument 2 of ‘copyArray’ from incompatible pointer type [-Werror=incompatible-pointer-types]
copyArray(t1, t2,4);
^~
luis.c:8:6: note: expected ‘int (*)[32]’ but argument is of type ‘int *’
void copyArray(TablaArray, TablaArray*, int);
^~~~~~~~~
cc1: all warnings being treated as errors
The first one is simple, it should be int main.
The second one is a bit harder to see exactly because you used a typedef. So your prototype is now
void copyArray(int *, int (*)[32], int);
With the second value being a pointer-to-array that by itself is a construct that is not used often.
Instead, you'd just need two pointers to int here, and the size of an array should perhaps use size_t instead:
void copyArray(int *, int *, size_t);
void copyArray(int *t1, int *t2, size_t n){
for (int i = 0; i < tam; i++) {
t2[i] = t1[i];
}
}
Finally, if you use a C99, C11 compiler, it could be nice to use the variable-length arrays arrays to tell that one of the parameters tell the sizes of the arrays; for that we need to reorder the parameters:
void copyArray(size_t, int[*], int[*]);
void copyArray(size_t n, int t1[n], int t2[n]) {
...
}
void copyArray(TablaArray, TablaArray, int); // prototype
void copyArray(TablaArray t1, TablaArray t2, int tam){
for(int i = 0; i<tam; i++){
printf("%d\n", t1[i]);
t2[i] = t1[i];
}
}
this will help
// much faster
#include <string.h>
void copyArray(TablaArray t1, TablaArray t2, int tam){
memcpy(t2, t1, sizeof(t1[0]) * tam);
}
In Your Copy function you were copying the same value of T1 to T2 on the Address Of T2. you can do it with out pointers but pointers helps you to refer the Address

'*' around parentheses : pointers

Consider this code for qsort:
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc(const void * a, const void * b)
{
return *(int*)a - *(int*)b;
}
int main()
{
int n;
printf("Before sorting the list is: \n");
for (n = 0; n < 5; n++)
{
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for (n = 0; n < 5; n++)
{
printf("%d ", values[n]);
}
return(0);
}
what does *(int*)a means specifically? It looks like a pointer to a pointer? why cant i do:
**a // dereferrencing twice would get the value, no?
or
*(int *a) // looks about the same. Also why do i need the int?
apologies if this question seemed obvious as I've been looking at this for hours now, and i still cant grasp why that '*' is wrapping around the bracket.
void* and const void* are used in C to stand in for a generic pointer of unknown type. qsort doesn't really know what it's sorting: the callback comparison function cmpfunc does that task. But C is statically-typed, so the callback function needs to have a specific prototype. That's where const void* is useful.
Of course, within your supplied cmpfunc, you know the type of object being sorted, so you are able to cast the const void* to your type. That is what (int*) is doing: it's a cast.
Technically you should cast to const int* instead:
return *(const int*)a - *(const int*)b;
Casting away const can cause you trouble.
A pointer to void can't be dereferenced. Therefore, in the given case it must have to cast to int * before dereferencing.
In *(int*)a, (int*) is casting a to pointer to int and then * outside the parenthesis dereferencing the value at that address.

C pass int array pointer as parameter into a function

I want to pass the B int array pointer into func function and be able to change it from there and then view the changes in main function
#include <stdio.h>
int func(int *B[10]){
}
int main(void){
int *B[10];
func(&B);
return 0;
}
the above code gives me some errors:
In function 'main':|
warning: passing argument 1 of 'func' from incompatible pointer type [enabled by default]|
note: expected 'int **' but argument is of type 'int * (*)[10]'|
EDIT:
new code:
#include <stdio.h>
int func(int *B){
*B[0] = 5;
}
int main(void){
int B[10] = {NULL};
printf("b[0] = %d\n\n", B[0]);
func(B);
printf("b[0] = %d\n\n", B[0]);
return 0;
}
now i get these errors:
||In function 'func':|
|4|error: invalid type argument of unary '*' (have 'int')|
||In function 'main':|
|9|warning: initialization makes integer from pointer without a cast [enabled by default]|
|9|warning: (near initialization for 'B[0]') [enabled by default]|
||=== Build finished: 1 errors, 2 warnings ===|
In your new code,
int func(int *B){
*B[0] = 5;
}
B is a pointer to int, thus B[0] is an int, and you can't dereference an int. Just remove the *,
int func(int *B){
B[0] = 5;
}
and it works.
In the initialisation
int B[10] = {NULL};
you are initialising anint with a void* (NULL). Since there is a valid conversion from void* to int, that works, but it is not quite kosher, because the conversion is implementation defined, and usually indicates a mistake by the programmer, hence the compiler warns about it.
int B[10] = {0};
is the proper way to 0-initialise an int[10].
Maybe you were trying to do this?
#include <stdio.h>
int func(int * B){
/* B + OFFSET = 5 () You are pointing to the same region as B[OFFSET] */
*(B + 2) = 5;
}
int main(void) {
int B[10];
func(B);
/* Let's say you edited only 2 and you want to show it. */
printf("b[0] = %d\n\n", B[2]);
return 0;
}
If you actually want to pass an array pointer, it's
#include <stdio.h>
void func(int (*B)[10]){ // ptr to array of 10 ints.
(*B)[0] = 5; // note, *B[0] means *(B[0])
//B[0][0] = 5; // same, but could be misleading here; see below.
}
int main(void){
int B[10] = {0}; // not NULL, which is for pointers.
printf("b[0] = %d\n\n", B[0]);
func(&B); // &B is ptr to arry of 10 ints.
printf("b[0] = %d\n\n", B[0]);
return 0;
}
But as mentioned in other answers, it's not that common to do this. Usually a pointer-to-array is passed only when you want to pass a 2d array, where it suddenly looks a lot clearer, as below. A 2D array is actually passed as a pointer to its first row.
void func( int B[5][10] ) // this func is actually the same as the one above!
{
B[0][0] = 5;
}
int main(void){
int Ar2D[5][10];
func(Ar2D); // same as func( &Ar2D[0] )
}
The parameter of func may be declared as int B[5][10], int B[][10], int (*B)[10], all are equivalent as parameter types.
Addendum: you can return a pointer-to-array from a function, but the syntax to declare the function is very awkward, the [10] part of the type has to go after the parameter list:
int MyArr[5][10];
int MyRow[10];
int (*select_myarr_row( int i ))[10] { // yes, really
return (i>=0 && i<5)? &MyArr[i] : &MyRow;
}
This is usually done as below, to avoid eyestrain:
typedef int (*pa10int)[10];
pa10int select_myarr_row( int i ) {
return (i>=0 && i<5)? &MyArr[i] : &MyRow;
}
In new code assignment should be,
B[0] = 5
In func(B), you are just passing address of the pointer which is pointing to array B. You can do change in func() as B[i] or *(B + i). Where i is the index of the array.
In the first code the declaration says,
int *B[10]
says that B is an array of 10 elements, each element of which is a pointer to a int. That is, B[i] is a int pointer and *B[i] is the integer it points to the first integer of the i-th saved text line.
Make use of *(B) instead of *B[0].
Here, *(B+i) implies B[i] and *(B) implies B[0], that is *(B+0)=*(B)=B[0].
#include <stdio.h>
int func(int *B){
*B = 5;
// if you want to modify ith index element in the array just do *(B+i)=<value>
}
int main(void){
int B[10] = {};
printf("b[0] = %d\n\n", B[0]);
func(B);
printf("b[0] = %d\n\n", B[0]);
return 0;
}
main()
{
int *arr[5];
int i=31, j=5, k=19, l=71, m;
arr[0]=&i;
arr[1]=&j;
arr[2]=&k;
arr[3]=&l;
arr[4]=&m;
for(m=0; m<=4; m++)
{
printf("%d",*(arr[m]));
}
return 0;
}
Using the really excellent example from Greggo, I got this to work as a bubble sort with passing an array as a pointer and doing a simple -1 manipulation.
#include<stdio.h>
void sub_one(int (*arr)[7])
{
int i;
for(i=0;i<7;i++)
{
(*arr)[i] -= 1 ; // subtract 1 from each point
printf("%i\n", (*arr)[i]);
}
}
int main()
{
int a[]= { 180, 185, 190, 175, 200, 180, 181};
int pos, j, i;
int n=7;
int temp;
for (pos =0; pos < 7; pos ++){
printf("\nPosition=%i Value=%i", pos, a[pos]);
}
for(i=1;i<=n-1;i++){
temp=a[i];
j=i-1;
while((temp<a[j])&&(j>=0)) // while selected # less than a[j] and not j isn't 0
{
a[j+1]=a[j]; //moves element forward
j=j-1;
}
a[j+1]=temp; //insert element in proper place
}
printf("\nSorted list is as follows:\n");
for(i=0;i<n;i++)
{
printf("%d\n",a[i]);
}
printf("\nmedian = %d\n", a[3]);
sub_one(&a);
return 0;
}
I need to read up on how to encapsulate pointers because that threw me off.
The argument of func is accepting double-pointer variable.
Hope this helps...
#include <stdio.h>
int func(int **B){
}
int main(void){
int *B[10];
func(B);
return 0;
}
In the function declaration you have to type as
VOID FUN(INT *a[]);
/*HERE YOU CAN TAKE ANY FUNCTION RETURN TYPE HERE I CAN TAKE VOID AS THE FUNCTION RETURN TYPE FOR THE FUNCTION FUN*/
//IN THE FUNCTION HEADER WE CAN WRITE AS FOLLOWS
void fun(int *a[])
//in the function body we can use as
a[i]=var

qsort does not work for double array

I try to sort an array of double value using qsort, but it doesn't seems to work. Wonder what has gone wrong here??
#include <stdio.h>
#include <stdlib.h>
static double compare (const void * a, const void * b)
{
if (*(double*)a > *(double*)b) return 1;
else if (*(double*)a < *(double*)b) return -1;
else return 0;
}
int main() {
int idx;
double* sum_least_square_err;
sum_least_square_err = (double*) malloc (2500*2500*sizeof(double));
sum_least_square_err[0] = 0.642;
sum_least_square_err[1] = 0.236;
sum_least_square_err[2] = 0.946;
idx = 3;
qsort(sum_least_square_err, idx, sizeof(sum_least_square_err), compare);
int i;
for (i=0; i<idx; i++){
fprintf(stderr,"sum_least_square_err[%d] = %.3f\n", i, sum_least_square_err[i]);
}
fprintf(stderr,"MAEE = %.3f\n", sum_least_square_err[idx/2]);
free(sum_least_square_err);
}
Result:
sum_least_square_err[0] = 0.642
sum_least_square_err[1] = 0.236
sum_least_square_err[2] = 0.946
MAEE = 0.236
Change:
static double compare (const void * a, const void * b)
to:
static int compare (const void * a, const void * b)
and change:
qsort(sum_least_square_err, idx, sizeof(sum_least_square_err), compare);
to:
qsort(sum_least_square_err, idx, sizeof(sum_least_square_err[0]), compare);
Note: you should have got an appropriate compiler warning about the first bug - are you compiling with gcc -Wall or equivalent, and if so are you taking notice of compiler warnings ? (If not then please take the hint and let the compiler catch problems such as this for you in future.)
I believe your error is at the line:
qsort(sum_least_square_err, idx, sizeof(sum_least_square_err), compare);
The problem is the 3rd parameter should be sizeof(double), that is, the size of an element of the array. You were instead passing the size of a pointer, which can be (and usually is) different from the size of the element.
For more information, see: http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/
Edit: And Paul R is right in his answer: The prototype of your comparison function is wrong. The prototype should be:
int ( * comparator ) ( const void *, const void * )
Last but not least, in your code:
if (*(double*)a > *(double*)b) return 1;
else if (*(double*)a < *(double*)b) return -1;
You are casting away the const. This has not consequence here, but still, this is bad form.

Resources