代码可以工作,但抛出不兼容指针类型警告

问题描述 投票:4回答:2

在学习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。

目前,我很高兴它能工作。但这些警告让我很烦。

c pointers casting avr 8-bit
2个回答
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;

6
投票

编辑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已经发了一个正确的答案。请大家参考一下,应该怎么做。

© www.soinside.com 2019 - 2024. All rights reserved.