Silly question regarding now()

Constantin

Well-known member
I have a dumb question - why is time_t apparently defined as a int32?

Was this a design choice in order to allow time calculations that preceded 1970?
 
It is a bad habit to use an "int" to be a variable that is NOT mathematical.
Indeed int (being signed) is rather rarely needed or prudent.
Of the zillion lines of code I've written in C/C++, about 5% of 32 bit variables were int. The reset were unsigned int, or the custom in ARM and other MCUs, stdint.h and uint32_t.

lazy use of int instead of unsigned can come back to bite you.
 
I believe it isn't a signed type to deal with times before the begin of the UNIX epoch, but instead so that you can do date relative calculations, i.e. if you want to get yesterday's date, you would subtract (24L*60L*60L, or 86,400) from time_t. However, leap seconds can play havoc with date calculations.
 
I believe it isn't a signed type to deal with times before the begin of the UNIX epoch, but instead so that you can do date relative calculations, i.e. if you want to get yesterday's date, you would subtract (24L*60L*60L, or 86,400) from time_t. However, leap seconds can play havoc with date calculations.
That's right. timer ticks, *nix epoch are examples of variables that are not mathematical in the sense of "natural" numbers where there is no concept of a negative value.
adding and subtracting (natural) numbers overflows the modulus (say, 2**n). In computers (most) with 2's complement signed arithmetic with non-natural whole numbers, and overflow changes the sign.

Some odd/old computers, instead of 2's complement for a signed whole number, used "sign and magnitude" where the most significant bit is the sign bit (1=negative), and the other bits are the magnitude. Ah, we find a negative 0 and a positive 0. Digital logic is easier with 2's complement.
 
But we do have -0.0 in floating point, as well as NaN (not a number). I was on the original ANSI C standards committee (X3J11) and during the original C standards process, there were some manufacturers represented that had challenges with the C language (the one's complement and sign/magnitude folk in particular had problems with unsigned arithmetic).

Lets see if I recall some of things that were challenges.

  • Univac (and maybe DEC-10) had one's complement machines;
  • Burroughs had sign magnitude machines;
  • Univac and DEC-10 had 36 words, but might want 7-bit bytes (the C standard does require that char fit evenly in words with no left over bits to make memcpy work, so those machines needed to use 9-bit 'bytes');
  • IBM used EBCDIC on its mainframes at the time (in EBCDIC, because it came from cards, the letters 'i' and 'j' are not adjacent, and 'I' and 'J' similarly);
  • Pr1me, Data General (my employer at the time) and probably Univac/Dec-10 had different flavors of pointer, as they originally only had pointers to word, and later pointers to characters/bytes within a word were added. IIRC, on the PR1ME system, char * was 48 bits, which was longer than any integer supported by the machine;
  • IBM and Data General used the IBM floating point instead of IEEE 754 (the old IBM format used hexadecimal digits instead of binary, and you would lose 1-2 binary bits of precision on average);
  • The IBM and DEC VMS systems had linkers with strict requirements (and the linkers were controlled by the OS group and not the compiler group -- IIRC, IBM mainframe externals could only be 1-8 characters, all upper case, while VMS was 1-31 characters all upper case);
  • The 80286/80386 compiler vendors had the concept of near and far pointers, and in some situations, the size of a function pointer was a different size than the size of a pointer to data.
 
Last edited:
A the simplicity of the Nova 800. The most significant bit of an address (pointer, though we didn't use that term), if 1, was an indirect flag.
One could easily create infinite indirect loops in machine language.
 
A the simplicity of the Nova 800. The most significant bit of an address (pointer, though we didn't use that term), if 1, was an indirect flag.
One could easily create infinite indirect loops in machine language.

More or less. The later Eclipse computers would raise an error if you had a memory indirection chain of more than 15 loads. In order to get character pointers, they shifted the word pointer left one bit, losing the indirection bit, and using the bottom bit to indicate which byte to addess. Having only 4 general purpose registers, and only 2 of them could be used to hold pointers, did make code generation interesting.
 
Before Teensy 3.0 and Arduino Due, the Time library used an unsigned number. The avr-libc code doesn't have any of the normal C library time functions.

When we started using newlib which does have POSIX time and other stuff, the Time library conflicted. It was changed to signed int to resolve the conflicts.
 
Thank you! Ok, so I may have a rollover issue on my humidifier in 30 years that I can resolve by setting back the clock 40 years, just like the social security administration did to deal with Y2k problems.
 
Back
Top