Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the type of a integral true constant?

Tags:

delphi

I'm sorry for asking a very basic question. Consider the following example:

const
  c1 = 1;      // Is this Byte or ShortInt?
  c2 = 1234;   // Is this Word or Smallint?
  c3 = 123456; // Is this Cardinal or Integer?

After reading this documentation, what I can conclude is that negative value is interpreted as signed, and positive value is interpreted as unsigned. However, e.g. 123456 (which according to the documentation will be interpreted as Cardinal) can also be used in a context of Integer, I mean it is used in an Integer variable that uses the constant in calculation. Therefore, is the constant guaranteed to be always Cardinal so that a typecast to Integer necessary?

like image 597
Aeoliyan Avatar asked Aug 22 '15 19:08

Aeoliyan


People also ask

What is the integral of a constant?

The integral of a constant is equal to that constant times the variable of integration plus an arbitrary constant. The derivative of a constant K times an independent variable x is equal to K, because the function Kx can be written y = Kx + 0, a line of constant slope K.

What is true definite integral?

The definite integral is defined to be exactly the limit and summation that we looked at in the last section to find the net area between a function and the x -axis. Also note that the notation for the definite integral is very similar to the notation for an indefinite integral.

How many types of integral are there?

The two types of integrals are definite integral (also called Riemann integral) and indefinite integral (sometimes called an antiderivative).

Why is the integral of zero a constant?

The integral of 0 is equal to an arbitrary constant as the derivative of a constant function is always equal to zero.


1 Answers

The documentation (XE8 is the latest version as I write this) tells you that true constants have a type. However, the documentation is misleading when it comes to specifying what that type actually is. And when I say misleading, I am being somewhat kind.

Were you to read this official documentation then you would be inclined to believe that unsigned types are preferred to signed types. But this program shows that is not the case:

program SO32160057_overloads;

{$APPTYPE CONSOLE}

procedure foo(value: UInt8); overload;
begin
  Writeln('UInt8');
end;

procedure foo(value: UInt16); overload;
begin
  Writeln('UInt16');
end;

procedure foo(value: UInt32); overload;
begin
  Writeln('UInt32');
end;

procedure foo(value: UInt64); overload;
begin
  Writeln('UInt64');
end;

procedure foo(value: Int8); overload;
begin
  Writeln('Int8');
end;

procedure foo(value: Int16); overload;
begin
  Writeln('Int16');
end;

procedure foo(value: Int32); overload;
begin
  Writeln('Int32');
end;

procedure foo(value: Int64); overload;
begin
  Writeln('Int64');
end;

const
  ZeroInt32 = Int32(0);
  ZeroUInt16 = UInt16(0);

begin
  foo(127);
  foo(128);

  foo(32767);
  foo(32768);

  foo(2147483647);
  foo(2147483648);

  foo(9223372036854775807);
  foo(9223372036854775808);

  foo(ZeroInt32);
  foo(ZeroUInt16);
  foo(UInt8(0));
end.

The output is:

Int8
UInt8
Int16
UInt16
Int32
UInt32
Int64
UInt64
Int32
UInt16
UInt8

Let's have a look at another program:

program SO32160057_comparisons;

var
  Int8var:  Int8  = 0;
  Int16var: Int16 = 0;
  Int32var: Int32 = 0;

begin
  if Int8var  <              127  then ;
  if Int8var  <              128  then ;  // line 10
  if Int8var  <        Int16(128) then ;  // line 11
  if Int16var <            32767  then ;
  if Int16var <            32768  then ;  // line 13
  if Int16var <      Int32(32768) then ;  // line 14
  if Int32var <       2147483647  then ;
  if Int32var <       2147483648  then ;  // line 16
  if Int32var < Int64(2147483648) then ;
end.

The compiler emits the following warnings:

(10): W1022 Comparison always evaluates to True
(10): W1023 Comparing signed and unsigned types - widened both operands
(11): W1022 Comparison always evaluates to True
(13): W1022 Comparison always evaluates to True
(13): W1023 Comparing signed and unsigned types - widened both operands
(14): W1022 Comparison always evaluates to True
(16): W1022 Comparison always evaluates to True
(16): W1023 Comparing signed and unsigned types - widened both operands

So, by my empirical analysis, the compiler looks at the value of an integral literal, and determines its type by finding the first type in the following list which can represent the value:

  • Int8
  • UInt8
  • Int16
  • UInt16
  • Int32
  • UInt32
  • Int64
  • UInt64

This rule can be overridden by specifying the type using the typecast syntax. For instance, to declare an Int32 with value 0 you would write Int32(0).


Now let us apply that rule to the concrete example that you give in the question, namely 123456. According to the rules above, the first type in the list which can represent this value is Int32. Also known as Integer.

Now, because this is an unsigned type, you might expect that a comparison against an unsigned UInt32 variable will result in warning W1023, comparing signed and unsigned types. But that is not the case. The compiler recognises that 123456 is a positive value and that we are comparing two positive values. On the other hand, the warning is emitted with -123456.

program SO32160057_123456;

var
  UInt32var: UInt32 = 0;

begin
  if UInt32var >  123456 then ; // line 7
  if UInt32var > -123456 then ; // line 8
end.

The compiler emits the following warnings:

(8): W1022 Comparison always evaluates to True
(8): W1023 Comparing signed and unsigned types - widened both operands
like image 156
David Heffernan Avatar answered Oct 16 '22 23:10

David Heffernan