LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-15-2010, 04:48 AM   #1
jamesbon
Member
 
Registered: Jun 2010
Posts: 147

Rep: Reputation: 9
return value from a function


On this link http://lxr.ncu.cc/source/kernel/timer.c#094 a return type is defined
Code:
     return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG);
What is the above function returning.I am not clear with definition of what is being returned in the above code.
 
Old 11-15-2010, 08:12 AM   #2
sylvain.mazet
LQ Newbie
 
Registered: Aug 2006
Posts: 6

Rep: Reputation: 0
hi,
I dont see the problem.
The function returns an unsigned int, doesn't it?

I personally would have written it:
Code:
return ((unsigned int) (((unsigned long)base) & TBASE_DEFERRABLE_FLAG) );
(added parenthesis).
 
Old 11-15-2010, 08:52 AM   #3
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by jamesbon View Post
Code:
     return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG);
What is the above function returning.
It returns either a 0 or a 1.

base is declared as a pointer, but from the code it appears that base is the combination of a pointer and a flag. The low bit of this kind of aligned pointer is always clear (on the architectures supported by this code) so that bit is available for other use.

The double cast may look strange. I think from the compiler's point of view there are four casts because IIUC, 0x1 is a signed integer constant. (I haven't looked up exact language rules on whether there are two implicit extra casts here, because it doesn't really matter).

You need an explicit cast from pointer to some integer type so that the & operator will be valid. If this is compiled in x86_64 architecture then you probably would get a warning casting directly from pointer to 32 bit integer. So casting to unsigned long and then casting again to unsigned gets you there without a warning. Then I think the compiler casts it implicitly to a signed int to do the & operator, then because the function is declared as returning unsigned int, the compiler implicitly casts the result back to unsigned.

Quote:
Originally Posted by sylvain.mazet View Post
I personally would have written it:
Code:
return ((unsigned int) (((unsigned long)base) & TBASE_DEFERRABLE_FLAG) );
(added parenthesis).
Why?

That tells the compiler to generate code for a potentially less efficient operation that has the same final result.

A decent compiler at a higher optimization level will probably see through that and still generate the same code as without the extra parenthesis. So it might do no harm. But what good does it do?

It also masks intent from some later programmer who might need to understand and maintain the code. Anyone maintaining this code should understand why there are two casts. If the casts are directly sequential with no intervening operation, that greatly limits the possibilities for the intent of the casts. In this case, I think it limits the reason for two casts instead of one down to avoiding a warning.

But if you went to obvious effort to make the & operation happen after one cast but before the other, a maintenance programmer should wonder why? Is some operation here trickier than the maintenance programmer can see? Or did the original programmer intend something that this code doesn't actually accomplish? Or what?

Last edited by johnsfine; 11-15-2010 at 09:04 AM.
 
Old 11-15-2010, 04:36 PM   #4
sylvain.mazet
LQ Newbie
 
Registered: Aug 2006
Posts: 6

Rep: Reputation: 0
OK,

if I get it right:
1) cast to unsigned long: to get the & operator without a warning, and also good habit on 64 bit platform (not rely on TBASE_DEFERRABLE_FLAG being 0x1),
2) then cast result "down" to unsigned int to get a 1, unsigned int (4 bytes), without warning.

The parenthesis I would add are for legibility, because I am lazy:
I dont like to rely on priority rules or the like, since I am never certain enough about them.
I am quite sure it has no influence on the compiled code, all compilers can optimize that, and don't really care if you put them or not.

I must add I am no kernel programmer, just the HPC developper kind. My intent is not at all to criticize the kernel code.

Cheers,
S.
 
Old 11-15-2010, 08:38 PM   #5
jamesbon
Member
 
Registered: Jun 2010
Posts: 147

Original Poster
Rep: Reputation: 9
Is the same thing happening here
http://www.mjmwired.net/kernel/Docum...ress-test.c#34
 
Old 11-16-2010, 07:50 AM   #6
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by jamesbon View Post
That example also involves a cast. But the reason is very different and not much else there fits your description of "same" relative to the earlier example.

Regardless of whether you are running 32 bit or 64 bit architecture, the rdtsc instruction gives you two 32 bit unsigned integer values that represent one 64 bit unsigned value.

To convert a 32 bit value into the high half of a 64 bit value, you need to explicitly cast before shifting. That is the reason for the explicit cast in this example.

If you relied on the implicit cast of the returned result, the shift would produce a 32 bit result (which would be zero) then the implicit cast to 64 bit would occur only after adding that zero to the other 32 bit half.

Having declared uint32_t hi;

(hi << 32) is a 32 bit zero.


(uint64_t)(hi << 32) is a 64 bit zero.

((uint64_t)hi << 32) is the correct 64 bit value of hi shifted up 32 bits.

Quote:
Originally Posted by sylvain.mazet View Post
The parenthesis I would add are for legibility, ...
I dont like to rely on priority rules
I strongly prefer a coding standard that pretends only a specific small subset of the language's precedence rules are known by the maintenance programmers. All other cases must be covered by redundant parentheses. So I absolutely agree with you in principle about adding parentheses. But the ones you added did not reinforce the order of operations built into the language. They changed the order of operations.

Compare that to the new example:

Code:
return (uint64_t)hi << 32 | lo;
I would absolutely add parentheses. My "known" subset of precedence rules lets me know basics, such as + happens after *, and even slightly more advanced rules such as | happens after & but I prefer to pretend I don't know that | happens after <<. So:

Code:
return ((uint64_t)hi << 32) | lo;

Last edited by johnsfine; 11-16-2010 at 08:06 AM.
 
Old 11-17-2010, 05:13 AM   #7
sylvain.mazet
LQ Newbie
 
Registered: Aug 2006
Posts: 6

Rep: Reputation: 0
Hi,

back to the first question about parenthesis.
I'm sorry, I don't get your meaning. It seems I am missing something.

Let's say "base" is a pointer type, flag a constant flag (#defined as 0x1).

Are you saying that
Code:
 (uint_t) (((uint64_t) base) | flag )
is not the same as
Code:
 (uint_t) (uint64_t) base | flag
?
How should the second expression be parenthesized,
to be left unchanged?

------------------------------
"The devil is in the details."
 
Old 11-17-2010, 07:39 AM   #8
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
How should the second expression be parenthesized,
to be left unchanged?
Code:
 (uint_t) (uint64_t) base | flag
is the same as

Code:
( (uint_t) ( (uint64_t) base ) ) | flag
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Get return value of function mortonmorton Linux - Newbie 4 10-09-2009 09:54 PM
where is return value of a function stored? fssengg Programming 7 06-26-2008 01:43 AM
return value of Clock function namanhams Programming 1 04-01-2008 12:00 PM
How to get return value from C function using shell yhacks Programming 3 03-11-2008 04:58 PM
return value of function in script ramesh_manu Red Hat 1 02-18-2007 01:05 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:18 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration