在函数中换行C块.初级问题

Wrap C block in function. Beginner question

本文关键字:问题 函数 换行      更新时间:2023-10-16

我找到了C代码片段,从这里获取当前工作目录。本质上,代码是:

char directory[_MAX_PATH];
getcwd(directory, sizeof(directory))

我想把它抽象到另一个函数中,在不同的文件中(这样,如果必要的话,它可以在不同的平台上交换)。

目前,我在外部文件

void getCurrentDirectory(char *directory) {
    getcwd(directory, sizeof(directory));
}

并且在主文件中

char directory[100];
getCurrentDirectory(directory);
printf("%s", *directory);

然而,当打印到屏幕上时,我会胡说八道(可能试图将内存位置打印为字符串?)

我相信这对一个非初学者来说是显而易见的。怎么回事?

编辑:我在Windows 7上,顺便说一句

谢谢。

这里有很多错误:

void getCurrentDirectory(char *directory) 
  {
      getcwd(directory, sizeof(directory));
  }

错误1:

`sizeof(directory)` 

给出了一个指针的大小,确切地说是char*。您的意图是传递数组的大小,而不是指针的大小。

错误2:

`printf("%s", *directory);` 

将数组的第一个元素传递给printf,而不是数组的地址。您的意图是打印整个数组,而不仅仅是第一个元素。

修正的解决方案

你应该做

void getCurrentDirectory(char *directory, size_t arrSize)  
{                                         ^^^^^^^^^^^^^^
    getcwd(directory, arrSize);
}

数组的大小是显式传递的,因此函数可以直接使用它

在打印阵列的主要内容时:

   printf("%s", directory);

此行:printf("%s", *directory);

应为:printf("%s", directory);

您将第一个元素(目录[0])传递给printf,而不是指向char数组的指针。

如果是C++,我建议尽可能使用boost::filesystem,它隐藏了所有底层平台的详细信息为您提供了C++风格的接口,而不是容易发生缓冲区溢出的C函数。

您将char*的大小传递给getcwd,而不是数组的大小。

将大小参数传递给函数。

void getCurrentDirectory(char *directory, size_t size) {
    getcwd(directory, size);
}

然后:

char directory[100];
getCurrentDirectory(directory, sizeof(directory));
printf("%s", *directory);

此外,如果您使用的是Windows,您可能应该将数组大小更改为预定义的MAX_PATH,以避免潜在的缓冲区溢出。getcwd需要一个长度,但我不认为所有的文件函数都需要。

您应该在本地分配缓冲区(如果需要长度是已知的,并且实际长度需要已知)以及返回字符串:

std::string
getCurrentDirectory()
{
    char results[_MAX_PATH];
    if ( getcwd( results, sizeof(results) ) == NULL )
        throw std::ios_base::failure( "Could not get current directory" );
    return std::string( results );
}

还要注意,_MAX_PATH只是一个猜测;实际最大值为不是编译时常数(因为它取决于文件系统)。考虑到这一点的实现可能看起来像:

std::string
getCurrentDirectory()
{
    long length = pathconf( ".", _PC_PATH_MAX );
    if ( length == -1 )
        throw std::ios_base::failure(
                "Could not determine necessary buffer length to get current directory" );
    std::string results( length, '' );
    if ( getcwd( &results[0], results.size() ) == NULL )
        throw std::ios_base::failure( "Could not get current directory" );
    results.resize( strlen( results.c_str() );
    return results;
}

然而,如果该程序只进行下去,那么这可能有些过头了在没有安装NFS或SMB驱动器的个人系统上使用。

既然是C++,为什么不这样做呢:

std::string getCurrentDirectory()
{
    char directory[_MAX_PATH] = {};
    getcwd(directory, sizeof(directory));
    return directory;
}

使用类似的sizeof无法找到指针指向的内存块的大小。它将根据指针本身的大小进行计算。

将您的功能更改为:

void getCurrentDirectory(char *directory, size_t buf_max)
{
    getcwd(directory, buf_max);
}

现在回答您的问题:

当getcwd由于某种原因失败时,directory(在您的情况下)指向的数组的内容是未定义的。因此,在大多数情况下,使用有缺陷的实现会看到垃圾。(此外,您应该检查getcwd的返回值,失败时返回-1)

现在,在您的情况下失败的原因是您使用sizeof(directory)指定的大小只是一个指针的大小(可能是4),并且您试图打印的当前工作目录名称中的字符不止于此。这将适用于大小为3或更小的目录。

最后,这里的许多其他人已经向您解释了如何修复它。