为什么使用.net框架的程序比使用非托管代码的程序要小?

本文关键字:程序 非托管代码 框架 为什么 net | 更新日期: 2023-09-27 18:10:50

我用非托管C代码编写了以下程序:

#include <Windows.h>
#include <tchar.h>
const TCHAR g_szClassName[] = _T("SkeletonAppWindowClass");
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam);
ATOM RegisterWCEX(HINSTANCE hInstance);
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd);
ATOM RegisterWCEX(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    ZeroMemory(&wcex, sizeof(WNDCLASSEX));
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hIcon =
    wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wcex.hInstance = hInstance;
    wcex.lpfnWndProc = WindowProc;
    wcex.lpszClassName = g_szClassName;
    return RegisterClassEx(&wcex);
}
BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
{
    HFONT hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SendMessage(hWnd, WM_SETFONT, (WPARAM)hfDefault, 0L);
    return TRUE;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    static HWND hButton;
    switch (Msg)
    {
    case WM_CREATE:
        hButton = CreateWindow(_T("BUTTON"), _T("Say Hi"), WS_VISIBLE | WS_CHILD, 130, 230, 70, 20, hWnd, NULL, GetModuleHandle(NULL), NULL);
        break;
    case WM_COMMAND:
        if ((HWND)lParam == hButton)
        {
            MessageBox(0, _T("Hello World!"), _T("Information"), MB_OK | MB_ICONINFORMATION);
        }
        break;
    case WM_CLOSE:
        DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    return 0;
}
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
{
    HWND hWnd;
    MSG Msg;
    RegisterWCEX(hInstance);
    hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, g_szClassName, _T("Simple Window"), WS_VISIBLE | WS_SYSMENU, 100, 100, 350, 370, NULL, NULL, hInstance, NULL);
    ShowWindow(hWnd, SW_SHOW);
    EnumChildWindows(hWnd, EnumChildProc, 0L);
    UpdateWindow(hWnd);
    while (GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

它所做的只是创建一个简单的窗口,当点击该窗口时,弹出一个消息框,上面写着"Hello World!"

该程序在Release模式下的大小为10KB,具有/O1(最小化空间)优化。

然后,当我在c#中创建一个"Windows窗体应用程序",并在窗体上创建一个按钮,其事件处理程序是:
    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Hello World", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

在发布模式下编译时,c#可执行文件的大小只有8KB。这是违反直觉的;我希望非托管程序更紧凑。

问题是我编写C程序的方式,还是我没有考虑到的其他东西?

为什么使用.net框架的程序比使用非托管代码的程序要小?

程序的大部分功能都包含在您所链接的库中。这些库不会影响程序的大小,除非它们需要更多的函数调用来完成相同的行为。这就是你的例子中的情况。windows库需要大量的设置和调用API来生成一个对话框,而. net应用程序只需要一个函数调用,不需要配置。编译程序的大小与链接和调用库的外部API的指令数量有关。非托管程序比使用。net的程序有更多的指令。

机器码的编译是在运行时进行的。代码的功能(库)是与。net一起安装的。所以你的应用程序更小,因为它使用了你的电脑上安装的库。