在学习C代码时尝试一下,我想测试一下。它按预期工作,但抛出警告
警告1来自不兼容指针类型的分配[启用 默认]
代码很简单。我在这里所做的就是在atmega2560上切换PIN B7。我有一个LED挂钩,我可以看到它闪烁,所以我知道它按预期工作。
有人可以解释为什么我看到这个错误,即使它按预期执行了吗? 代码如下:
#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是一个8位寄存器,每个引脚有一位用于控制该引脚是高电平还是低电平。
现在,我很高兴它有效。但是这些警告让我烦恼。
答案 0 :(得分:9)
int *ptr;
ptr = &PORTB; // This line throws the warning
PORTB
是volatile unsigned char
定义的类似内容:
*(volatile unsigned char *) 0xBEEF
将您的ptr
声明更改为volatile unsigned char *
:
volatile unsigned char *ptr;
ptr = &PORTB;
答案 1 :(得分:5)
PORTB
可能未被定义为int
,这意味着当您获取PORTB
的地址时,您将无法获得int *
。如果您确定自己是正确的并且可以使用int *
作为PORTB
,则可以使用强制转换来告诉编译器它不需要担心。你可以像这样投射:
ptr = (int*)&PORTB
转到PORTB
的定义,让我们知道它是什么类型。
编辑2:
我已经写了一个解释为什么你不应该使用我上面的答案,当我到处纠正它时,我发现@ouah已经发布了正确答案所以我请你用它而不是我的。有关原因的解释,请阅读下面的编辑1 。
修改1:
我的假设是您知道PORTB
是int
并且您是从void*
投出来的。感谢@ H2CO3指出它实际上是(*(volatile uint8_t *)(0x25))
,这基本上意味着PORTB
是volatile uint8_t
。
在这种情况下,你永远不应该把它投到int
!如果这有效,则意味着您的机器可能是little endian,您不应该依赖它。
为了正确解释,我们设置一个简单的例子:
我们在记忆中有这个:
Address Value
0x02 7
0x03 11
注意:7为十六进制0x07,二进制为00000111,十六进制为11 0x0B,二进制为00001011
现在我们有2个指针:
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's set both to point to our fake memory address
BytePointer = (uint8_t*) 0x02;
IntPointer = (int*) 0x02;
// Now let's 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
这个例子说明当我们从指针读取值时会发生什么,写怎么办?让我们保持与以前相同的变量并写一些值
*BytePointer = 5;
内存现在看起来像这样:
0x02 5
0x03 11
int
指针怎么样?
*IntPointer = 5;
由于int
是两个字节,它将改变两个字节:
// Little endian
0x02 5
0x03 0
// Big endian
0x02 0
0x03 5
因此,如果您使用PORTB
作为int
,则每次分配给它时,您将写入2个字节,一个写入PORTB
的地址,然后一个写入。我希望无论什么事情都不重要......你不应该这样做,所以如果你真的想使用指针,你应该使用uint8_t*
。
但是当我开始正确地解释它时,@ ahah已经发布了正确的答案。请参考它如何做到这一点。