Procedure and pointers C - c

im trying to make a procedure to find a maximum numbers out of 3, which i will assign later to another variable pointer in main program
int Maximum (int *a, int *b, int *c)
{
if (*a>=*b)
{
if (*a<*c)
{*a=*c;}
}
else
{
*a=*b;
if (*a<*c)
{*a=*c;}
}
return a;
}
compiler giving me error that "expected 'int*' but argument is of type 'int' "
so i changes that part to
int * Maximum (int *a, int *b, int *c)
but error sentence still same ?

First off, your original function is designed to return an int and you're returning a, which is an int pointer. Either return the int (*a), or change the function so it returns an int *.
However, based on your actual message:
expected 'int*' but argument is of type 'int'
and the fact you state you've made that change and still have the problem (note the word "argument" in the message), this indicates that the problem lies not with the return value but with the way you're passing the arguments to it.
You are actually passing int where the function expects int * and that's probably caused by you using something like:
int one = 3;
int two = 7;
int three = 42;
int maxOfThree = Maximum (one, two, three);
If you wanted to pass pointers to the function, you would need:
Maximum (&one, &two, &three);
(passing the pointers to the variables, not the values of them).
A better solution (more readable and with correct data types both going in to, and coming out of, the function) to your problem would probably be:
int Maximum (int a, int b, int c) {
if ((a > b) && (a > c))
return a;
if (b > c)
return b;
return c;
}

Related

Passing a multidimensional array of variable size

I'm trying to understand what "best practice" (or really any practice) is for passing a multidimensional array to a function in c is. Certainly this depends on the application, so lets consider writing a function to print a 2D array of variable size. In particular, I'm interested in how one would write the function printArry(__, int a, int b) in the following code. I have omitted the first parameter as I'm not exactly sure what that should be.
void printArry(_____, int a, int b){
/* what goes here? */
}
int main(int argc, char** argv){
int a1=5;
int b1=6;
int a2=7;
int a2=8;
int arry1[a1][b1];
int arry2[a2][b2];
/* set values in arrays */
printArry(arry1, a1, b1);
printArry(arry2, a2, b2);
}
The easiest way is (for C99 and later)
void printArry(int a, int b, int arr[a][b]){
/* what goes here? */
}
But, there are other ways around
void printArry(int a, int b, int arr[][b]){
/* what goes here? */
}
or
void printArry(int a, int b, int (*arr)[b]){
/* what goes here? */
}
Compiler will adjust the first two to the third syntax. So, semantically all three are identical.
And a little bit confusing which will work only as function prototype:
void printArry(int a, int b, int arr[*][*]);
This is not really an answer, but extended comment to the OP's comment question, "well you can pass the array without knowing the number of rows with this, but then how will you know when to stop printing rows?"
Answer: generally, you can't, without passing the array size too. Look at this 1-D example, which breaks the array size.
#include <stdio.h>
int procarr(int array[16], int index)
{
return array[index];
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100));
return 0;
}
Program output (although all elements initialised to 0):
768
That was undefined behaviour and there was no compiler warning. C does not provide any array overrun protection, except for array definition initialisers (although such initialisers can define the array length). You have to pass the array size too, as in
#include <stdio.h>
int procarr(int array[16], size_t index, size_t size)
{
if (index < size)
return array[index];
return -1; // or other action / flag
}
int main (void)
{
int arr[16] = {0};
printf("%d\n", procarr(arr, 100, sizeof arr / sizeof arr[0]));
return 0;
}
Program output:
-1

Sort three pointers without using selection sort

I'm new to C and am having a lot of trouble understanding how to utilize pointers in my code. I need to sort the addresses of three user-input integers in ascending order, using a separate sort function. I can't include any sort of selection sort or general-purpose sort, however.
EDIT: When I run the program, it gives me the addresses in descending order for some reason. I need to fix that.
Here's my code thus far:
#include <stdio.h>
#include <stdlib.h>
void sortThree(int * a, int * b, int * c);
int main(void)
{
int x, y, z;
printf("Please enter three variables: ");
scanf("%i %i %i",&x,&y,&z);
void sortThree(int * x, int * y, int * z);
printf("%u %u %u",&x, &y, &z);
return 0;
}
void sortThree(int * a, int * b, int * c)
{
int min, mid, max;
if (*a <= *b)
{
if (*a <= *c)
{
min = *a;
}
if (*b <= *c)
{
mid = *b;
max = *c;
}
else
{
mid = *c;
max = *b;
}
}
}
I'm sure it's something I'm overlooking or something but my brain just doesn't see it. Thanks in advance!
There are so many errors in this code it is hard to comment without re-writing it for you, and I won't. In addition to those mentioned above, you are using printf() to show integers by address instead of by value. You can't want to sort the addresses, or you would not have bothered to input any values. Also, why do you switch the format specifier bewteen int and unsigned int? It might not cause an error but it's plain sloppy.
In the sort function, you aren't even changing anything, you are throwing away the results on return. The reason it has given you the addresses in descending order, is because you haven't even sorted them, they are the order they were declared and pushed onto the stack. You are passing the pointers to printf() but telling it they are unsigned integers. The actual variable values are ignored.

How to have an array of functions that returns pointers of ints

When I try to compile the following line
int* x[](), (*y)();
I get the error "x declared as an array of functions of type int()"
You cannot really declare an array of functions, but you can have an array of function pointers, which will probably give you the same effect, because you can invoke them without explicit dereferencing.
The following will declare an array of 5 function pointers which return int*.
int* (*x[5])();
The website cdecl will let you play with various pointer declarations to see what they mean in English.
Here is the golden rule for reading C declarations, stolen from this old article.
Start at the variable name (or innermost construct if no identifier is
present. Look right without jumping over a right parenthesis; say what
you see. Look left again without jumping over a parenthesis; say what
you see. Jump out a level of parentheses if any. Look right; say what
you see. Look left; say what you see. Continue in this manner until
you say the variable type or return type.
When applied to the declaration above, we say:
x is an array of 5 pointers to functions returning pointer to int.
As SteveCox correctly commented below, we note that if we run into a type qualifier on the left hand side when following the above rule, it will describe the type to its left rather than its right. For example, the following declaration declares an array of 5 pointers to functions returning const pointer to int, not pointer to const int.
int* const (*x[5])();
Try this for an array of 2 function pointers.
#include <stdio.h>
int *first(void) { return NULL; }
int *second(void) { return NULL; }
int main(void) {
int *(*fx[2])(void);
fx[0] = first;
fx[1] = second;
/* ... */
if (fx[0]() == fx[1]()) {
printf("Calling both functions returns the same value.\n");
}
return 0;
}
A practical application might look like:
#include <ansi_c.h>
int add_(int, int);
int sub_(int, int);
int mul_(int, int);
int div_(int, int);
enum {
ADD,
SUB,
MUL,
DIV
};
int (*mathOps[4])(int, int);
int main(void)
{
int i;
mathOps[ADD]=add_;
mathOps[SUB]=sub_;
mathOps[MUL]=mul_;
mathOps[DIV]=div_;
for(i=ADD;i<=DIV;i++)
{
printf("results are: %d\n", mathOps[i](3, 3));
}
getchar();
return 0;
}
int add_(int a, int b)
{
return a + b;
}
int sub_(int a, int b)
{
return a - b;
}
int mul_(int a, int b)
{
return a * b;
}
int div_(int a, int b)
{
return a / b;
}

C a comparator of int for an array of pointers

I'm following LCTHW tutorial and I have a task to do.
This is the data structure:
typedef struct DArray {
int end;
int max;
size_t element_size;
size_t expand_rate;
void **contents;
} DArray;
I have declared a typedef:
typedef int (*DArray_compare) (const void *a, const void *b);
When I create a sorting function, I pass to it a DArray_compare, the problem is that I can't figure out how to do an example of this comparator.
I tried to do something like this:
int compare(const void *a, const void *b)
{
int i = (int)*a;
int k = (int)*b;
printf("%d %d\n", i, k);
return i - k;
}
But I get an error:
error: operand of type 'void' where arithmetic or pointer type is required int i = (int)*a;
The question is: without changing the struct and the typedef of the comparator, I want to create a comparator that compares int, how can I do it?
int i = *(int*)a;
// This one has more parens to make it really obvious what your intent is.
int k = *((int*)b);
The second line (k=) is easiest to explain cos of all the brackets. You can rewrite it as follows:
// Cast b from a pointer to a void into a pointer to an int.
int *X = (int*)b;
// k = "what X is pointing to" or "the contents of X"
int k = *X;
edit:
I think ralu's comment is suggesting you change all the void* to int* which is a much safer solution if you have that power.
typedef int (*DArray_compare) (const int *a, const int *b);
int compare(const int *a, const int *b)
{
int i = *a;
int k = *b;
...
A comparison function for use with bsearch() or qsort() from the standard C library for arrays of DArray structures might look like:
int compare(const void *a, const void *b)
{
const DArray *d1 = a;
const DArray *d2 = b;
if (d1->end < d2->end)
return -1;
else if (d1->end > d2->end)
return +1;
else if (d1->max < d2->max)
return -1;
else if (d2->max > d2->max)
return +1;
else
return 0;
}
Clearly, if you need to compare other fields, you can add those comparisons into the framework above quite easily. The general structure of the function is my recommended way of writing such comparators. You can add explicit casts to the assignment lines if you wish; C++ would require them, but C does not.
Note that your typedef is of minimal relevance to the comparator itself (though the comparator as a function pointer should match that typedef). It is the type that a comparator should have, but you can't use that typedef name when writing the function. You could use the typedef in the implementation of the sort function and in its declaration.
I observed in a couple of places that returning the difference of two signed int values as the result of the comparator leads to undefined behaviour.
In a comment to a now deleted answer, AR89 asked:
Instead of the subtraction an if statement would be safer?
Yes. Consider what happens if you have 16-bit int values and you compare -30,000 and +30,000; you've got signed overflow, and you might get a positive value back from your comparator, even though the first value is less than the second. Analogous situations can occur with 32-bit or 64-bit integers. They're relatively unlikely; if you know that your values are well within range, you'd be OK. But for general purpose code, you should do the piecewise comparison:
if (i < k)
return -1;
else if (i > k)
return +1;
else
return 0;
as it works regardless of the values of i and k. Also note that the if comparison works reliably for unsigned int types too, whereas subtraction really doesn't work then (the result is always zero or positive).

Why does C disallow an array return type?

Why is this valid in C
int * foo(int a,int b){
...
}
but this is invalid
int [] foo(int a,int b){
...
}
The syntax is somewhat funny.
int foo(int a, int b) []
{
...
}
But it's not allowed anyway. See n1256 6.7.5.3 paragraph 1, "Function declarators".
A function declarator shall not specify a return type that is a function type or an array type.
You can return pointers to arrays:
int (*foo(int a, int b)) []; // Weird syntax, n'est-ce pas?
But you might as well just return a pointer instead, since the following are equivalent:
int array[] = { ... };
int *x = array, (*y)[] = &array;
x[0];
(*y)[0]; // same as above, just with more cumbersome syntax
Typically, if a function needs to return an array of int, you either return the pointer or pass the pointer in. One of the following:
int *func(int a, int b); // Allocated by func
void func(int a, int b, int *array); // Allocated by caller
void func(int a, int b, int **array); // Allocated by func
The "struct-hack" also works for arrays that have a fixed size:
struct { int arr[50]; } array_struct;
struct array_struct func(int a, int b);
But this is not recommended unless the array is small.
Rationale:
Arrays are often large, and often have a size not known until runtime. Since parameters and return values are passed using the stack and registers (on all ABIs I know of), and the stack has a fixed size, it is somewhat dangerous to pass such a large object around on the stack. Some ABIs also don't gracefully handle large return values, potentially causing extra copies of return values to be generated.
The following code can also be dangerous:
void func(...)
{
int arr[BIG_NUMBER]; // potential for stack overflow
int *ptr = alloca(sizeof(int) * BIG_NUMBER); // potential for stack overflow
}
In C passing arrays by value is not directly supported (even when you write int [] as a parameter is actually interpreted as int *), if I remember correctly it's some sort of artifact of the passage from BCPL to C.
That being said, you can actually return arrays encapsulating them into structs:
struct
{
int value[20]
} foo(int a, int b)
{
/* ... */
}
(this trick obviously works also for parameters)
First, recall that arrays in C are really just syntactic sugar around pointers to blocks of memory. So C isn't restricting the functionality of the language by forcing the use of the former notation (See the example which follows).
Also, they may have made this choice to prevent early programmers from writing code like this:
char *itoa(int n){
char retbuf[25];
sprintf(retbuf, "%d", n);
return retbuf;
}
ref
Which looks simple enough, but what happens to the memory retbuf points to at the end of the function? Can the calling functions trust the data in the pointer it gets back?

Resources