gpt4 book ai didi

c++ - (C++) 调用函数时变量值发生变化

转载 作者:行者123 更新时间:2023-11-28 00:36:39 25 4
gpt4 key购买 nike

我有以下代码

N核心.h

#ifndef _NCORE_H_
#define _NCORE_H_

#include <Windows.h>
#include <cstdio>

namespace Neat
{
class NCore
{
private:
// Structure Definitions
struct NApplicationVersion
{
int major = 0;
int minor = 0;
int build = 0;
LPCSTR toString();
};

// Application Variables
LPCSTR applicationName;
NApplicationVersion applicationVersion;

protected:


public:
NCore();

LPCSTR ApplicationName(LPCSTR _applicationName = NULL);
NApplicationVersion ApplicationVersion(LPCSTR _applicationVersion = NULL);
};
}

#endif

N核心.cpp

#include "NCore.h"

Neat::NCore::NCore()
{
this->applicationName = NULL;
}

LPCSTR Neat::NCore::NApplicationVersion::toString()
{
char str[16];
memset(&str, 0, sizeof(str));
sprintf_s(str, sizeof(str), "%i.%i.%i", this->major, this->minor, this->build);
return str;
}

LPCSTR Neat::NCore::ApplicationName(LPCSTR _applicationName)
{
if (_applicationName)
this->applicationName = _applicationName;
return this->applicationName;
}

Neat::NCore::NApplicationVersion Neat::NCore::ApplicationVersion(LPCSTR _applicationVersion)
{
if (_applicationVersion)
{
//I know this isn't needed. I was just testing something.
Neat::NCore::NApplicationVersion *nav = (Neat::NCore::NApplicationVersion *)malloc(sizeof(Neat::NCore::NApplicationVersion));
sscanf_s(_applicationVersion, "%i.%i.%i", &nav->major, &nav->minor, &nav->build);
this->applicationVersion.major = nav->major;
this->applicationVersion.minor = nav->minor;
this->applicationVersion.build = nav->build;
free(nav);
}
return this->applicationVersion;
}

主要.cpp

#include <Windows.h>

#include "NCore.h"

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT iCmdShow)
{
Neat::NCore n;
n.ApplicationName("test");
LPCSTR test = n.ApplicationName();

LPCSTR test2 = n.ApplicationVersion().toString();
if (strcmp(test2, "0.0.0") == 0)
{
MessageBox(NULL, "", "", MB_OK);
}
n.ApplicationVersion("10.50.136");
if (strcmp(test2, "0.0.0") == 0)
{
MessageBox(NULL, "", "", MB_OK);
}
LPCSTR test3 = n.ApplicationVersion().toString();
if (test3 == "10.50.136")
{
MessageBox(NULL, "", "", MB_OK);
}

while (true);
return 0;
}

我的问题是 test2 初始化为“0.0.0”并且显示了第一个 MessageBox。但是在我调用 ApplicationVersion("10.50.136") 之后,它会将 test2 更改为“10.50.136”,并且不会显示第二个 MessageBox。

有人可以解释为什么会发生这种情况/如何解决它吗?

编辑:我正在测试一个可以同时作为获取/设置函数运行的函数。我对此很陌生,我从失败中学习。我只是想不通这里到底出了什么问题。

编辑 2:我按如下方式更改了代码...

N核心.h

struct NApplicationVersion
{
int major = 0;
int minor = 0;
int build = 0;
char asString[16];
LPCSTR toString();
};

N核心.cpp

LPCSTR Neat::NCore::NApplicationVersion::toString()
{
memset(this->asString, 0, 15);
sprintf_s(this->asString, 16, "%i.%i.%i", this->major, this->minor, this->build);
return this->asString;
}

这可行吗?

根据我的理解,我将变量“str”放入堆栈。这会导致它在内存中没有固定位置(?),当其他调用更改堆栈时,它们也会更改指针“test2”试图从中读取的数据?

最佳答案

其实很简单。 toString 通过返回一个数组 (str) 来调用未定义的行为,该数组在本地分配给函数并超出 return 的范围:

LPCSTR Neat::NCore::NApplicationVersion::toString()
{
char str[16];
memset(&str, 0, sizeof(str));
sprintf_s(str, sizeof(str), "%i.%i.%i", this->major, this->minor, this->build);
return str;
}

在大多数常见的 C++ 实现中,str 将在堆栈上。 (C++ 标准不需要所有自动变量所在的统一概念“堆栈”,但大多数常见实现都是这样工作的。)

因此,修改堆栈的后续函数也将修改调用 toString() 所指向的 C 风格字符串。例如,对 n.ApplicationVersion() 的后续调用可能会破坏 str。只要字符串更改为“0.0.0”以外的任何内容,您的第二个消息框就不会显示,并且不会以这种方式破坏堆栈。


根据您随后的编辑:使字符串成为您类(class)的成员将有些起作用。对 toString 的任何调用都将重写此字符串,从而影响保存指向此缓冲区的指针的所有调用方。

不过,这肯定比将字符串保存在堆栈上安全得多。此外,只要 toString 写入此缓冲区,您就可以明确定义该字符串何时有效的规则。

关于c++ - (C++) 调用函数时变量值发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20626927/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com