What is the function of "(void) (&_min1 == &_min2)" in the min macro in kernel.h?

CLinux Kernel

C Problem Overview


In kernel.h min is defined as:

#define min(x, y) ({				\
	typeof(x) _min1 = (x);			\
	typeof(y) _min2 = (y);			\
	(void) (&_min1 == &_min2);		\
	_min1 < _min2 ? _min1 : _min2; })

I don't understand what the line (void) (&_min1 == &_min2); does. Is it some kind of type checking or something?

C Solutions


Solution 1 - C

The statement

(void) (&_min1 == &_min2);

is a guaranteed "no-op". So the only reason it's there is for its side effects.

But the statement has no side effects!

However: it forces the compiler to issue a diagnostic when the types of x and y are not compatible.
Note that testing with _min1 == _min2 would implicitly convert one of the values to the other type.

So, that is what it does. It validates, at compile time, that the types of x and y are compatible.

Solution 2 - C

The code in include/linux/kernel.h refers to this as an "unnecessary" pointer comparison. This is in fact a strict type check, ensuring that the types of x and y are the same.

A type mismatch here will cause a compilation error or warning.

Solution 3 - C

This provides for type checking, equality between pointers shall be between compatible types and gcc will provide a warning for cases where this is not so.

We can see that equality between pointers requires that the pointers be of compatible types from the draft C99 standard section 6.5.9 Equality operators which says:

>One of the following shall hold:

and includes:

>both operands are pointers to qualified or unqualified versions of compatible types;

and we can find what a compatible type is from section 6.2.7 Compatible type and composite type which says:

>Two types have compatible type if their types are the same

This discussion on osnews also covers this and it was inspired by the GCC hacks in the Linux kernel article which has the same code sample. The answer says:

> has to do with typechecking. > > Making a simple program: > > int x = 10; > long y = 20; > long r = min(x, y); > > Gives the following warning: warning: comparison of distinct pointer > types lacks a cast

Solution 4 - C

See http://www.osnews.com/comments/20566 which explains:

> It has to do with typechecking. > > Making a simple program: > > int x = 10; > long y = 20; > long r = min(x, y); > > Gives the following warning: > warning: comparison of distinct pointer types lacks a cast

Solution 5 - C

Found answer here

"It has to do with typechecking. Making a simple program:

int x = 10; 
long y = 20; 
long r = min(x, y); 

Gives the following warning: warning: comparison of distinct pointer types lacks a cast"

Solution 6 - C

The Linux kernel is full of stuff like this (gratuitous gcc-specific hacks for the sake of "type safety" and other similar considerations), and I would consider it very bad practice and urge you not to follow it unless someone requires you to.

pmg is right about the purpose of the hack, but any sane person would define min as ((x)<(y)?(x):(y)).

Note that the kernel definition precludes many correct usages, e.g. where one argument is int and another is long. I suspect what they really wanted to preclude is signedness mismatches, where for example min(-1,1U) is 1. A better way to assert this would be to use a compile-time assertion for ((1?-1:(x))<0)==((1?-1:(y))<0). Note that this does not require any gcc-specific hacks.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRobert S. BarnesView Question on Stackoverflow
Solution 1 - CpmgView Answer on Stackoverflow
Solution 2 - CHasturkunView Answer on Stackoverflow
Solution 3 - CShafik YaghmourView Answer on Stackoverflow
Solution 4 - CEmil SitView Answer on Stackoverflow
Solution 5 - Cincogn1toView Answer on Stackoverflow
Solution 6 - CR.. GitHub STOP HELPING ICEView Answer on Stackoverflow