Is there a difference between these two declarations?

Krupski:
Is the fact that the first and #3 point to the same memory location due to compiler optimization?

I would think that since they were declared separately, they would be distinct entities in memory even though they contain the same data, UNLESS the compiler is smart enough to see that they are the same?

The pointers occupy distinct areas in memory. What they point to doesn't.

str2 and str4 in my example are not pointers, they are arrays. Hence they occupy different addresses.

This expanded sketch demonstrates that:

const char *str = "Hello";
const char str2[] = "Hello";
const char *str3 = "Hello";
const char str4[] = "Hello";

void setup ()
  {
  Serial.begin (115200);

  Serial.println ((unsigned int) str, HEX);
  Serial.println ((unsigned int) str2, HEX);
  Serial.println ((unsigned int) str3, HEX);
  Serial.println ((unsigned int) str4, HEX);
  
  Serial.println ("Addresses of variables:");

  Serial.println ((unsigned int) &str, HEX);
  Serial.println ((unsigned int) &str2, HEX);
  Serial.println ((unsigned int) &str3, HEX);
  Serial.println ((unsigned int) &str4, HEX);
  
  }  // end of setup

void loop () { }

Output:

118  <-- str
122  <-- str2
118  <-- str3
128  <-- str4
Addresses of variables:
11E  <-- address of str
122  <-- address of str2
120  <-- address of str3
128  <-- address of str4

Note that for the arrays (str2 and str4) the "pointer" is the variable.

For the pointers (str and str3) the variables are at unique addresses (0x11E and 0x120) but what they point to is at the same address, as the compiler has realized it can point them both to the string "Hello" (stored at 0x118).