The code works, but issues a warning about an incompatible type pointer

Trying to figure out how I learn C code, I wanted to check something. It worked as expected, but gives a warning

Warning 1 assignment from an incompatible pointer type [enabled by default]

The code is simple. All I do here is switch the B7 PIN to atmega2560. I have an LED connected to it, and I see it blink, so I know that it works as expected.

Can someone explain why I see this error, even if it is executed, as expected? The code is as follows:

#include <avr/io.h> #include <util/delay.h> void main(void) { int *ptr; ptr = &PORTB; // This line throws the warning DDRB = (1 << 7); while(1) { *ptr = (1 << 7); _delay_ms(1000); *ptr = (0 << 7); _delay_ms(1000); } } 

PORTB is an 8-bit register that has a bit per pin to control whether this pin is HIGH or LOW.

So far, I'm glad it works. But these warnings annoy me.

+4
source share
2 answers
 int *ptr; ptr = &PORTB; // This line throws the warning 

PORTB is a volatile unsigned char , defined roughly as follows:

 *(volatile unsigned char *) 0xBEEF 

Change the ptr declaration to volatile unsigned char * :

 volatile unsigned char *ptr; ptr = &PORTB; 
+9
source

PORTB is probably not defined as int , which means that when you take the address of PORTB , you will not get int * . If you are sure that you are right and that you can use int * for PORTB , you can use a throw to tell the compiler that it does not need to worry. You can do it as follows:

 ptr = (int*)&PORTB 

Go to the PORTB definition and let us know what type it is.

Edit 2:

I wrote an explanation why you SHOULD NOT USE MY ANSWERED RESPONSE, and by the time I corrected it, I see that @ouah has already posted the correct answer, so I ask you to use it instead of mine. For an explanation of why, read my Editing 1 below.

Change 1:

My guess was that you knew that PORTB was int and that you were dropping it from void* . Thank you @ H2CO3 for pointing out that this is actually (*(volatile uint8_t *)(0x25)) , which basically means that PORTB is volatile uint8_t .

In this case, NEVER use it for int ! If this worked, it means that your machine is probably a bit endian , and you should not rely on it.

To correctly explain this, give a simple example:

We have this in mind:

 Address Value 0x02 7 0x03 11 

Note: 7 is 0x07 in hexadecimal and 00000111 in binary, and 11 is 0x0B in hexadecimal and 00001011 in binary

Now we have 2 pointers:

 uint8_t* BytePointer; int* IntPointer; // int is either 2 or 4 bytes, we will assume it is 2 bytes. int Value16; uint8_t Value8; // Let set both to point to our fake memory address BytePointer = (uint8_t*) 0x02; IntPointer = (int*) 0x02; // Now let see what value each holds? Value8 = *BytePointer; Value16 = *IntPointer; // Value8 will contain 0x07 // Value16 will contain 0x0B07 on a Little Endian machine // Value16 will contain 0x070B on a Big Endian Machine 

This example shows what happens when we read values ​​from pointers, but what about spelling? Let the same variables as before be stored and write down some values

 *BytePointer = 5; 

Now the memory will look like this:

 0x02 5 0x03 11 

What about an int pointer?

 *IntPointer = 5; 

Since a int is two bytes, it will change two bytes:

 // Little endian 0x02 5 0x03 0 // Big endian 0x02 0 0x03 5 

Therefore, if you use PORTB as an int , each time you assign it, you write 2 bytes, one at the address PORTB and once in a row. I hope everything after that doesn't matter ... You shouldn't do this, so you should use uint8_t* if you really want to use pointers.

But by the time I got to explain everything correctly, @ouah had already posted the correct answer. Please contact him for how this should be done.

+5
source

Source: https://habr.com/ru/post/1491344/


All Articles