Understanding casting in c

Hi,

I have a function declared as:

uint8_t * get_live_reading(int *readinglen)

So this function returns a pointer of uint8_t and takes a pointer of type int.

In my main(), if I try compile the code below I get the error:

error: assignment makes integer from pointer without a cast

I understand that this is because I am trying to set address which is an int equal to the pointer that get_live_reading() returns.

int address, value;
case 'R':
address = get_live_reading(& value);
printf("Picture is at [%x] with length [%x] \r\n",address,value);

Now, if I do the following, it compiles ok.

My question is, why does putting (int) before get_live_reading() fix this error.

int address, value;
case 'R':
address = (int)get_live_reading(& value);
printf("Picture is at [%x] with length [%x] \r\n",address,value);

Your address variable is not a pointer.

The address is int (2 bytes), data type at this place in memory is unknown. Similar situation like EEPROM memory is addressed with uint16_t (2 bytes). In C language address is pointer like 'uint8_t *'. It is pointer to a byte and the size of address is 2 bytes on AVR but on 32-bit system it is 4 bytes. So no fixed size from system to system.
The C compiler protects against incorrect assignment, but if developer is decided that it is correct, he can use cast. In your case it is assignment from 2 byte pointer (address) to 2 byte integer which is not an address.

My question is, why does putting (int) before get_live_reading() fix this error.

that's because you transform the address that is returned (the pointer in memory towards the uint8_t) into an int thus the compiler is happy to save it into an int.

a pointer (a memory address) in standard basic Arduino fits on 2 bytes, an int fits on 2 bytes - all works smoothly.

Now that's not the best way to do this because

1/ int are signed, so if the returned pointer was to be 0x8000 for example (which is 32768 - on the right arduino with plenty of memory) then address which is a signed int would be set to -32768...

2/ it's better to do the right thing. the function returns a pointer and you want to store it, declare a pointer storage uint8_t * address;

try this for example

void setup() {
  Serial.begin(115200);
  uint8_t pointer0;
  uint8_t pointer1;
  uint8_t pointer2;
  uint8_t pointer3;
  Serial.print("Ox"); Serial.print((uint16_t) &pointer0, HEX); Serial.print(" --> ");  Serial.println((uint16_t) &pointer0, DEC);
  Serial.print("Ox"); Serial.print((uint16_t) &pointer1, HEX); Serial.print(" --> ");  Serial.println((uint16_t) &pointer1, DEC);
  Serial.print("Ox"); Serial.print((uint16_t) &pointer2, HEX); Serial.print(" --> ");  Serial.println((uint16_t) &pointer2, DEC);
  Serial.print("Ox"); Serial.print((uint16_t) &pointer3, HEX); Serial.print(" --> ");  Serial.println((uint16_t) &pointer3, DEC);
}

void loop() {}

Your function should be doing pass by reference:

uint8_t * get_live_reading(int &readinglen);

Then, call it:

   int value;
   uint8_t *pReading = get_live_reading(value);

(though I can't really guess why the function returns a pointer and populates an int).

C is a strongly-typed language. In general, every value has a type, and to treat a value as some other type, you need to cast it. The exception is certain standard promotions - int to long, that sort of thing.

The short answer is: "that's the way the C++ language works".

I understand that this is because I am trying to set address which is an int equal to the pointer that get_live_reading() returns.

Typically, things that "set an address" take a pointer, and that's how they are declared.

The main circumstance when you'd be treating an adress as an int was when you wanted the offset of something in an array. But C
1 - treats arrays as a pointer to their first element
2 - permits you to subtract pointers of the same type
3 - when pointers are subtracted, the result is divided by the thing the pointer points at.

int[] a = { 3, 6, 7, 2 ,8, 0 };

int *x = find_number(7, a);
int *y = find_number(3, a);

int offs3_7 = y-x;  // this will set offs3_7 to -2.

Delta_G:
(Sorry, no Arduino handy to test and if I'm wrong then I need to get that cleared up)

Atmel Studio is perfect tool for tracing the program (for Atmel processors of course) and for observing how the things work in C and also on MCU.