函数调用

时间:2017-07-21 18:59:33

标签: c++ pointers arduino

最近,我试图解决一个问题,这让我有点困扰。

问题是,当我调用一个方法并传递一个结构,它有一个数组指针作为成员时,前面两个字节在返回方法后被清零。即使它们被初始化为(在这种情况下)0xFF。他们总是没有被玷污。有时发生了,他们确实带来了一些价值,但我无法找到任何模式。

我最近解决了这个问题。我不得不传递Bitmap结构的指针。但是我不明白为什么,当我只需要更改数组的值时,正如你在下面看到的那样,我正在写入相同的地址,但是当它从方法返回时,2个第一个字节为零;

有人可以解释我错过了什么吗?感谢。

我有这段代码:

void Printer::offsetBitmapVertically(Bitmap bitmap, uint8_t offset)
{
    byte length = bitmap.arrayLength();

    byte previousValue = 0;

    for (byte i = 0; i < bitmap.width; i++)
    {
        byte previousValue = 0;
        for (byte j = 0; j <= bitmap.height / 8; j++)
        {
            byte index = i + bitmap.width * j;

            byte tmp = bitmap.value[index] >> 8 - offset;
            bitmap.value[index] = (bitmap.value[index] << offset) | previousValue;
            Serial.print("address: "); Serial.println((uint16_t)&bitmap.value[index]);
            Serial.print("value: "); Serial.println(bitmap.value[index], HEX);
            previousValue = tmp;
        }
    }

    Serial.println("");
    Serial.println("");
    Serial.println("");
}

void TextPrinter::print(const char *str, Point p, Font* p_font)
{
    while (*str)
    {
        Bitmap bitmap = p_font->getBitmapFromCharacter(*str);
        offsetBitmapVertically(bitmap, 0);
        for (int i = 0; i < bitmap.arrayLength(); i++)
        {
            Serial.print("address: "); Serial.println((uint16_t)&bitmap.value[i]);
            Serial.print("value: "); Serial.println(bitmap.value[i], HEX);
        }

        p_lcd->writeBitmap(bitmap.value, p.x, p.y, bitmap.width, bitmap.height);
        p.x += bitmap.width + 2;

        str++;
    }  
}

/*
address: 1240
value: FF
...
address: 1241
value: FF
...



address: 1240
value: 0
address: 1241
value: 0
...
*/

Bitmap结构定义如下

struct Bitmap
{
    public:
        Bitmap(const byte* bitmapArray);
        ~Bitmap() { delete [] value; }

        uint8_t arrayLength() { return arrayLength(width, height); } 
        static uint8_t arrayLength(uint8_t width, uint8_t height) { return width * ((height / 8) + 1); } // TODO potencional bug when height % 8 == 0

        byte* value;
        uint8_t width;
        uint8_t height;
};

Bitmap::Bitmap(const byte* bitmapArray)
{
    width = pgm_read_word(bitmapArray);
    height = pgm_read_word(bitmapArray + 1);

    byte length = arrayLength(width, height);
    value = new byte[length];
    for (byte i = 0; i < length; i++)
        value[i] = pgm_read_word(bitmapArray + i + 2); // first two bytes were width and height
}

1 个答案:

答案 0 :(得分:2)

您按值传递bitmap变量。这意味着offsetBitmapVertically函数从print函数接收变量的副本

更改副本当然不会改变原件。

您应该通过引用传递参数

void Printer::offsetBitmapVertically(Bitmap& bitmap, uint8_t offset) { ... }
//                                         ^
//                       Note ampersand here

另请注意,除非您更改为通过引用传递,否则您的代码会导致未定义的行为。这是因为默认的复制构造函数(将用于创建副本)只是复制指针,导致两个不同的对象具有指向同一内存的相同指针。一旦bitmap函数内的offsetBitmapVertically变量超出范围并被破坏,它将delete[]该内存,这意味着原始指针不再指向已分配的内存。

了解the rules of three, five and zero以了解如何解决此问题。