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.
Related
I was reading about function pointer. That it contains address of instructions. And there I encountered one question to find an element in array using function pointer. Here is the code.
#include <stdio.h>
#include <stdbool.h>
bool compare(const void* a, const void* b)
{
return (*(int*)a == *(int*)b);
}
int search(void* arr, int arr_size, int ele_size, void* x, bool compare(const void*, const void*))
{
char* ptr = (char*)arr; // Here why not int *ptr = (int*)arr;
int i;
for (i = 0; i < arr_size; i++)
{
if (compare(ptr + i * ele_size, x))
{
return i;
}
}
return -1;
}
int main()
{
int arr[] = { 2, 5, 7, 90, 70 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = 7;
printf("Returned index is %d ", search(arr, n, sizeof(int), &x, compare));
return 0;
}
In the search function char *ptr = (char*)arr; is used which is giving perfect answer = 2.
But when I have used int *ptr = (int*)arr; it gives -1 as answer.
Why is this? Can anyone explain this?
A char is the smallest addressable unit in any C program, and on most system it corresponds to a single byte. That treats the array as a generic sequence of bytes, and uses the ele_size to calculate the byte-position of each element with ptr + i*ele_size.
If you use int *ptr then the byte-position calculation will be wrong by a factor of sizeof(int) (typically 4), since the pointer arithmetic will be done in units of the base type (int instead of char).
The function search knows nothing about what is the type of elements of the array pointed to by the pointer arr of the type void *.
So casting the pointer to the type int * does not make a sense. If to do so then the expression ptr + i*ele_size where the pointer arithmetic is used will produce an incorrect result.
That it contains address of instructions
There is a subtle difference between normal (object) pointers and function pointers. It is not possible to access the single instructions of a function - they do not have the same length.
With other pointers the increment (arithmetic) is adapted to the type, whether as p[i] or p + i or *(p+i).
Side note: there still is int at the bottom of the call chain:
return (*(int*)a == *(int*)b);
#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;
}
I have coded a generic insertion sort in C, and it works really fine.
But, On my function of insertion sort, it gets a void** arr,
and on its signature it gets a void* arr, otherwise, it doesn't work.
Why is it so?
Do we have any other ways to code the insertion sort to be generic?
The Full code is here:
#include <stdio.h>
#include <malloc.h>
#define SIZE 10
int cmp(void* elm1, void* elm2);
void insertionSort(void* arr, int size);
int main()
{
int arr[] = {5, 8, 2, 3, 15, 7, 4, 9, 20, 13};
int arr2[] = {1};
int i;
for (i = 0; i < SIZE; i++)
printf("%d ", arr[i]);
printf("\n");
insertionSort(&arr, SIZE);
for (i = 0; i < SIZE; i++)
printf("%d ", arr[i]);
return 0;
}
void insertionSort(void** arr, int size)
{
int i = 1;
int j;
void* temp;
while (i < size)
{
if (cmp(arr[i], arr[i-1]) == -1)
{
temp = arr[i];
j = i - 1;
while (j >= 0 && cmp(arr[j], temp) == 1)
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
i++;
}
}
int cmp(void* elm1, void* elm2)
{
if ((int)elm1 == (int)elm2)
return 0;
else if ((int)elm1 > (int)elm2)
return 1;
else
return -1;
}
The code as it is, is undefined, because of multiple problems. It just happens to work, because on your system the size of the pointer is the same as the size of the type int.
You code will not compile without warnings (if you enable them). The function insertionSort and it's prototype must have the same type.
You should change the type in the function definition to
void insertionSort(void* arr, int size)
And then cast the pointer arr, to an appropriate type. Since this is a generic sort, like qsort(), the only realistic option is a cast to char*. This means you will also have to pass the size of the type into the function, so the pointer can be incremented correctly. This will require you to change the function drastically.
So, the function prototype should really be the same as qsort:
void Sort(void* arr, size_t size , size_t object_size , int(*)( const void* , const void* ))
The problem is that integers are not pointers, so your test array is of type *int or int[]. But in your function, you don't know that and you try to make your code work with pointers. So you expect * void[]. If you change your temp variable to int, you don't need the ** in the signature. The same way, if you want to keep the "generic" (as you call), you need an array of *int.
Basically, in C you cannot write a function working out of the box for both primary types and pointers. You need some tricks. Have a look at this stackoverflow, maybe it will help.
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
Today I tried to use const indentifier, but I find the const variable can still be modified, which confuses me..
Following is the code, in compare(const void *a, const void *b) function, I tried to modify the value that a is pointing to:
#include <stdio.h>
#include <stdlib.h>
int values[] = {40, 10, 100, 90, 20, 25};
int compare (const void *a, const void*b)
{
*(int*)a=2;
/* Then the value that a points to will be changed! */
return ( *(int*)a - *(int*)b);
}
int main ()
{
int n;
qsort(values, 6, sizeof(int), compare);
for (n = 0; n < 6; n++)
printf("%d ", values[n]);
return 0;
}
Then I also tried to change the value of a itself:
#include <stdio.h>
#include <stdlib.h>
int values[] = {40, 10, 100, 90, 20, 25};
int compare (const void *a, const void*b)
{
a=b;
return ( *(int*)a - *(int*)b);
}
int main ()
{
int n;
qsort(values, 6, sizeof(int), compare);
for (n = 0; n < 6; n++)
printf("%d ", values[n]);
return 0;
}
However, I found both of them works..
Can anyone explain to me why I need to use const in the parameter list of compare if they can still be changed?
It only works in this case because the pointer you're working against wasn't originally constant. Casting away constness and then modifying a value is undefined behaviour. UB means that the app can do anything from succeed to crash to make purple dragons fly out of your nostrils.
Its protecting you from silly mistakes, not when you try hard to make a mistake.
(int *)a when a is const something * is a bad practice, use (const int *)a instead.
a = b when a is const void * is ok because only the value pointed to is const. if you want both *a = x and a = x disallowed, declare a as const void * const.
Case 1: You are using a static cast to cast away the constness. You are violating the contract that was defined for the method.
Case 2: You are not changing the contents of a (which is const), but assigning the variable a which contains a const void pointer.
For practical implications: With case 1.) you could shoot yourself in the foot, in case a was not really pointing to a variable.
Suggestion: Cast away constness only if you know what you are doing.
Actually.
int compare (const void *a, const void*b);
Here there are 2 things you need to consider, the pointer and the memory location that the pointer is pointing to. The pointer is not constant but the memory location is.
If you would change the signature to:
int compare (const void *const a, const void *const void);
Then everything would be const. In your case you can change the pointer but not the value. So that your pointer can point to a different memory location.