【问题标题】:Misunderstanding something when passing by reference (C structures)通过引用传递时的误解(C结构)
【发布时间】:2021-08-06 16:06:37
【问题描述】:

我正在做一些基本的 C 编码并遇到了一个我无法弄清楚的问题。所以我目前的设置是我已经定义了一个简单的结构:

struct UserInfo
{
   WCHAR* UserName;
   WCHAR* ComputerName;
}

从我的主目录中,我想创建该结构的一个实例,通过引用两个函数来传递该结构,每个函数将填充两个字段之一。我的主要代码是:

void main()
{
   struct UserInfo userInfo;

   GetUserName(&userInfo);
   GetComputerName(&userInfo);

   return 0;
}

两个函数如下:

BOOL GetUserName(struct UserInfo* userInfo)
/*
Function calls the winapi function GetUserNameW to return the current
username in widechar format.
*/
{
    WCHAR UserName[USERNAME_MAXSIZE + 1];
    DWORD UserNameSize = USERNAME_MAXSIZE + 1;

    if (!GetUserNameW(UserName, &UserNameSize))
    {
        if (&UserNameSize != USERNAME_MAXSIZE + 1)
        {
            if (!GetUserNameW(UserName, &UserNameSize)) return FALSE;
        }
        else return FALSE;
    }
    userInfo->UserName = UserName;

    return TRUE;
}

BOOL GetComputerName(struct UserInfo* userInfo)
{
    LPWSTR ComputerBuffer[MAX_PATH];
    DWORD ComputerBufferSize = MAX_PATH;
    if (!GetComputerNameW(ComputerBuffer, &ComputerBufferSize))
    {
        if (&ComputerBufferSize != MAX_PATH)
        {
            if (!GetComputerNameW(ComputerBuffer, &ComputerBufferSize)) return FALSE;
        }
        else return FALSE;
    }

    userInfo->ComputerName = ComputerBuffer;

    return TRUE;
}

我遇到的问题是,当调用第二个函数时,存储在第一个值中的数据似乎被覆盖了。因此,例如,在浏览代码时,第一个函数会使用指向我的系统用户名的指针正确填充 userInfo->UserName。

当调用第二个函数时,用户 userInfo->UserName 的值似乎被覆盖了,第二个函数运行良好并且 userInfo->ComputerName 被正确填充。我很困惑为什么会这样?如果我像这样将这些功能合并为一个:

BOOL GetData(struct UserInfo* userInfo)
{
    WCHAR UserName[USERNAME_MAXSIZE + 1];
    DWORD UserNameSize = USERNAME_MAXSIZE + 1;
    LPWSTR ComputerBuffer[MAX_PATH];
    DWORD ComputerBufferSize = MAX_PATH;

    if (!GetUserNameW(UserName, &UserNameSize))
    {
        if (&UserNameSize != USERNAME_MAXSIZE + 1)
        {
            if (!GetUserNameW(UserName, &UserNameSize)) return FALSE;
        }
        else return FALSE;
    }
    userInfo->UserName = UserName;

    if (!GetComputerNameW(ComputerBuffer, &ComputerBufferSize))
    {
        if (&ComputerBufferSize != MAX_PATH)
        {
            if (!GetComputerNameW(ComputerBuffer, &ComputerBufferSize)) return FALSE;
        }
        else return FALSE;
    }

    userInfo->ComputerName = ComputerBuffer;

    return TRUE;
}

这一切都按预期工作,我是否误解了有关通过引用传递的内容?据我了解,&userInfo 基本上是传递一个指向我的结构的指针,而 userInfo->somefield 实际上是在修改我的结构,而不是像按值传递那样修改我的结构。我不明白为什么当将相同的结构传递给不同的函数时,每个函数都会修改不同的字段,它们会相互干扰?

提前感谢您对理解这一点的任何帮助。

【问题讨论】:

  • 您正在存储指向局部变量(字符串数组)的指针。当您退出函数(或它们定义的块)时,它们不再存在。并且它们的内存可能会被重新用于其他目的。

标签: c pointers struct reference


【解决方案1】:

数组UserNameComputerBuffer 是函数中的非静态局部数组。这意味着它们的生命在从函数返回时结束,因此在从函数返回后不能使用指向它们的指针。

你应该在堆上分配一些缓冲区,这样数据在返回时不会被删除。

您还应该使用WCHAR,而不是LPWSTR,作为ComputerBuffer 的元素,因为要分配的成员ComputerName 具有WCHAR* 类型。

而不是这些:

    WCHAR UserName[USERNAME_MAXSIZE + 1];
    DWORD UserNameSize = USERNAME_MAXSIZE + 1;
    LPWSTR ComputerBuffer[MAX_PATH];
    DWORD ComputerBufferSize = MAX_PATH;

你应该这样做:

    DWORD UserNameSize = USERNAME_MAXSIZE + 1;
    WCHAR *UserName = malloc(sizeof(*UserName) * UserNameSize);
    DWORD ComputerBufferSize = MAX_PATH;
    WCHAR *ComputerBuffer = malloc(sizeof(*ComputerBuffer ) * ComputerBufferSize);

你应该添加

#include <stdlib.h>

如果 malloc() 尚不存在,则使用它。

【讨论】:

  • 用完后别忘了在分配的内存上调用free
  • 啊,谢谢,这是有道理的,因为我的结构类型是 wchar*,我正在用指向函数结束后超出范围的非静态本地数组的指针填充字段。
猜你喜欢
  • 2013-05-12
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多