Different data sizes in program usage

TheMemberFormerlyKnownAsAWOL:
No, if you put the value of a constant into a variable, you will always be able to change the value of the variable.

Read it again.

OK, I know the comment mentioned a reference pointer, which basically I thought it's a variable.

The way I understand it constexpr fixes a loophole in const. Where if you create a reference or pointer to a const variable it can then be changed and is no longer actually constant

So if I declared a constexpr:

constexpr int var = 10;
int *var_ptr;
var_ptr = var;
*var_ptr = 20;

OK, that gave me error. Well I guess I didn't understand what is in the reply #33.

That should be var_ptr = &var;

What you do sometimes see is someone declaring a char* and initializing it to point to a string constant, then latet in the code using the pointer to alter the string.

Experiments arising from a discussion in another thread showed that changing the string associated with a char pointer variable left holes in the memory, which could have nasty effects down the line because it leaves holes in the memory

Try this

char * arrayA[4] = {"short0", "short1", "short2", "short3"};

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  printArray();
  arrayA[0] = "longer0";
  arrayA[1] = "longer1";
  arrayA[2] = "longer2";
  arrayA[3] = "longer3";
  printArray();
  arrayA[0] = "even more characters0";
  arrayA[1] = "even more characters1";
  arrayA[2] = "even more characters2";
  arrayA[3] = "even more characters3";
  printArray();
}

void loop()
{
}

void printArray()
{
  for (int x = 0; x < 4; x++)
  {
    int add = &arrayA[x][0];
    Serial.print("pointer address : ");
    Serial.print(add);
    Serial.print("\tdata : ");
    Serial.println(arrayA[x]);
  }
  Serial.println();
}

Whandall:
A constant has to be placed in RAM if its address is taken, because there is no concept of a pointer to flash.

I was under the impression that there could be pointers to flash, such as declaring a number of char arrays in flash, then declaring an array of pointers to those char arrays, again stored in flash. Common technique for storing large amounts of strings, and appears to work, but you do need to be careful to properly declare everything as const, and use specific instructions to let the compiler know to access flash memory instead of ram.

The is also the point that some processors have the flash memory in the same address space as ram.

UKHeliBob:
Experiments arising from a discussion in another thread showed that changing the string associated with a char pointer variable left holes in the memory, which could have nasty effects down the line because it leaves holes in the memory

Try this

char * arrayA[4] = {"short0", "short1", "short2", "short3"};

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  printArray();
  arrayA[0] = "longer0";
  arrayA[1] = "longer1";
  arrayA[2] = "longer2";
  arrayA[3] = "longer3";
  printArray();
  arrayA[0] = "even more characters0";
  arrayA[1] = "even more characters1";
  arrayA[2] = "even more characters2";
  arrayA[3] = "even more characters3";
  printArray();
}

void loop()
{
}

void printArray()
{
  for (int x = 0; x < 4; x++)
  {
    int add = &arrayA[x][0];
    Serial.print("pointer address : ");
    Serial.print(add);
    Serial.print("\tdata : ");
    Serial.println(arrayA[x]);
  }
  Serial.println();
}

I know its incorrect, but is very common because the IDE hides the warnings.

david_2018:
I was under the impression that there could be pointers to flash, such as declaring a number of char arrays in flash, then declaring an array of pointers to those char arrays, again stored in flash.

Yes, you can access flash, but not by de-referencing a pointer but only by special instructions.

All the code resides in flash anyway,
so a function pointer is the closest you can get to a real pointer to flash that works directly.

There is no "pointer to flash data" type that knows it points to flash in the AVR C++ ecosystem, as far as I know.

Hutkikz:
Trust me your not alone. I've been at this for a good while now and am only a tiny bit further along than you. TBH I'm kinda proud of how I seem to be doing in this thread. Usually others would have needed to correct me by now. :grin:

That's depends on how much anyone's experience in something. There are a lot of stuff to learn, programming aspects are so many and doing one thing to me these days, could take me up to several days to figure it out or get a recommendation or solution from online.

Let's see if I can keep it up: A constant should never change during run time. Therefore it does not need to be placed in memory(RAM). it can instead be placed in the program space(Flash) and most of the time it is.

A pointer is an ordinary variable that contains a special type of data. That data is the address of another variable. If you have a address of something you can then change the value of the data contained in that address. That address must be in RAM and not in Flash.

Yep for sure.

Now if you create a pointer to a constant then the compiler is forced to place that constant in RAM so that the pointer has an address to point to.

Yep, I got an error for that just now.

The loophole is that while you still cannot change the value of this constant directly it is possible to change it by using the pointer. Therefore the constant is no longer actually constant and you will get no errors from the compiler. When you use constexpr the compiler will not allow you to create a pointer( or reference) to it.

I tried an example that didn't work out, could you post code so I know how you do it ?

The reality is that with the small programs that will fit on a arduino usually written by only one person it is not likely you will make pointer to a constant but constexpr guarantee's that you can't do so by mistake.

So, what you mean here ? What I understood is that either ways you can't use a pointer to const, is that what you mean ?

Whandall:
Taking the address of a constant does not allow for changes to the constant, it is still a pointer to a const object.
You have to cast it to something non-const to allow changes.

A constant has to be placed in RAM if its address is taken, because there is no concept of a pointer to flash.

constexpr int var = 10;
int *var_ptr;

int main()
{
    var_ptr = &var;
    return 0;
}

This issued an error:

main.cpp|16|error: invalid conversion from 'const int*' to 'int*' [-fpermissive]|

david_2018:
What you do sometimes see is someone declaring a char* and initializing it to point to a string constant, then latet in the code using the pointer to alter the string. Can lead to odd behavior when the compiler sees multiple occurences of the string and optimizes the code to only store a single copy.

OK, so what is the solution of this problem ?
If the string could be used in multiple functions, so it has to be in global and in functions, I use a pointer to reference to it. Is that a scenario that you mean here ?
For example, also I have array of image I want to send to glcd, so I have to use a pointer to that array. Is this the case ?

For example, this is the most function for me that worked with progmem that I learned that it put data in flash and I read it with progmem functions:

void glcd_img(const uint8_t *img){
	if(!function_lock){
		buf_cnts = 2; buf_cntr = 0;	lcd_cmdt = CMD;

		data_buf[0] = y < 32 ? 0x80+y : 0x80+y-32;        
		data_buf[1] = y < 32 ? 0x80+x : 0x88+x;
		data_buf[2] = pgm_read_byte_near(&img[(y*16)+(x*2)]);          // this one
		data_buf[3] = pgm_read_byte_near(&img[(y*16)+((x*2)+1)]);      // this one too
	
		x++; if(x>7){y++;x=0;}
		if(y>64){function_init_lock = 0; lcd_st_flag = DONE;}
		function_lock = 1;
	}
	glcd_manager();
}

Array example:

const unsigned char img[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ... etc.
};