在学习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位的寄存器 每个引脚有一个位来控制该引脚是HIGH还是LOW。
目前,我很高兴它能工作。但这些警告让我很烦。
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;
编辑2:在我改正我最初的答案(如下)时,我看到@ouah已经发布了正确的答案,所以请你使用它来代替我的答案。
当我来得及更正我的原始答案(如下)时,我看到@ouah已经公布了一个正确的答案,所以我请你用它代替我的答案。更详细的解释请阅读 "编辑1 下面的。
我最初的答案。
PORTB
可能没有被定义为 int
这意味着,当你把地址的 PORTB
你不会得到 int *
. 如果你确定你是对的,而且你可以使用一个。int *
对于 PORTB
你可以使用一个 Cast 来告诉编译器它不需要担心。你可以像这样投递。
ptr = (int*)&PORTB
转到定义中的 PORTB
并让我们知道是什么类型的。
编辑1:
我的假设是你知道 PORTB
是一个 int
而你的铸造是来自 void*
. 谢谢@H2CO3指出,它其实是一个。(*(volatile uint8_t *)(0x25))
这基本上意味着 PORTB
是一个 volatile uint8_t
.
在这种情况下,你不应该把它投给一个人。int
! 如果这样做了,说明你的机器可能是。苣荬菜 而你不应该依赖这个。
为了正确解释它,让我们设置一个简单的例子。
我们在内存里有这样一个例子:
Address Value
0x02 7
0x03 11
注:7在十六进制中是0x07,在二进制中是000011 11在十六进制中是0x0B,在二进制中是00001011。
现在我们有了两个指针。
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*
如果你真的想用指针的话。
但当我来不及好好解释的时候,@ouah已经发了一个正确的答案。请大家参考一下,应该怎么做。