quick question about unsigned long long...

Go To Last Post
27 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys, stumbled on to a ee problem that I can't see the solution to.  See the code below:

static unsigned int data_to_endian(unsigned long long value, unsigned char * endian){

	endian[0] = (unsigned char)value;
	endian[1] = (unsigned char)value >> 8;
	endian[2] = (unsigned char)value >> 16;
	endian[3] = (unsigned char)value >> 24;
	endian[4] = (unsigned char)value >> 32;
	endian[5] = (unsigned char)value >> 40;
	endian[6] = (unsigned char)value >> 48;
	endian[7] = (unsigned char)value >> 54;
}

but I'm getting a compiler saying:

warning: right shift count >= width of type [-Wshift-count-overflow]

but why, value is a 64bit integer?

This topic has a solution.
Last Edited: Mon. Aug 16, 2021 - 04:52 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You should do this.

static unsigned int data_to_endian(unsigned long long value, unsigned char * endian){
	endian[0] = (unsigned char)value;
	endian[1] = (unsigned char)(value >> 8);
	endian[2] = (unsigned char)(value >> 16);
	endian[3] = (unsigned char)(value >> 24);
	endian[4] = (unsigned char)(value >> 32);
	endian[5] = (unsigned char)(value >> 40);
	endian[6] = (unsigned char)(value >> 48);
	endian[7] = (unsigned char)(value >> 54);
	return 0;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

If you want to promote the shifts to be "long long" then perhaps also consider:

(value >> 54ULL);

BTW do NOT use "unsigned long long" anyway. Use uint64_t.

 

If you port this code to a machine where a long is not 32 bit then it will not build correctly. However if you use uint64_t then not only does it tell the reader immediately that "this is an unsigned 64 bit variable" it also guarantees it whatever architecture the code is built for. You should never use any of "short, int, long". It is OK to use "char" but don't use it for numerics, only for characters, for 8 bit numerics use int8_t or uint8_t.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

If you want to promote the shifts to be "long long" then perhaps also consider:

(value >> 54ULL);

 

That would work with other operators, but doesn't work with shifts. The type used for the shift operation is the (integer promoted) type of the left operand only.

So it would need to be (uint64_t)(value) >> 54

If value is already a uint64_t (or unsigned long long) then cast is not needed of course.

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But as Cliff pointed out - why is anyone using long long in this day and age? Use a defined length variable: uint64_t

 

I have a vague idea that shifts are undefined/implementation dependent for signed variables - is this the case?

 

Neil

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Compiler dependent?

 

#include <stdint.h>

void out(uint64_t val);

int main() {
  uint64_t value = 1;
  value >> 54ULL; // PC-lint generates a 522
  value = value >> 54ULL;
  out(value);
}

 

Gimpel On-Line Message Reference Manual

Copyright © 2011, Gimpel Software

[1/4 page]

522

   Highest operator or function lacks side-effects -- If a statement
      consists only of an expression, it should either be one of the
      privileged operators: assignment, increment, decrement or call to
      an impure function or one modifying its argument(s).  For example
      if operator * is the built-in operator, the statement *p++; draws
      this message but p++; does not.  This is because the highest
      operator is '*' which has no side effects.

      The definition of pure and impure functions and function calls
      which have side effects are given in the discussion of the pure
      semantic in section 

 


PC-lint Plus Online Demo - Gimpel Software - The Leader in Static Analysis for C and C++ with PC-lint Plus

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

barnacle wrote:

I have a vague idea that shifts are undefined/implementation dependent for signed variables - is this the case?

Some aspects are.

May as well just quote the C standard. Thsi is from C99, i don't think it will have changed since

 

The integer promotions are performed on each of the operands. The type of the result is
that of the promoted left operand. If the value of the right operand is negative or is
greater than or equal to the width of the promoted left operand, the behavior is undefined.

 

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with
zeros. If E1 has an unsigned type, the value of the result is E1 × 2 ^^E2 , reduced modulo
one more than the maximum value representable in the result type. If E1 has a signed
type and nonnegative value, and E1 × 2^^E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.

 

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type
or if E1 has a signed type and a nonnegative value, the value of the result is the integral
part of the quotient of E1 / 2^^E2 . If E1 has a signed type and a negative value, the
resulting value is implementation-defined.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

barnacle wrote:

But as Cliff pointed out - why is anyone using long long in this day and age? Use a defined length variable: uint64_t

 

"Defined length" types are optional.

 

barnacle wrote:

I have a vague idea that shifts are undefined/implementation dependent for signed variables - is this the case?

 

Firstly, shifts for positive signed values have always been perfectly defined (as long as there's no overflow). In C left shifts for negative values are undefined. Right shifts for negative values are implementation defined.

 

Secondly, C++ has already adopted "one true signed representation" to rule them all: 2's-complement. 1's-complement and sign-and-magnitude got outlawed. Now in C++ all shifts are perfectly defined in all cases for all values, including negative ones. C is not there yet. Maybe C will stick with multiple supported signed representations longer, but it will probably get there sooner or later as well.

Dessine-moi un mouton

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you both; that was what I had remembered.

 

Neil

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"Defined length" types are optional.

 

It might still be a good idea to use them. Nobody said they were mandatory.

 

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Nobody said they were mandatory.
Except MISRA ? ;-)

 

EDIT: that is...

 

  • MISRA C:2004, 6.3 - typedefs that indicate size and signedness should be used in place of the basic types
  • MISRA C++:2008, 3-9-2 - typedefs that indicate size and signedness should be used in place of the basic numerical types

 

(one day I'll find my actual copies of MISRA - the efficiency bunny has hidden them!)

 

EDIT2: so, in the absence of the book, it wasn't too hard to find a dodgy PDF on the internet in fact - so OK, 6.3 is just "(advisory)" rather than "(required)" - I'll grant you that.

Last Edited: Wed. Aug 18, 2021 - 01:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

54=9*6 is not a multiple of 8.

56 would seem to be wanted.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I didn't know I could have 64 bit unsigned integers in a mega.  Aren't floats and doubles both 32 bits?  Can I get a 64 bit floating point variable?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MarkThomas wrote:
Can I get a 64 bit floating point variable?
Yes

Libf7 | avr-gcc - GCC Wiki

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MarkThomas wrote:
I didn't know I could have 64 bit unsigned integers in a mega.

Hard to believe but still these 8 bit micros pack quite a punch. A man can probably leave this solar system with a bunch of 8-bit megaAVR's controlling the rocket.

“Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?” - Brian W. Kernighan
“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” - Antoine de Saint-Exupery

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MarkThomas wrote:

I didn't know I could have 64 bit unsigned integers in a mega.  Aren't floats and doubles both 32 bits?  Can I get a 64 bit floating point variable?

Surely you aren't really asking about "mega", but rather "with <insert name here> C toolchain...".

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That tells me I need V10 of gcc.  How do I see what compiler my AS Version 7.0.2397 is using?  I know I have seen it somewhere in the past, and I that I can change compilers, but I can't seem to find it now.  I see gnu99 as one of the compiler flags.  I can declare a long double, and multiply it by itself, and it compiles, so my version seems to know what one is. 

 

Thanks.  I'm pretty much hopeless at system level stuff and machine language level.  All I've ever done is algorithms in C and Fortran before that, so I live in that little slot between system and machine, blissfully ignorant of how it all works, but happy when the numbers coming out of my code are as should be. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Surely you aren't really asking about "mega", but rather "with <insert name here> C toolchain...".

 

ATmega1284P and ATmega328P

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Lee's point was that it doesn't matter what model of AVR you have, whether you can do uint64_t, 64 bit double and so on is down to which C compiler you choose to use. IAR and the Pro version of the (now demised) Imagecraft both offered 64bit double by default I believe (though they cost $3000 and $800). Other compilers like GCC and Codevision have both float and double as 32 bit. There is no 64 bit support. As for uint64_t ((unsigned) long long) I think IAR/Imagecraft/GCC have this but I'm not sure about Codevision. There are, of course, other compilers like MikroC - but who knows about them !

 

As for a GCC that is >=10, this page appears to have V11:

 

https://blog.zakkemble.net/avr-g...

 

In Studio 7 you would set this up as a "toolchain flavour", see:

 

https://microchipsupport.force.c...

 

EDIT: Just checked Codevision user manual so it has 64 bit integers too...

 

Last Edited: Mon. Sep 6, 2021 - 08:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
There are, of course, other compilers like MikroC - but who knows about them !

Rowley/CrossWorks, pay-for, has long-long as well as true double.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yup, apart from David I don't know anyone who ever uses Rowley but it sounds like it's probably actually pretty good. I know David likes the debug environment too. No idea what it costs though?

 

EDIT: OK, $150 for a personal/non-commercial license apparently.

Last Edited: Mon. Sep 6, 2021 - 11:50 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Cliff.  That helps.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Surely you aren't really asking about "mega", but rather "with <insert name here> C toolchain...".

 

I guess, yeah.  It's as Cliff says.  It's all about the compiler.  But I would think the hardware platform imposes some constraints. 

 

It has always been like magic for me.  I write my code and numbers come out.  How that happens is a black box I don't much think about.  I know lots of people find the workings of the black box fascinating.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

MarkThomas wrote:
But I would think the hardware platform imposes some constraints.

 

The absolute minimum you need for an ALU to be able to do arithmetic is the ability to subtract one register from another (or from memory) and the ability to NAND two registers/memory locations. With those you can do the whole suite of basic arithmetic operations - though it's more common to find addition, subtraction, and AND/OR/XOR which makes it a bit simpler.

 

The size of the operations you can perform is limited not by the register size but by the amount of memory you can address... if an eight-bit micro is trying to do 64- or 128-bit arithmetic, it just has to take more steps to do it. There's nothing intrinsic in the processor that inhibits larger variables and operations, in the same way there's no practical difference between adding two single digit decimal numbers and decimal numbers with more digits. Just more of the same, and keep an eye on the carry!

 

Neil

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But I would think the hardware platform imposes some constraints. 

Remember that the very early calculators in the 70's were using 4 bit micros.

 

Later I owned a Sinclair Programmable, things had moved on a bit by then, but if you typed "45, sin, cos, tan, atan, acos, asin" you could basically walk away and get a coffee in the time it took for the result to appear ! It probably had an 8 bit micro but I'm guessing 1MHz so maths was "do-able" but it took a long long time.

 

It's more about the "cleverness" of the software than the capabilities of the hardware.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
apart from David I don't know anyone who ever uses Rowley

It seemed to me that Segger Embedded Studio is a re-badge of Rowley (I think "Rowley" got a mention in some of the config/system files?)

 

https://www.segger.com/products/development-tools/embedded-studio/

 

So that might count me in as a "Rowley user" ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Neil, now you are talking my language.  That makes perfect sense.

 

Cliff, I got a 4 function calculator for graduation from high school - add subtract multiply divide.  It cost $100.  I recall it was LED display.  In 1967, it was probably the LEDs that cost so much.  Not the arithmetic chips.  I never found it very useful.  At the time I could do arithmetic in my head, but my parents thought it was pretty cool.  I still use a Casio fx-82 that uses 2 AA batteries.  It sits next to my laptop because I can't do arithmetic in my head so clearly anymore.  I have to wait a second or two for a cosine to pop up, but I have plenty of time.  I did a Bing search and was amused the image was from the IT History Society.  Now that made me feel old.