我正在学习c++,我刚刚开始学习Qt的一些功能来编写GUI程序。我问了自己以下问题:
c++以前没有语法能够要求操作系统提供一个窗口或一种通过网络进行通信的方式(我承认我也不完全理解api),它是如何通过c++本身编写的库突然获得这些功能的?在我看来,这一切都是可怕的循环。你能在这些库中找到哪些c++指令?
我知道这个问题对一个有经验的软件开发人员来说似乎微不足道,但我已经研究了几个小时,没有找到任何直接的回答。这已经到了我无法理解Qt教程的地步,因为库的存在对我来说是不可理解的。
我正在学习c++,我刚刚开始学习Qt的一些功能来编写GUI程序。我问了自己以下问题:
c++以前没有语法能够要求操作系统提供一个窗口或一种通过网络进行通信的方式(我承认我也不完全理解api),它是如何通过c++本身编写的库突然获得这些功能的?在我看来,这一切都是可怕的循环。你能在这些库中找到哪些c++指令?
我知道这个问题对一个有经验的软件开发人员来说似乎微不足道,但我已经研究了几个小时,没有找到任何直接的回答。这已经到了我无法理解Qt教程的地步,因为库的存在对我来说是不可理解的。
当前回答
你是对的,一般来说,图书馆不能使任何不可能的事情成为可能。
但是库并不一定要用c++来编写才能被c++程序使用。即使它们是用c++编写的,它们也可能在内部使用其他不是用c++编写的库。因此,c++没有提供任何方法来做这件事的事实并不妨碍它被添加,只要在c++之外有某种方法来做这件事。
在相当低的级别上,c++(或C)调用的一些函数将用汇编编写,并且该汇编包含所需的指令,以完成在c++中不可能(或不容易)的操作,例如调用一个系统函数。此时,该系统调用可以做计算机能够做的任何事情,因为没有任何东西可以阻止它。
其他回答
关键在于操作系统是否可能公开API以及如何使用该API的详细描述。
操作系统提供了一组具有调用约定的api。 调用约定定义了将参数提供给API的方式、返回结果的方式以及如何执行实际调用。
操作系统和为它们创建代码的编译器可以很好地协同工作,所以您通常不必考虑它,只需使用它。
创建窗口不需要特殊的语法。所需要的只是操作系统提供一个API来创建窗口。这样的API由c++提供语法的简单函数调用组成。
此外,C和c++是所谓的系统编程语言,能够访问任意指针(可能由硬件映射到某些设备)。此外,调用在程序集中定义的函数也相当简单,这允许处理器提供的全部操作。因此,使用C或c++和少量的汇编程序来编写操作系统本身是可能的。
还应该提到Qt是一个不好的例子,因为它使用所谓的元编译器来扩展c++的语法。然而,这与它调用操作系统提供的api来实际绘制或创建窗口的能力无关。
好问题。每一个新的C或c++开发人员都有这样的想法。在本文的其余部分中,我假设使用的是标准的x86机器。如果你使用的是微软c++编译器,打开你的记事本并输入这个(命名为Test.c)
int main(int argc, char **argv)
{
return 0
}
现在编译这个文件(使用开发人员命令提示符)cl Test.c /FaTest.asm
现在打开Test。在你的记事本里。你看到的是翻译后的代码——C/ c++被翻译成汇编程序。你明白我的意思了吗?
_main PROC
push ebp
mov ebp, esp
xor eax, eax
pop ebp
ret 0
_main ENDP
C/ c++程序是设计来在金属上运行的。这意味着他们可以访问较低级别的硬件,从而更容易利用硬件的功能。比如说,我要在x86机器上编写一个C库getch()。
根据汇编器的不同,我可以这样输入:
_getch proc
xor AH, AH
int 16h
;AL contains the keycode (AX is already there - so just return)
ret
我用汇编程序运行它并生成一个。obj -命名为getch.obj。
然后我写了一个C程序(我不包括任何东西)
extern char getch();
void main(int, char **)
{
getch();
}
现在将这个文件命名为GetChTest.c。通过传递getch来编译这个文件。obj。(或者单独编译到.obj和LINK GetChTest。Obj和getch。Obj一起生成GetChTest.exe)。
运行GetChTest.exe,你会发现它在等待键盘输入。
C/C++ programming is not just about language. To be a good C/C++ programmer you need to have a good understanding on the type of machine that it runs. You will need to know how the memory management is handled, how the registers are structured, etc., You may not need all these information for regular programming - but they would help you immensely. Apart from the basic hardware knowledge, it certainly helps if you understand how the compiler works (ie., how it translates) - which could enable you to tweak your code as necessary. It is an interesting package!
这两种语言都支持__asm关键字,这意味着你也可以混合汇编语言代码。学习C和c++会让你成为一个更全面的程序员。
不需要总是与汇编程序链接。我提到它是因为我认为这会帮助你们更好地理解。大多数这样的库调用都利用了操作系统提供的系统调用/ api(操作系统负责硬件交互)。
C和c++有两个属性,允许OP所谈论的所有这些可扩展性。
C和c++可以访问内存 C和c++可以调用非C或c++语言中的汇编代码。
在内核或基本的非保护模式平台中,外围设备(如串口或磁盘驱动器)以与RAM相同的方式映射到内存映射中。内存是一系列的开关,翻转外围设备的开关(比如串口或磁盘驱动器)可以让外围设备做一些有用的事情。
在保护模式操作系统中,当用户希望从用户空间访问内核时(比如写入文件系统或在屏幕上绘制像素),需要进行系统调用。C语言没有指令来进行系统调用,但是C语言可以调用汇编代码来触发正确的系统调用,这就是为什么C代码可以与内核对话。
为了使特定平台的编程更容易,系统调用被包装在更复杂的函数中,这些函数可以在自己的程序中执行一些有用的函数。可以直接调用系统调用(使用汇编程序),但是使用平台提供的一个包装器函数可能更容易。
还有另一层API比系统调用有用得多。以malloc为例。这不仅会调用系统来获取大块的内存,而且还会通过对正在发生的事情进行所有簿记来管理这些内存。
Win32 api用一个公共平台小部件集包装了一些图形功能。Qt更进一步,以跨平台的方式包装了Win32(或X Windows) API。
从根本上讲,C编译器将C代码转换为机器代码,由于计算机被设计为使用机器代码,所以你应该期望C能够完成计算机所能完成的大部分工作。包装器库所做的一切都是为您做繁重的工作,这样您就不必做了。
我认为你忽略了系统调用的概念。每个操作系统都提供了大量的资源和功能,您可以利用它们来做与操作系统相关的底层工作。即使当您调用常规的库函数时,它也可能在幕后进行系统调用。
系统调用是一种利用操作系统强大功能的低级方式,但使用起来可能复杂且麻烦,因此通常被“包装”在api中,这样您就不必直接处理它们。但实际上,几乎所有涉及O/S相关资源的操作都将使用系统调用,包括打印、网络和套接字等。
在windows的情况下,微软windows已经把它的GUI写进了内核,所以有一些系统调用来创建窗口,绘制图形等。在其他操作系统中,GUI可能不是内核的一部分,在这种情况下,据我所知,不会有任何与GUI相关的系统调用,您只能在更低的级别上使用任何可用的低级图形和输入相关调用。