In C, why can't I shift a 64-bit integer more than 32 bits?

I'm using Mingw's compiler, and UEStudio.

When I try to shift a 64-bit integer more than about 32 bits, I get zero for the result. I've googled and googled, and can't find an answer.

Here is the pertinent code:
unsigned long long int MyLongLong;
unsigned long long int ShiftAmount;

printf("%d\n",sizeof(MyLongLong));

MyLongLong = 1;
ShiftAmount = 13;

printf("%016LLX\n", MyLongLong);

MyLongLong = MyLongLong << ShiftAmount;
printf("%016LLX\n", MyLongLong);

MyLongLong = MyLongLong << ShiftAmount;
printf("%016LLX\n", MyLongLong);

MyLongLong = MyLongLong << ShiftAmount;
printf("%016LLX\n", MyLongLong);

Open in new window


This prints into the console:
8
0000000000000001
0000000000002000
0000000004000000
0000000000000000

I'd looooove any ideas!
--Steve D.
StevenMilesAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kent OlsenData Warehouse Architect / DBACommented:
Hi Steve,

The shift count is probably just an integer (not a long or long/long).  :)

I'd add another test.  After line 18, add this:

MyLongLong = MyLongLong >> ShiftAmount;
printf("%016LLX\n", MyLongLong);

That will show us whether the shift is truly failing or if the output format is dropping the upper 32 bits.


Kent
0
TommySzalapskiCommented:
You have upper case Ls in your printf which is for doubles. Try changing them to lower case for 64 bit integer.
0
StevenMilesAuthor Commented:
HA!! Doing the right shift showed that the shift is happening, but I just can't print it out!

I thought I was going crazy.

But now, how do I print it out? I've tried these, without success:
%16LLX
%16llX, then I realized my "X" was capital, so I used
%16llx, and
%llx , which also shows a zero result, but the right shift proves that the value is not zero.
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

StevenMilesAuthor Commented:
FWIW, "llu" also prints out zero for the higher numbers.
0
Kent OlsenData Warehouse Architect / DBACommented:
Start with the basics.

Use "%llu" as the formatter.  You can modify it once you're comfortable that it works.
0
Kent OlsenData Warehouse Architect / DBACommented:
Ah.  Sorry.

Try "%I64d" for integer and "%I64x" for hex.
0
TommySzalapskiCommented:
What version of C/C++ are you using? What compiler?
0
StevenMilesAuthor Commented:
I'm using the very latest installation from MinGW, I think. I just installed it yesterday:
C:\MinGW\bin>gcc --version
gcc (GCC) 4.8.1

C:\MinGW\bin>g++ --version
g++ (GCC) 4.8.1

In place of where I had the printf statements, I made a call to this function I just wrote:

void Print_64_bit(unsigned long long int printThis) {
	unsigned long long int highorder;
	unsigned long long int loworder;
	highorder = printThis;
	loworder = printThis;
	highorder = highorder >> 32;
	printf ("0x");
	printf ("%08llx",highorder);
	printf ("%08llx\n",loworder);
	return;
}

Open in new window


And the output now looks like this (for ShiftAmount=15):
8
0x0000000000000001
0x0000000000008000
0x0000000040000000
0x0000200000000000
0x1000000000000000
0x0000200000000000
0x0000000040000000
0x0000000000008000

So it would seem that I can proceed with my programming, because I now know how to print out a 64-bit integer. And it's easy. But this is a kludge. I still don't really understand what's going on.
0
TommySzalapskiCommented:
MinGW uses the Win32 Runtime so Kdo's suggestion to use %l64x should work. Windows doesn't respect the ll specifier.
0
Kent OlsenData Warehouse Architect / DBACommented:
Hi Steven,

I downloaded the GCC compiler and to my Windows environment and tried this.  It looks like just lower casing the items in the format string will work.

  printf("%16.16llx\n", MyLongLong);
  printf("%016llx\n", MyLongLong);

Both of those lines printed the desired results for me, using the 32-bit compiler 4.9.3.  


Good Luck!
Kent
0
StevenMilesAuthor Commented:
Okay, folks,

I appreciate all the help, and you don't have to keep racking your brains, but it's not working. However, it doesn't really matter right now, since my kludge is fine.

I tried "%l64x" but that prints out "64x" for MyLongLong, not even the bits.

I also tried   "%16.16llx\n"  and    "%016llx\n" but they had the same problem: after 32 bits, the printout was all zeroes.

I'm at a loss, but as I said, I'm in business again with the kludge. I'll distribute points around; I always appreciate the help, even if a solution isn't found.
0
Kent OlsenData Warehouse Architect / DBACommented:
Just to make sure, but "I64" is eye-sixty-four, not ell-sixty-four.  :)

Also, whenever I display hex or octal values I invariable split full words for readability.

printf ("%04x %o4x  %o4x %o4x\n",
  MyLongLong >> 48,
  (MyLongLong >> 32) & 0xFFFF,
  (MyLongLong >> 16) & 0xFFFF,
  MyLongLong & 0xFFFF);

It's much easier to identify stray bits this way, and it will work even your your environment.

And if it's a memory dump or similar, I take it a step further and replace all zero ("0000") with all dashes ("----"), making it trivial to identify the non-zero values.

Sorry that we couldn't fix this for you!
Kent
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
StevenMilesAuthor Commented:
Oh how embarrassing. I must be sleeping through this week.

%I64x , with an "eye", works!! So if I use %016I64x, I can get 16 digits no matter where the bits are set. Wow.

And, I love your idea of re-formatting it. Actually, I had already updated my Print_64_bit function from above, to make the hex printout not like this:
0x2345673428798304

but rather like this:
0x 2345-6734-2879-8304

Much more readable. Maybe spaces here are better than hyphens, and I can use hyphens for the zeros.

Thanks again.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.