Representation of integer types?

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

Pretty sure the first one is shared with C and C++ but not sure. Second question appears to fall straight into the C++ domain.

 

A. Suppose that I have a uint16_t variable, lets say "x". If I write x = 0xFFFF, it will represent a positive integer and if x is an int16_t, it will represent a negative value. Is this correct?

 

B. Now, for C++, lets suppose I have an overloaded function, one myFunct( uint16_t value ) and the other as myFunct( int16_t value ). Now, if I use a typed variable, say "x" from the previous question, I am assuming that the type of x will determine which one is executed. But, what happens if I write myFunct(0xFFFF)? 0xFFFF has not been given a type (or has it?). 

 

Yes, I have code that I am going to test with, in a few minutes. But, I am trying to understand the underlying principles, here. And I don't know what the principles are.

 

Thanks

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

A) Yes
B) Don't know much about C++, but my guess is that the type of 0xFFFF is the same as in C. Which one exactly? That depends on sizeof(int). If we are talking about AVR, then sizeof(int) is 2, then 0xFFFF is "unsigned int", which should be the same as uint16_t, I would think.

If sizeof(int) was 4, like on an ARM, for example, then 0xffff would be an "int".

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

Appreciate that. sizeof(int) was one of the missing pieces. But I don't see why 0xffff would be an int on 4-byte integer system. Does the type assignment depend on the value of the constant?

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Thu. Jul 13, 2017 - 04:42 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just googled some sort of C++ standard: http://www.open-std.org/jtc1/sc2... . So, let's see. Page 24, "The type of an integer literal is the first of the corresponding list in Table 6 in which its value can be represented". The first type in the list is "int". 0xFFFF can be represented by an int. Therefore, 0xFFFF is an int.

Last Edited: Thu. Jul 13, 2017 - 04:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ahhh, did not even know what to search for. That makes some sense. So, it DOES depend on the value of the literal compared to the maximum possible value (for the type).

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Thu. Jul 13, 2017 - 05:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I tried to test it on a PC (cygwin) and here are the results :

astyle  ka7ek_integer.cpp ;  g++ ka7ek_integer.cpp
Inchangée  /home/briond/ka7ek_integer.cpp
ka7ek_integer.cpp: In function ‘int main(int, char**)’:
ka7ek_integer.cpp:11:19: erreur: call of overloaded ‘myFunct(int)’ is ambiguous
     myFunct(0xFFFF);
                   ^
ka7ek_integer.cpp:11:19: note: candidates are:
ka7ek_integer.cpp:4:6: note: void myFunct(uint16_t)
 void myFunct( uint16_t value ) {
      ^
ka7ek_integer.cpp:7:6: note: void myFunct(int16_t)
 void myFunct( int16_t value ) {
      ^

I called g++ with no arguments (I bet it can be less permissive) but, as such, it protests and cannot compile (too ambiguous);

Source code is  that (very much like C)

 

$ cat ka7ek_integer.cpp

#include <stdio.h>
#include <stdint.h>
void myFunct( uint16_t value ) {
    printf("function pour uint va=:<%d>\n", value);
}
void myFunct( int16_t value ) {
    printf("function pour int va=:<%d>\n", value);
}
int main (int argc, char* argv[] ) {
    myFunct(0xFFFF);
    return(0);
}

 

Edited : my PC compiler is old -4.8.2 .  I decided to try a cloud compiler, cpp.sh (Johan ekdahl kindly told it existed) and ... results are the same.... Perhaps Avr is "better" than PC and clouds...

Last Edited: Thu. Jul 13, 2017 - 01:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What I find odd is that for your "A" question if I write:

#include <stdint.h>
int16_t x = 65535;

which is identical to your example but clearly wrong (65535 will never fit in a 16-bit signed integer), no compiler warnings are generated.

It requires -Wconversion enabling to report the problem.

 

nigel@E3510:~$ cat ka7ek_integer.cpp
#include <stdint.h>
int16_t x = 65535;

nigel@E3510:~$ g++ -Wall -Wextra -c ka7ek_integer.cpp -o /dev/null
nigel@E3510:~$

nigel@E3510:~$ gcc -Wall -Wextra -Wconversion -c ka7ek_integer.c -o /dev/null
ka7ek_integer.c:2:13: warning: conversion to ‘int16_t {aka short int}’ alters ‘int’ constant value [-Wconversion]
 int16_t x = 65535;
             ^
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
So, it DOES depend on the value of the literal compared to the maximum possible value (for the type).

 

In avr-gcc (4.9.2) with default flags,  my test code compiles without warnings, the function called depends on size of the literal

 

  // these call uint16_t method
  motionControl.myFunc (0xFFFF);
  motionControl.myFunc (0x8000);
  motionControl.myFunc (0x7FFFU);

  // these call int16_t method
  motionControl.myFunc (0x7FFF);
  motionControl.myFunc (-1);

 

I threw in 'U' suffix just to check. As it happens, I have just been struggling with integer promotion issues. Code that worked fine with int/unsigned, stopped working when I used int32_t/uint32_t. I thought the extra range would help, but it introduced a bug instead!

 

Edit: interesting, the Eclipse code analyzer flags these lines with an error, even though avr-gcc doesn't flag a warning even with -Wconversion -Wall

Bob.

Last Edited: Thu. Jul 13, 2017 - 10:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So according to that standard, myFunct(0xFFFF) and myFunct(65535) will call different versions of myFunct:

 

hex: 0xFFFF can't fit in int, next is unsigned int. It fits, so myFunct(unsigned int) is called.

 

decimal: 65535 can't fit in int, next is long int. It fits, so myFunct(long int) is called.

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

dbrion0606 wrote:

$ cat ka7ek_integer.cpp

#include <stdio.h>
#include <stdint.h>
void myFunct( uint16_t value ) {
    printf("function pour uint va=:<%d>\n", value);
}
void myFunct( int16_t value ) {
    printf("function pour int va=:<%d>\n", value);
}
int main (int argc, char* argv[] ) {
    myFunct(0xFFFF);
    return(0);
}

With a 32-bit int, 0xFFFF is neither uint16_t nor int16_t,

hence any literal will require a conversion for either myFunc.

The compiler has no standard with which to select, hence ambiguity.

 

Also, signed integer overflow as a result of arithmetic is undefined.

As a result of conversion, it is implementation-defined.

gcc's implementation has the effect of a reinterpret_cast,

i.e. keep the same bits, just interpret them according to the signed type.

I expect this is common for twos-complement platforms.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?

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

Thanks Skeeve : your explanation is  consistent with the fact avr-gcc (yes : the suffix leads to automagic invocation of avr-g++ ...)  does not throw any error with the same source -there is no ambiguity with  avr processor)

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

Some things you can test in "desktop C++" and some things you can't. When sizeof(int)==2 is an important factor that will probably fall into the "can't" category

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

Well, I agree, but it is ironical since int_xxxt types were meant to make code (more) portable...

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

But we're talking about 0XFFFF which completely fills an int on AVR but is just a small value for a "PC int". 

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

dbrion0606 wrote:
Well, I agree, but it is ironical since int_xxxt types were meant to make code (more) portable...
Explicit conversion, e.g. uint16_t(0xFFFF), will cure the ambiguity.

 

This raises an important issue:

How much effort should one put into ensuring code can be tested, or at least compiled,

for a platform other than one for which it is targeted?

Not all platforms will have uint16_t.

On those that do, it could be either unsigned int, unsigned short,

unsigned char or even an implementation-defined type.

It could even change between compiler versions.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?

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

clawson wrote:
But we're talking about 0XFFFF which completely fills an int on AVR but is just a small value for a "PC int".

 

I remember a thread where this was thoroughly hashed out.  Much consternation and gnashing of teeth.  Picking through the standard; distinction between constant and literal; much quoting of promotion rules.

 

Still don't quite understand it, but I'd call it the definitive thread. 

 

Now if I can only find it...

 

http://www.avrfreaks.net/forum/s... maybe?

 

 

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.

Last Edited: Sat. Jul 15, 2017 - 08:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now if I can only find it...

 

http://www.avrfreaks.net/forum/s... maybe?

The very one I imagined you had in mind.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

theusch wrote:
clawson wrote:
But we're talking about 0XFFFF which completely fills an int on AVR but is just a small value for a "PC int".

 

I remember a thread where this was thoroughly hashed out.  Much consternation and gnashing of teeth.  Picking through the standard; distinction between constant and literal; much quoting of promotion rules.

 

Still don't quite understand it, but I'd call it the definitive thread. 

 

Now if I can only find it...

 

http://www.avrfreaks.net/forum/s... maybe?

As more than hinted at, there was a lot of heat to go with the light.

I'll try to summarize the types of integer literals part.

integer != int .

Integer literals have bases and values that together with the platform's integer type implementations determine their types.

The same literal can have different types on different platforms.

The smallest possible types of an integer literal are int and unsigned int.

The C standards' semantics ensure that no integer literal can have a negative value.

An unsuffixed decimal integer literal will always have a signed integer type.

An unsuffixed octal or hexadecimal literal will have an unsigned type if

the value fits in an unsigned type, but not in the corresponding signed type.

That is the implication of the table in 6.4.4.1 Integer Constants .

65, 01001 and 0x41 are all integer literals with the same value.

The value is representable by an int on any platform.  Their types are all int.

0xFF00 and 65280 are integer literals with the same value.

On a 16-bit platform, 0xFF00 is an unsigned int and 65280 is a long.

On a 17-bit platform, they are both ints.

Neither -0xFF00 nor -65280 are integer literals.

Minus signs are not part of literals.

One result of this is that -1-INT_MAX cannot be represented

as either an integer literal or the negative of an integer literal.

 

In most binary operations, possibly promoted operands are converted to the same type before the operations.

This is another situation in which the platform matters.

A promoted operand is at least as big as an int or unsigned int.

Operands not larger than int are converted to int if the conversion would be value-preserving,

otherwise the conversions are to unsigned int.

A signed char or a signed short would be converted to int on any platform.

A 16-bit unsigned short could be converted to a 16-bit unsigned int or, on a different platform, a 32-bit int.

After promotion, if the operands have different types, one is converted to the type of the other.

If possible, a value-preserving conversion is used, otherwise the unsigned type is used.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?