Assigning a value to an "int": Before setup or in the loop?

What is the difference?

To illustrate it, I tortured old "Blink" a bit:

I can define my int ("delayvalue") and the value of it in the beginning:

/*
  Blink 1
  Turns on an LED on and off for a delay, repeatedly.
  */
 const int led = 13; // Pin 13 has an LED connected 
int delayvalue = 500;

// the setup routine runs once 
void setup() 
{                
    pinMode(led, OUTPUT);     // initialize the digital pin as an output.
}

// the loop routine runs over and over again forever:
void loop() 
{
  digitalWrite(led, HIGH);   // turn the LED on 
  delay(delayvalue);               // wait for a delay
  digitalWrite(led, LOW);    // turn the LED off 
  delay(delayvalue);               // wait for a delay
}

I can also start by defining the int "delayvalue", and later give it a value in the loop:

/*
  Blink 2
  Turns on an LED on and off for a delay, repeatedly.
  */
int led = 13; // Pin 13 has an LED connected 
int delayvalue;

// the setup routine runs once:
void setup() 
{                
    pinMode(led, OUTPUT);     // initialize the digital pin as an output.
}

// the loop routine runs over and over again forever:
void loop() {
  delayvalue = 500;
  digitalWrite(led, HIGH);   // turn the LED on 
  delay(delayvalue);               // wait for a delay
  digitalWrite(led, LOW);    // turn the LED off 
  delay(delayvalue);               // wait for a delay
}

Or I can define the "int delayvalue" in the loop, and assign a value to it at the same time:

/*
  Blink 3
  Turns on an LED on and off for a delay, repeatedly.
  */
int led = 13; // Pin 13 has an LED connected 

// the setup routine runs once:
void setup() 
{                
    pinMode(led, OUTPUT);     // initialize the digital pin as an output.
}

// the loop routine runs over and over again forever:
void loop() 
{
  int delayvalue = 200;
  digitalWrite(led, HIGH);   // turn the LED on 
  delay(delayvalue);               // wait for a delay
  digitalWrite(led, LOW);    // turn the LED off 
  delay(delayvalue);               // wait for a delay
}

Should I just enjoy the artistic freedom.... or is there more to it?

It's all down to a concept called "scope" which defines how and where variables are "visible".
Initialising to the same value every time through "loop()" is just a waste of processor cycles

Thanks (and holy Moses, that was the fastest answer I've ever received!)

In other words, if the value is given by reading an input from a sensor or similar, it must be in the loop. And the loop will read in each time around.
And if it doesn't have to be in the loop, it should be moved outside it.
?

(Of course, nothing is absolute, but as a noob's rule of thumb)

Peter_I:
In other words, if the value is given by reading an input from a sensor or similar, it must be in the loop. And the loop will read in each time around.
And if it doesn't have to be in the loop, it should be moved outside it.

The value should be updated whenever there is a new value to update it. If it's never going to be updated, it should be declared as const in the global scope.

The variable should be declared within the innermost scope it is used. If it isn't used outside of loop(), it shouldn't be declared outside of loop() (although it's not going to kill you if you don't follow this rule). If the value needs to persist between loop() calls, it should be declared as static. If it going to be used in multiple functions, then it can be declared global.

int x;  // no value given, is a global, so defaults to zero before setup or loop run.
int y = 1;     // value specified, is a global set once before setup or loop run
void setup ()
{
  x = 3;   // setup only executes once, so x only gets written once per reset
}

void loop ()
{
  y = 2; // this is a waste of processor cycles
  x = analogRead (A0);  // this is probably sensible
}{

Global scope occurs when a data item is defined outside of any function. You can think of "scope" as being similar to "visibility. Data with global scope can be accessed by any part of the program.

If you define a data item inside a function, it has function block scope and is visible from its point of definition to the closing brace of the function.

If you define a data item within a statement, such as for (int i = 0; i < MAX; i++), variable i has statement block scope and can only be used within the opening and closing braces of the for loop.

What Arrch is trying to tell you is that you should use the most restrictive scope level you can for each data item that still allows you to address the task at hand. This is the general concept of encapsulation, which means you want to hide your data as much as you can. Why? Well, I once worked on a program with over 800,000 lines of code and if some variable goes screwy and has global scope, where should I start looking? If that screwy variable is defined within a function, at least I've narrowed the bug down from 800,000 to maybe a few dozen lines or less. You use scope for the same reason medieval kings hid their daughters in the castle tower...to keep people from messing around with them. You should do the same with your data.

Is it possible to declare something in setup() that is globally accessible? Like my now non-compilable example?

boolean isMaster = true;

void setup()
{
  Serial.begin(115200);
  
    if( isMaster )
      int clients[20];
    else
      int clients[3];
}

void loop()
{
  for ( int i=0; i<(sizeof(clients/clients[0]); i++ )
    Serial.println( clients[i] );
}

Is it possible to declare something in setup() that is globally accessible?

No, that isn't possible, or desirable.

Better look up the "new" operator. You can make an array of variable size with that.