下面的C代码有什么问题?

时间:2010-07-05 14:51:05

标签: c

以下代码来自this answer

#include <windows.h> 

int main()
{
    HANDLE h = ::CreateFile(L"\\\\.\\d:", 0, 0, NULL, OPEN_EXISTING, 0, NULL);

    STORAGE_DEVICE_NUMBER info = {};
    DWORD bytesReturned =  0;

    ::DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &info, sizeof(info), &bytesReturned, NULL);
}

当我编译并运行上面的内容时,得到如下错误:

error C2059: syntax error : ':'
error C2059: syntax error : '}'
error C2143: syntax error : missing ';' before ':'

更新

将上述内容保存为cpp文件后,出现此错误:

error C2664: 'CreateFileA' : cannot convert parameter 1 from 'const wchar_t [7]' to 'LPCSTR'

4 个答案:

答案 0 :(得分:9)

Plain C没有名称空间,因此您需要省略::全局名称空间说明符。那些只在C ++中有效。

字符串前面的L指定这是一个宽字符串。如果您的项目不使用宽字符,请省略L以获取正常的字符串。如果您需要支持这两种变体,您还可以使用_T宏:_T("...")根据项目设置扩展为字符串文字的正确变体。

答案 1 :(得分:3)

我很确定您不能将::用作C编程语言中标识符名称的一部分。这看起来更像是C ++的一些奇怪的,混乱的用法。 IIRC,::本身位于标识符前面,指定它位于全局或文件范围内(以避免与类中的方法发生冲突)。

答案 2 :(得分:2)

它不是C,它是C ++。删除双冒号(或将其编译为C ++)。

此外,字符串常量使用宽字符。将L放在公开引用的前面。

答案 3 :(得分:0)

所以,我想你的问题更多的是关于获得你想要的结果而不是代码不编译的原因:)

现在你已经开始工作,DeviceIoControl()调用将填充你传递给它的STORAGE_DEVICE_NUMBER结构,并带有你想要的结果。因此,您应该会发现info.DeviceType现在包含设备类型,info.DeviceNumber包含设备编号,info.PartitionNumber包含分区编号。

在使用返回值之前测试成功。我可能会在C:驱动器而不是D:驱动器上尝试它,就像你现在正在做的那样,直到我确定它正在工作;至少你知道你在Windows中几乎总是有一个C:驱动器:)所以,使用\\\\.\\c:而不是\\\\.\\d:

无论如何,未经测试,但是:

if (::DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &info, sizeof(info), &bytesReturned, NULL))
{
    std::cout << "Device: " << info.DeviceNumber << 
                 " Partition: " << info.PartitionNumber << std::endl;
} else {
    std::cerr << "Ooops. The DeviceIoControl call returned failure." << std::endl;
}

......很明显,你需要一个#include <iostream>来实现这一点,因为我正在使用iostream转储这些值,但你可以根据需要打印这些值,或者将它们打印出来,介意你已经引入了windows.h。

请记住,自从我做任何Windows C ++工作以来已经有十年左右了,但也许这会让你感到高兴......