MIN and MAX in C
Where are
MIN
andMAX
defined in C, if at all?
They aren't.
What is the best way to implement these, as generically and type safe as possible (compiler extensions/builtins for mainstream compilers preferred).
As functions. I wouldn't use macros like #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
, especially if you plan to deploy your code. Either write your own, use something like standard fmax
or fmin
, or fix the macro using GCC's typeof (you get typesafety bonus too) in a GCC statement expression:
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
Everyone says "oh I know about double evaluation, it's no problem" and a few months down the road, you'll be debugging the silliest problems for hours on end.
Note the use of __typeof__
instead of typeof
:
If you are writing a header file that
must work when included in ISO C
programs, write__typeof__
instead of
typeof
.
Use of min and max functions in C++
fmin
and fmax
are specifically for use with floating point numbers (hence the "f"). If you use it for ints, you may suffer performance or precision losses due to conversion, function call overhead, etc. depending on your compiler/platform.
std::min
and std::max
are template functions (defined in header <algorithm>
) which work on any type with a less-than (<
) operator, so they can operate on any data type that allows such a comparison. You can also provide your own comparison function if you don't want it to work off <
.
This is safer since you have to explicitly convert arguments to match when they have different types. The compiler won't let you accidentally convert a 64-bit int into a 64-bit float, for example. This reason alone should make the templates your default choice. (Credit to Matthieu M & bk1e)
Even when used with floats the template may win in performance. A compiler always has the option of inlining calls to template functions since the source code is part of the compilation unit. Sometimes it's impossible to inline a call to a library function, on the other hand (shared libraries, absence of link-time optimization, etc.).
Using functions to determine min or max
#include <stdio.h>
//variables for the functions
void MinMax(double a, double* max, double* min);
//main program
int main() {
double num = 0;
double min = 0;
double max = 0;
printf("Enter a real number: ");
scanf("%lf",&num);
//To exit the loop and avoid undefined behaviour
while (num != -999) {
MinMax(num, &max, &min);
printf("Enter a real number: ");
scanf("%lf",&num);
}
return 0;
}
void MinMax (double a, double* max, double* min) {
if (a > *max)
*max = a;
if (a < *min)
*min = a;
printf("The max is %lf and the min is %lf\n", *max, *min);
}
You may also choose to use:
static double max = 0, min = 0;
This would go on top of the MinMax function, but the best way to go about your problem is to use pointers to pass by reference. As demonstrated above:
void MinMax(double a, double* min, double* max)
Note: C uses * in prototype not &.
Happy coding.
Is max(a,b) defined in stdlib.h or not?
Any C library which defines a macro named max
in its standard headers is broken beyond imagination. Fortunately, an easy workaround if you need to support such platforms is to #undef max
(and any other problematic macros it defines) after including the system headers and before any of your own headers/code.
Note that everyone else is saying to wrap your definition in #ifndef max ... #endif
. This is not a good idea. Defining max
in a system header is an indication that the implementor was incompetent, and it's possible that certain versions of the environment have incorrect macros (for example, ones which do not properly protect arguments with parentheses, but I've even seen a max
macro that was incorrectly performing min
instead of max
at least once in my life!). Just use #undef
and be safe.
As for why it's so broken for stdlib.h
to define max
, the C standard is very specific about what names are reserved for the application and what names are reserved for standard functions and/or internal use by the implementation. There are very good reasons for this. Defining macro names in system headers that could clash with variable/function names used in the application program is dangerous. In the best case it leads to compile-time errors with an obvious cause, but in other cases it can cause very strange behavior that's hard to debug. In any case it makes it very difficult to write portable code because you never know what names will already be taken by the library.
C minimum/maximum function
So it seems there is not such standard function, so here is my solution:
For minimum:
void* get_min(void* start,size_t size,size_t elementSize,int (*compare)(const void *, const void*))
{
char* minObject = start;
for(int i = elementSize;i<size*elementSize;i+=elementSize){
char* object = start+i;
if(compare(object,minObject)<0){
minObject = object;
}
}
return minObject;
}
and for maximum:
void* get_max(void* start,size_t size,size_t elementSize,int (*compare)(const void *, const void*))
{
char* maxObject = start;
for(int i = elementSize;i<elementSize*size;i+=elementSize){
char* object = start+i;
if(compare(object,maxObject)>0){
maxObject = object;
}
}
return maxObject;
}
Use 'if' to find maximum and minimum
Your max
and min
are set to 1
at the beginning but after the input, the value of a
changes but max and min remain 1
.
You can solve this by initializing the max
and min
after the scanf
statement or you could just initialize max
and min
to INT_MAX
and INT_MIN
defined in limits.h
as pointed out by Barak Manos.
#include <stdlib.h>
//Enter five numbers and find the maximum and minimum.
int main()
{
int a,b,c,d,e;
scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);
int max = a, min = a;
....
....
}
Also, a simple version would be store all the input numbers in an array and call min
and max
on that array.
Related Topics
Unordered_Map Hash Function C++
Copy Constructor of Template Class
What Is the Optimal Algorithm for Generating an Unbiased Random Integer Within a Range
What Does '<Cuchar>' Provide, and Where Is It Documented
How to Set Up Googletest as a Shared Library on Linux
Can You Make Custom Operators in C++
How to Create a Pause/Wait Function Using Qt
How to Use MACro Argument as String Literal
What Is a Glibc Free/Malloc/Realloc Invalid Next Size/Invalid Pointer Error and How to Fix It
Why Does Ostream_Iterator Not Work as Expected
Blending Does Not Remove Seams in Opencv
How to Delete an Element from a Vector While Looping Over It
Efficient Thread-Safe Singleton in C++
Are There Practical Uses for Dynamic-Casting to Void Pointer