Why does it work without issues?

I compiled and tested below code before posting it in another thread here and I'm curious as to why the code works as expected with delays of 15 minutes and 45 minutes.

void loop()
  // some debug
  printTime("relay on at: ");
  // set pin high
  digitalWrite(relaypin, HIGH);
  // delay 15 minutes

  // some debug
  printTime("relay off at: ");
  // set pin low
  digitalWrite(relaypin, LOW);
  // delay 45 minutes

The question is specifically about the delay function that takes an unsigned long as a parameter.

I seem to remember from years ago (Linux / C) that I had to append something like 'UL' to the number to tell the compiler that it was an unsigned long. I however did not specifically do that in this case and it works correctly.

Is my memory wrong, did compilers evolve or ... ?

C is not my native language (I started programming in 1962, in FORTRAN), but I use unsigned longs all the time in the Arduino IDE. As long as you declared it as "unsigned long" before referencing it in code, everything seems fine. (One of my major complaints about C is there seem to be too many variations from one version to the next.)

Moved to Programming at the original poster's request.

That's weird ... this is the first question I've seen asking why something works. delay()

I've noticed this before. Under some circumstances avr-gcc makes the appropriate choice to use unsigned long for a numeric constant even if "UL" is not specified. Under other circumstances, it does not make that choice. I don't know what the rule is, though.

The rule is actually very simple. If the constant fits in an int then int is the datatype. Otherwise, if the constant fits in a long then long is the datatype. Otherwise, if the constant fits in a long long then long long is the datatype. Otherwise the constant is float.

900000 does not fit in an int but does fit in a long so the datatype is long.

However, including the suffix makes your (the programmer's) intent crystal clear to others including your future self.

Perhaps the OP has half-remembered a situation like delay (60 * 1000); where the intention is to delay a minute, but the reality is somewhat different.
Here, the constants all fit the default "int", but the result of the expression does not.