What does it mean o'377' in Fortran 77? When I tried to print it outputs 255.
print*,"result", o'377'
which returns
result 255
It's an octal (base 8) representation. 377 octal is 255 decimal or FF hex.
This is what they call a boz-literal-constant:
A binary, octal, or hexadecimal constant (boz-literal-constant) is a sequence of digits that represents an ordered sequence of bits. Such a constant has no type.
R764 boz-literal-constant is binary-constant, octal-constant or hex-constant
R765 binary-constant is B ’ digit [ digit ] ... ’ or B " digit [ digit ] ... "
C7107 (R765) digit shall have one of the values 0 or 1.
R766 octal-constant is O ’ digit [ digit ] ... ’ or O " digit [ digit ] ... "
C7108 (R766) digit shall have one of the values 0 through 7.
R767 hex-constant is Z ’ hex-digit [ hex-digit ] ... ’ or Z " hex-digit [ hex-digit ] ... "
R768 hex-digit is digit or A through F
C7109 (R764) A boz-literal-constant shall appear only as a data-stmt-constant in a DATA statement, or where explicitly allowed in 16.9 as an actual argument of an intrinsic procedure.
source: Fortran 2018 Standard Section 7.7
As is seen from the Standard, a boz-literal constant has no type and can only appear in data-statements or some implicit functions. This implies that the notation:
print*,"result", o'377'
is invalid code since the octal representation has no type. The correct code would have read:
print *, "result", INT(o'377')
However, in Fortran 90 this would also have been invalid as one could only use boz-literal constants in DATA-statements. The only valid way would have been:
INTEGER :: constant
DATA constant /o'377'/
print *, "result", constant
note: Some compilers allow the usage of boz-literal-constants outside of the DATA statement. Solaris-studio converts them to the type required by the context. Other compilers might have different opions on that.
Related
When an integer is initialized as int a = 010, a is actually set to 8, but for int a = 10, a is set to 10.
Can anyone tell me why a is not set to 10 for int a = 010?
Because it's interpreting 010 as a number in octal format. And in a base-8 system, the number 10 is equal to the number 8 in base-10 (our standard counting system).
More generally, in the world of C++, prefixing an integer literal with 0 specifies an octal literal, so the compiler is behaving exactly as expected.
0 before the number means it's in octal notation. So since octal uses a base of 8, 010 would equal 8.
In the same way 0x is used for hexadecimal notation which uses the base of 16. So 0x10 would equal 16 in decimal.
In C, C++, Objective C and related languages a 0 prefix signifies an octal literal constant, so 010 = 8 in decimal.
Leading 0 in 010 means that this number is in octal form. So 010 means 8 in decimal.
In a C++ class I've the following code/while loop:
uint8_t len = 0;
while (*s != ',') {
len = (uint8_t)(len + 1u);
++s;
}
return (len);
The outcome should be a value between 0 and max 20.
As I receive a strange outcome, and started debugging. When I step through this
I get the following values for the variable Len:
‘\01’, ‘\02’, ‘\03’, ‘\04’, ‘\05’, ‘\06’, ‘\a’, ‘\b’, ‘\t’
I don’t understand the change from ‘\06’ to ‘\a’!
Can somebody explain this? I expect that the Len value is simply increased by 1 until character array pointer s hits the ',' char.
The values are correct, but your debugger interprets them as char type, not an integer type.
You can see escape sequences used in C++ here (and the corresponding values in ASCII).
\01 - 1 in octal, 1 in decimal
\02 - 2 in octal, 2 in decimal
...
\06 - 6 in octal, 6 in decimal
\a - equivalent to \07, the ASCII code to use the computer bell
\b - equivalent to \010 (10 octal, 8 decimal), the ASCII code for "backspace" character
\t - equivalent to \011 (11 octal, 9 decimal), the ASCII code for tabulator
etc.
I don't know if you can change the way your debugger interprets the data. Worst case, you can always print the value after casting it to int.
(gdb)p static_cast<int>(len)
When assigning a binary value and a hexadecimal value directly you can do it as follows (respectively):
uint8_t val1 = 0b10101;
uint8_t val2 = 0xFF;
What does the 0b and 0x mean? Specifically the 0 at the front. Can you have other values instead of 0?
Also as another curious question, what other characters can go in the place of b and x? Is there one for octal as an example?
Any and all integer literals you can create are summarized in the C++ standard by the grammar production at [lex.icon]
integer-literal:
binary-literal integer-suffixopt
octal-literal integer-suffixopt
decimal-literal integer-suffixopt
hexadecimal-literal integer-suffixopt
binary-literal:
0b binary-digit
0B binary-digit
binary-literal 'opt binary-digit
octal-literal:
0
octal-literal 'opt octal-digit
decimal-literal:
nonzero-digit
decimal-literal 'opt digit
hexadecimal-literal:
hexadecimal-prefix hexadecimal-digit-sequence
binary-digit:
0
1
octal-digit: one of
0 1 2 3 4 5 6 7
nonzero-digit: one of
1 2 3 4 5 6 7 8 9
hexadecimal-prefix: one of
0x 0X
hexadecimal-digit-sequence:
hexadecimal-digit
hexadecimal-digit-sequence 'opt hexadecimal-digit
hexadecimal-digit: one of
0 1 2 3 4 5 6 7 8 9
a b c d e f
A B C D E F
As we can deduce from the grammar, there are four types of integer literals:
Plain decimal, that must begin with a non-zero digit.
Octal, any number with a leading 0 (including a plain 0).
Binary, requiring the prefix 0b or 0B.
Hexadecimal, requiring the prefix 0x or 0X.
The leading 0 for octal numbers can be thought of as the "O" in "Octal". The other prefixes use a leading zero to mark the beginning of a number that should not be interpreted as decimal. "B" is intuitively for "binary", while "X" is for "hexadecimal".
0b (or 0B) denotes a binary literal. C++ has allowed it since C++14. (It's not part of the C standard yet although some compilers allow it as an extension.) 0x (or 0X) is for hexadecimal.
0 can be used to denote an octal literal. (Interestingly 0 itself is an octal literal). Furthermore you use the escape sequence \ followed by digits to be read in octal: this applies only when defining const char[] literals using "" or char or multicharacter literals using ''. The '\0' notation that you often see to denote NUL when working with strings exploits that.
In the absence of a user defined literal suffix, any numeric literal starting with a non-zero is in denary.
There are rumblings in the C++ world to use 0o for an octal literal and perhaps even drop support for the leading zero version. Although that would be an hideous breaking change.
What does the 0b and 0x mean?
They mean that the nuneric literal is respectively in binary and hexadecimal base.
Can you have other values instead of 0?
A numeric literal starting with a non zero digit will be a decimal literal.
Also as another curious question, what other characters can go in the place of "b" and "x"?
Besides b and x, any octal digit can go there in which case it is the most significant digit of an octal literal.
When I use MBCS and msvcr120.dll (12.0.40660.0) I get unexpected results when using %g with sprintf to convert a double to a string. The documentation for %g says default precision will be 6. Why am I seeing the results below?
{
double d = 1234567.00;
char buf[100];
sprintf_s(buf, sizeof(buf), "%g", d);
//result is 1.23457e+006
}
Why is the result 1.23457e+006 instead of 1.23456e+006? Does truncation occur after 6 digits?
Why am I seeing the results below?
This is how the C standard specifies the format in section [Formatted input/output functions] (C++ delegates the specification):
f,F
A double argument representing a floating-point number is converted to decimal notation in style [−]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is zero and the # flag is not specified, no decimal-point character appears. If a decimal-point character appears, at least one digit appears before it. The value is rounded to the appropriate number of digits.
e,E
A double argument representing a floating-point number is converted in the style [-]d.ddde±dd, where there is one digit (which is nonzero if the argument is nonzero) before the decimal-point character and the number of digits after it is equal to the precision; if the precision is missing, it is taken as 6; if the precision is zero and the # flag is not specified, no decimal-point character appears. The value is rounded to the appropriate number of digits. The E conversion specifier produces a number with E instead of e introducing the exponent. The exponent always contains at least two digits, and only as many more digits as necessary to represent the exponent. If the value is zero, the exponent is zero.
A double argument representing an infinity is converted in one of the styles [-]inf or [-]infinity - which style is implementation-defined. A double argument representing a NaN is converted in one of the styles [-]nan* or **[-nan](n-char-sequence) - which style, and the meaning of any n-char-sequence, is implementation-defined. The F conversion specifier produces INF,INFINITY, or NAN instead of inf,infinity ,or nan, respectively.
g,G
A double argument representing a floating-point number is converted in style f or e (or in style F or E in the case of G conversion specifier), depending on the value converted and the precision. Let P equal the precision if nonzero, 6 if the precision is omitted, or 1 if the precision is zero. Then, if a conversion with style E would have an exponent of X:
if P > X ≥ -4, the conversion is with style f (or F) and precision P - (X + 1).
otherwise, the conversion is with style e (or E) and precision P - 1.
Why is the result 1.23457e+006 instead of 1.23456e+006?
Because the default precision is 6, and the value is rounded.
The default rounding mode (according to IEEE 754) is "round to nearest and ties to even". The next and previous round values of 1.234567 are 1.23457 and 1.23456. 1.23457 is nearer, so 1.234567 rounds to 1.23457.
Is it possible to initialize a float variable with a hexadecimal float point value in C++?
Something like this:
double d = 0x011.1; // wrong!
The Technical Specification P0245 Hexadecimal floating literals for C++ has been voted into C++17 at the ISO C++ Standards Committee in Jacksonville, Florida on February 2016.
The language C99 also has this feature, and the C++ feature is compatible.
However, as pointed by the Lưu Vĩnh Phúc's comment, the syntax 0x011.1 is not part of the standard. The binary exponent is mandatory for hexadecimal floating-point literals. One reason is to avoid ambiguity of the trailing F within 0x011.1F. Is it the hex digit F of the fractional part or the floating-suffix meaning float?
Therefore append p followed by a positive or negative decimal number, for example: 0x011.1p0.
See the more readable page floating literal page on cppreference.com.
0x | 0X hex-digit-sequence
0x | 0X hex-digit-sequence .
0x | 0X hex-digit-sequence(optional) . hex-digit-sequence
Hexadecimal digit-sequence representing a whole number without a radix separator. The exponent is never optional for hexadecimal floating-point literals: 0x1ffp10, 0X0p-1, 0x1.p0, 0xf.p-1, 0x0.123p-1, 0xa.bp10l
The exponent syntax for hexadecimal floating-point literal has the form
p | P exponent-sign(optional) digit-sequence
exponent-sign, if present, is either + or -
suffix, if present, is one of f, F, l, or L. The suffix determines the type of the floating-point literal:
(no suffix) defines double
f F defines float
l L defines long double
See also the current working draft C++17, chapter § 2.13.4 Floating literals on GitHub: https://github.com/cplusplus/draft/raw/master/papers/n4604.pdf
floating-literal:
decimal-floating-literal
hexadecimal-floating-literal
decimal-floating-literal:
fractional-constant exponent-partopt floating-suffixopt
digit-sequence exponent-part floating-suffixopt
hexadecimal-floating-literal:
hexadecimal-prefix hexadecimal-fractional-constant binary-exponent-part floating-suffixopt
hexadecimal-prefix hexadecimal-digit-sequence binary-exponent-part floating-suffixopt
fractional-constant:
digit-sequenceopt . digit-sequence
digit-sequence .
hexadecimal-fractional-constant:
hexadecimal-digit-sequenceopt . hexadecimal-digit-sequence
hexadecimal-digit-sequence .
exponent-part:
e signopt digit-sequence
E signopt digit-sequence
binary-exponent-part:
p signopt digit-sequence
P signopt digit-sequence
sign: one of
+ -
digit-sequence:
digit
digit-sequence ’opt digit
floating-suffix: one of
f l F L
1 A floating literal consists of an optional prefix specifying a base, an integer part, a radix point, a fraction part, an e, E, p or P, an optionally signed integer exponent, and an optional type suffix. The integer and fraction parts both consist of a sequence of decimal (base ten) digits if there is no prefix, or hexadecimal (base sixteen) digits if the prefix is 0x or 0X. The literal is a decimal floating literal in the former case and a hexadecimal floating literal in the latter case. Optional separating single quotes in a digit-sequence or hexadecimal-
digit-sequence are ignored when determining its value. [ Example: The literals 1.602’176’565e-19 and 1.602176565e-19 have the same value. — end example ] Either the integer part or the fraction part (not both) can be omitted. Either the radix point or the letter e or E and the exponent (not both) can be omitted from a decimal floating literal. The radix point (but not the exponent) can be omitted from a hexadecimal floating literal. The integer part, the optional radix point, and the optional fraction part, form the significand of the floating literal. In a decimal floating literal, the exponent, if present, indicates the power of 10 by which the significand is to be scaled. In a hexadecimal floating literal, the exponent indicates the power of 2 by which the significand is to be scaled. [ Example: The literals 49.625 and 0xC.68p+2 have the same value. — end example ] If the scaled value is in the range of representable values for its type, the result is the scaled value if representable, else the larger or smaller representable value nearest the scaled value, chosen in an implementation-defined manner.
The type of a floating literal is double unless explicitly specified by a suffix. The suffixes f and F specify float, the suffixes l and L specify long double. If the scaled value is not in the range of representable values for its type, the program is ill-formed.
As unwind has advised, you can use strtof(). The following snippet decodes Hexadecimal floating literals (without C++17):
#include <iostream>
#include <cstdlib>
#include <cstdio>
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cout <<"Usage: "<< argv[0] <<" 0xA.Bp-1 => Decode hexfloat" "\n";
return 1;
}
long double l;
double d;
float f;
std::cout <<"Decode floating point hexadecimal = "<< argv[1];
//std::istringstream(argv[1]) >> std::hexfloat >> d;
l = std::strtold(argv[1],NULL); if(errno == ERANGE) std::cout << "\n" "std::strtold() range error";
d = std::strtod (argv[1],NULL); if(errno == ERANGE) std::cout << "\n" "std::strtod() range error";
f = std::strtof (argv[1],NULL); if(errno == ERANGE) std::cout << "\n" "std::strtod() range error";
std::cout <<"\n" "long double = "<< std::defaultfloat << l <<'\t'<< std::hexfloat << l
<<"\n" "double = "<< std::defaultfloat << d <<'\t'<< std::hexfloat << d
<<"\n" "float = "<< std::defaultfloat << f <<'\t'<< std::hexfloat << f <<'\n';
}
No, C++ doesn't support that for literals, it's not part of the standard.
A non-portable solution is to use a compiler that adds this as an extension (GCC does this).
A portable workaround is to parse them from string literals at runtime using e.g. strtof() or strtod() for double.
As pointed out in a comment, you can also opt to store the constants in a C file. Doing so requires that you have access to a C99 compiler though, since hex float literals is a C99-level feature. Since environments with a new C++ compiler but without a C99 compiler (read: Visual Studio) are quite common, that might not be a workable solution.
Update: C++17 supports hexadecimal floating point literals.