【问题标题】:Visual C++ Pointer Scope [duplicate]Visual C++ 指针范围 [重复]
【发布时间】:2015-10-30 09:27:14
【问题描述】:

我有一个小问题。 我正在用 Visual C++(VS 2013)编写一个程序。我想制作这样的工作代码。

void Blob::ReadBytes(BYTE* target, DWORD position, DWORD readLength)
{
    // check
    if (position + readLength > this->Length)
    {
        // clean if it allocated memmory, because need return nullptr
        target = static_cast<BYTE*>(realloc(target, 0));
        return;
    }

    // allocate memmory
    target = static_cast<BYTE*>(realloc(target, readLength));

    memmove(target, this->Data + position, readLength);
}

它工作,目标分配和初始化。但是当我从这个函数返回时,目标链接到NULL

例如:

...
Blob b;
BYTE* data = new BYTE[4];
data[0] = 'a';
data[1] = 'b';
data[2] = 'c';
data[3] = 'd';

b.Append(data, 4); // Add data to Blob

BYTE* bytes = nullptr;
b.ReadBytes(bytes, 0, 3); 
// There bytes = NULL
...

Blob 的样子

class Blob
{
    public:
    ...
    BYTE* Data;
    DWORD Length;
    ...
}

函数返回后我可以做些什么来保存新分配的范围? 一种解决方案是创建一个新对象 Blob 并像这样分配其字段:

Blob Blob::ReadBytes(DWORD position, DWORD readLength)
{
    Blob blob;

    // check
    if (position + readLength > this->Length)
    {
            blob.Data = static_cast<BYTE*>(realloc(blob.Data, 0));
            return Blob();
    }

    // allocate memmory
    blob.Data = static_cast<BYTE*>(realloc(blob.Data, readLength));

    memmove(blob.Data, this->Data + position, readLength);

    blob.Length = readLength;

    return blob;
}

在这种情况下,一切正常。但是,如果我只想获得分配内存的 BYTE* 指针怎么办? 可能是我不明白什么?

【问题讨论】:

  • 你做错了。停止使用指针和原始数组,学习使用标准容器,例如std::vector
  • 我使用 WinCrypt。它使用 BYTE* 数组
  • 由于WinCrypt既不分配也不释放缓冲区,你可以毫无问题地传递std::vector&lt;BYTE&gt;的内容(使用myvector.data()&amp;myvector[index])。

标签: c++ pointers visual-studio-2013 scope


【解决方案1】:

您需要返回target 或使用BYTE 的指针:

BYTE* Blob::ReadBytes(DWORD position, DWORD readLength)
{
    BYTE* target, 
    // your code
    return target ;
}

BYTE *bytes = Blob::ReadBytes(...) ;

或者:

void Blob::ReadBytes(BYTE** target, DWORD position, DWORD readLength)
{
    // check
    if (position + readLength > this->Length)
    {
        // clean if it allocated memmory, because need return nullptr
        *target = static_cast<BYTE*>(realloc(target, 0));
        return;
    }

    // allocate memmory
    *target = static_cast<BYTE*>(realloc(target, readLength));

    memmove(*target, this->Data + position, readLength);
}

BYTE *bytes ;
Blob::ReadBytes (&bytes, ...) ;

请记住,当您拥有函数fn (TYPE var) 时,您分配给var 的值仅保留在函数的范围内:

void fn (BYTE var) {
    var = 8 ;
}

BYTE myVar = 4 ;
fn (myVar) ;
// myVar still equals 4

指针也一样:

void fn (BYTE *bytes) {
    bytes = static_cast<BYTE*>(realloc(target, readLength));
}

BYTE *bytes = 0 ;
fn (bytes) ;
// bytes still equals 0

如果你想给给定的参数赋值,你需要使用一个指针,然后使用*p取消引用它。

  • 如果要检索BYTE,则使用BYTE*,然后使用*pb = 4
  • 如果要检索BYTE*,则使用BYTE**,然后使用*ppb = new BYTE[...](或任何你想要的)。
void gn (BYTE **bytes) {
    *bytes = static_cast<BYTE*>(realloc(target, readLength));
}

BYTE *bytes = 0 ;
fn (&bytes); // Don't forget to send a pointer to bytes using &bytes, not simply bytes!
// bytes is not equals to 0 anymore!

【讨论】:

  • 感谢您的好回答 =) !
【解决方案2】:

这是因为“目标”名称是您的函数的本地名称。如果要更改调用函数中变量的值,则必须传递指向该变量的指针或引用,或者作为值返回(如第二个示例中所示)。

您传递的是指向某个内存的指针,而不是指向指向该内存的变量的指针。

所以你可以声明你的函数

void Blob::ReadBytes(BYTE* &target, DWORD position, DWORD readLength)

它的优点是不需要重写所有代码,但它的缺点是如果你在任何地方都看不到声明,它不会立即改变传入的变量。

或者您可以将其声明为

void Blob::ReadBytes(BYTE** target, DWORD position, DWORD readLength)

以牺牲实现中的一些不可读性为代价,让您清楚地知道您在做什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 2015-09-30
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多