Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 当传递一个固定长度的字符串时,Left()函数如何处理GetWindowsDirectory API?_Excel_Vba_Winapi - Fatal编程技术网

Excel 当传递一个固定长度的字符串时,Left()函数如何处理GetWindowsDirectory API?

Excel 当传递一个固定长度的字符串时,Left()函数如何处理GetWindowsDirectory API?,excel,vba,winapi,Excel,Vba,Winapi,我无法使我的标题既具有描述性又简洁。我正在阅读一本名为powerprogrammingwithvba的书,其中一个例子使用了一个名为GetWindowsDirectoryA的windowsapi,它使用字符串lpBuffer&long nSize参数。声明后,作者在子例程中使用它来检索Windows目录 让我困惑的是这种情况的发生方式。代码如下: 如果是VBA7和Win64,则 声明PtrSafe函数GetWindowsDirectoryA Lib内核32_ ByVal lpBuffer作为字符

我无法使我的标题既具有描述性又简洁。我正在阅读一本名为powerprogrammingwithvba的书,其中一个例子使用了一个名为GetWindowsDirectoryA的windowsapi,它使用字符串lpBuffer&long nSize参数。声明后,作者在子例程中使用它来检索Windows目录

让我困惑的是这种情况的发生方式。代码如下:

如果是VBA7和Win64,则 声明PtrSafe函数GetWindowsDirectoryA Lib内核32_ ByVal lpBuffer作为字符串,ByVal nSize作为长字符串 其他的 声明函数GetWindowsDirectoryA Lib kernel32_ ByVal lpBuffer作为字符串,ByVal nSize作为长字符串 如果结束 子ShowWindowsDir 将WinPath设置为字符串*255'为什么即使我将其设置为常规变量字符串,它也可以工作? 暗淡的温迪尔如弦 如果我更改此数字或注释掉它,WinPath=Space255'也可以正常工作,但如果注释掉它,符号仍然保留 WinDir=LeftWinPath,GetWindowsDirectoryAWinPath,LenWinPath MsgBox WinDir、vbInformation、Windows目录 端接头 它的工作方式没有问题。当我看到它在编辑器中一步一步地执行时,它似乎以某种方式执行了一个对我来说并不明显的额外步骤

声明WinPath时,它是一个容量为255个字符的空字符串。我不知道为什么这是必要的,因为删除字符串的固定长度性质仍然可以正常工作

由于未知原因,WinPath被255个空格填充。没有这个也行

这是我的悖论。我们将WinPath作为参数传递给Left,但是WinPath中只有255个空格,Left的第二部分通常告诉它将第一个参数截断为X个空格。提供GetWindowsDirectoryAWinPath、LenWinPath如何绕过这种正常逻辑,并突然产生结果:C:\Windows


我觉得如果我了解这是如何工作的,它将帮助我了解其他API是如何做生意的。顺便说一句,代码中的注释是我的,不是作者的。

执行函数时,参数列表从堆栈中弹出时需要按正序排列,因此加载时需要按从后到前的相反顺序排列,GetWindowsDirectoryA首先执行,然后WinPath获得一个值,然后将值返回到参数列表。 下面是一个简单的Win32程序

#include <windows.h>
#include <iostream>
void f(int a, int b)
{
    printf("a = %d\nb = %d\n", a, b);
}
int main()
{
    int i = 1;
    f(i, ++i);
    getchar();
    return 0;
}
但不是

a = 1
b = 2

在调用函数之前,需要对其所有参数进行求值。在此之前,该函数尚未调用

Left有两个参数,我们为第二个参数提供了一个表达式。在调用Left之前,必须对该表达式GetWindowsDirectoryAWinPath和LenWinPath进行完整计算

该表达式具有修改WinPath内容的副作用,因此在GetWindowsDirectoryA返回后,WinPath包含新值

只有执行进入左侧,它才有机会读取传递给它的参数

请注意,在这种情况下,如果在执行GetWindowsDirectoryA之前将WinPath实际推送到堆栈上,这甚至无关紧要。如果是这样的话,推送的是变量,而不是它的内容。因此,当调用Left时,它将从堆栈中读取WinPath变量,并且它将指向修改后的数据


至于WinPath的初始内容,在调用GetWindowsDirectoryA之前需要缓冲区,因此您确实需要使用一些一次性字符(如空格或vbNullChars)填充它。您可以通过使用*255修饰符或调用=Space255来实现这一点,两者都是多余的。但是请注意,缓冲区的长度应为MAX_PATH字符,即260。

函数参数通常按向后顺序堆叠,因此先执行后者,然后WinPath有一个值。参数在堆栈上的顺序与问题无关。C++中的示例代码也不是真正相关的,因为它是不同的语言,有不同的规则。
a = 1
b = 2