Below is an arduino program which demonstrates some basic principles about pointers.
Keep in mind, memory pointers (i.e. pointers to variables) are pointers to SRAM memory, while function pointers are pointers to flash memory. The AVR uses a modified Harvard Architecture, which allows the contents of the instruction memory to be accessed as if it were data. However, there are restrictions imposed upon access to flash memory. Most modern computers that are documented as Harvard Architecture (like the arduino) are, in fact, Modified Harvard Architecture.
So, considering the different types of memory in an 8-bit AVR µC, there are several overlapping addresses. For example, there is a 0x0000 address for each type, SRAM, flash and EEPROM. SRAM can be addressed via standard C pointers. Flash functions can be addresses per standard C pointers, however data placed in flash requires the use of the PROGMEM routines found in pgmspace.h. And finally EEPROM requires the use of the EEPROM routines found in eeprom.h.
Simple demonstration program:
// //pointers by example // void setup() { char text[32]; Serial.begin(9600); // //pointer basics // uint8_t n; //declare a byte uint8_t *p; //declare a pointer to any uint8_t size variable n = 0x11; //initialize n p = &n; //initialize p to the address of n (p points to n) sprintf(text, " n = %x (n)\n", n); Serial.print(text); sprintf(text, "&n = %x (address of n)\n", &n); Serial.print(text); sprintf(text, " p = %x (address of n)\n", p); Serial.print(text); sprintf(text, "&p = %x (address of p)\n", &p); Serial.print(text); sprintf(text, "*p = %x (n)\n", *p); Serial.print(text); *p = 0x22; //assign value to what p points at (n) sprintf(text, "After *p = 0x22, n = %x\n", n); Serial.print(text); Serial.println(); // //pointer arithmetic // uint8_t a[] = { 1, 2, 3 }; //declare an array uint8_t *pa = a; //declare pa and initailize to point to a pa = a; //does same as above sprintf(text, " a[0] = %x\n", a[0]); Serial.print(text); sprintf(text, "&a[0] = %04x (address of a)\n", &a[0]); Serial.print(text); sprintf(text, " pa = %04x (address of a)\n", pa); Serial.print(text); sprintf(text, " *pa = %x (a[0])\n", *pa); Serial.print(text); pa += 1; //increment pointer sprintf(text, "After increment, pa = %04x\n", pa); Serial.print(text); sprintf(text, " *pa = %x (a[1])\n", *pa); Serial.print(text); Serial.println(); // //machine endianness == little endian // uint32_t n32 = 0x12345678; //declare and initialize 32-bit number (not order of digits) uint8_t* pn = (uint8_t *)&n32; //declare uint8_t pointer to 1st byte of 32-bit number for (uint8_t i=0; i<4; i++) { //iterate through all 4-bytes of n32, noting order of digits sprintf(text, "%p: %02x \n", pn, (uint8_t)*pn++); Serial.print(text); } Serial.println(); // //function pointer // int16_t (*fptr)(int16_t); //declare a function pointer int16_t x = 5; //initalze x for demonstration fptr = square; //point fptr to square() function //call square using function pointer sprintf(text, "%d squared is %d\n", x, fptr(x)); Serial.print(text); //note: fptr is a word address sprintf(text, " fptr = %04x (address of function square()\n", fptr); Serial.print(text); sprintf(text, "&fptr = %04x (address of fptr)\n", &fptr); Serial.print(text); } //example function int16_t square(int16_t n) { return n*n; } void loop() { }
Clear explanation to help to understand addresses and pointers!!!!! Thank you!!!!!!!