window環境下,如何通過USB接口控制打印機

雖然說大多數情況下,我們可以非常便利的通過打印機驅動來控制打印機,但還是有一些特殊情況,導致無法通過打印機驅動來完成我們預想的任務,比如,打印機只是一個系統設備中的一部分,需要協調其它設備一起工作時,如果只是通過打印機驅動來完成打印任務,就很難與系統中的其它設備完美協調。

那么,我們應該如何解決這種問題呢?一、開發特定的打印機驅動來配合;二、定制專用的Firmware,增加特殊的控制指令,通過USB端口來控制打印機的打印并實時獲取打印機當前的工作狀態,從而實現完美配合系統其它設備的功能。

那么,新的問題來了,我們應該選擇方案一還是方案二呢?其實這個問題,不難選擇,大多數情況下,有這種需求的打印機,就不是一款通用形的打印機,而是一款定制的或專用于某個領域的打印機,也就意味著,這種打印機本就是定制的,從硬件到Firmware,都是定制的,所以,顯然選擇方案二是最合適的。

新問題又有了,我們如何才能通過USB端口控制打印機呢?回答這個問題之前,我們先介紹一下window系統下usb設備的類型。

一、usb設備的類型

USB設備類型根據功能和應用場景可分為以下幾大類:

一)、常用設備類

  1. ?HID(人機接口設備)?

    • 用途:用于人與計算機交互的輸入設備
    • 示例:鍵盤、鼠標、游戲手柄
    • 協議特征:支持低速/全速模式,兼容性強
  2. ?MSC(大容量存儲設備)?

    • 用途:數據傳輸與存儲
    • 示例:U盤、移動硬盤、SD卡讀卡器
    • 協議速度:USB 2.0最高支持480Mbps
  3. ?CDC(通信設備類)?

    • 用途:串行通信與網絡連接
    • 示例:調制解調器、網絡攝像頭
    • 應用場景:虛擬COM端口、數據透傳
  4. ?Audio Class(音頻設備類)?

    • 用途:音頻輸入/輸出
    • 示例:USB麥克風、耳機、MIDI設備
    • 應用特點:支持音頻流傳輸與處理
  5. ?Video Class(視頻設備類,UVC)?

    • 用途:視頻捕捉與傳輸
    • 示例:網絡攝像頭、視頻采集卡
    • 協議優勢:標準化視頻傳輸協議

二)、其他設備類

  1. ?Printer Class(打印機類)?
    • 用途:打印機控制與數據傳輸
  2. ?PTP(圖像傳輸協議)?
    • 用途:相機、掃描儀等圖像設備的數據傳輸
  3. ?Hub Class(集線器類)?
    • 用途:擴展USB端口數量

三)、物理接口類型

雖然與功能分類無關,但物理接口類型影響設備兼容性:

  • ?Type-A?:最常見接口,用于U盤、鍵盤等
  • ?Type-C?:正反插設計,支持高速數據傳輸與供電
  • ?Micro/Mini USB?:主要用于舊款手機及小型設備

注:USB設備類與物理接口類型無直接綁定關系,同一接口(如Type-C)可能支持多種設備類功能

二、USB 設備 GUID 核心解析

一)、GUID 的定義與作用

?GUID(全局唯一標識符)? 是用于標識 USB 設備類別的 128 位唯一編碼,確保不同設備接口或功能在系統中被精準識別。

  • ?設備接口類 GUID?:標識設備的具體功能接口(如打印機、存儲設備),
    例如 USB 打印設備的接口 GUID 為
    ?GUID_DEVINTERFACE_USBPRINT{28d78fad-5a12-11d1-ae5b-0000f803a8c2}
  • ?設備安裝類 GUID?:用于管理驅動安裝分類(如鼠標、鍵盤),通過注冊表路徑?HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class?查看對應關系。

二)、GUID 與硬件標識符的關系

?標識符??含義??用途?
?VID?供應商 ID(由 USB-IF 分配)標識設備制造商
?PID?產品 ID(由廠商自定義)區分同一廠商的不同產品型號
?GUID?全局唯一標識符(系統或驅動定義)系統層面管理設備接口或驅動分類(如?GUID_DEVINTERFACE_USBPRINT?標識打印接口)

三)、系統級 GUID 應用場景

  1. ?驅動匹配與加載?

    • Windows 系統通過設備接口類 GUID 自動加載對應驅動程序(如?usbprint.sys?驅動綁定?GUID_DEVINTERFACE_USBPRINT)。
    • 若 GUID 與驅動注冊不匹配,設備管理器會顯示未知設備或錯誤代碼(如?43)。
  2. ?設備枚舉與管理?

    • 使用 API?SetupDiGetClassDevs?時需指定 GUID 來篩選設備(示例:DIGCF_DEVICEINTERFACE | DIGCF_PRESENT?枚舉已連接的 USB 打印機)。
    • 設備路徑(如?\\?\USB#VID_xxxx&PID_xxxx#...)中隱含 GUID 信息,用于底層通信。

四)、GUID 查看與調試方法

  1. ?注冊表查看?

    • ?設備接口類 GUID?:通過?HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses?分支查詢。
    • ?設備安裝類 GUID?:在?HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class?下按設備類別檢索。
  2. ?設備管理器調試?

    • 右鍵設備 → ?屬性? → ?詳細信息? → 選擇 ?設備類 GUID? 字段,查看當前設備綁定的 GUID。

五)、Windows 11 的 GUID 管理優化

  • ?動態切換機制?:針對多功能設備(如打印掃描一體機),系統會根據當前操作模式動態切換 GUID,優化資源分配。
  • ?USB4 兼容性增強?:新增 USB4 設備接口 GUID(如隧道協議支持),提升高速數據傳輸和 DisplayPort 視頻流的穩定性

?三、USB 打印設備 GUID

一)、USB 打印設備接口 GUID

Windows 系統通過 ?GUID(全局唯一標識符)? 識別特定設備類型。對于 USB 打印機,其設備接口 GUID 定義為:

DEFINE_GUID(GUID_DEVINTERFACE_USBPRINT, 0x28d78fad, 0x5a12, 0x11d1, 0xae, 0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2);

該 GUID 用于通過 Windows API 枚舉和識別 USB 打印設備。

二)、獲取 GUID 的編程方法

  1. ?設備枚舉核心代碼
    ?

    #include <SetupAPI.h>
    #include <initguid.h>
    #include <Usbiodef.h>HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBPRINT,  // 指定打印機接口 GUIDNULL,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
    );
    

    通過?SetupDiGetClassDevs?函數可獲取所有已連接的 USB 打印機設備實例。

  2. ?設備路徑提取?

    SP_DEVICE_INTERFACE_DATA interfaceData = {0};
    interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);// 遍歷設備接口列表
    SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_USBPRINT, 0, &interfaceData);
    
    結合?SetupDiGetDeviceInterfaceDetail?可進一步獲取設備物理路徑(如?\\?\USB#VID_04B8&PID_0202...)

四、實例說明通過USB端口控制打印機

?一)、枚舉USB打印機端口

DEFINE_GUID(GUID_DEVINTERFACE_USBPRINT,0x28d78fad, 0x5a12, 0x11d1, 0xae, 0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2);#define	FX_PRINTER_ID	_T("\\\\?\\USB#VID_03EB&PID_6013#")
#define	SL_PRINTER_ID	_T("\\\\?\\USB#VID_03EB&PID_6006#")
#define	ST_PRINTER_ID	_T("\\\\?\\USB#VID_03EB&PID_5008#")
#define OEM_PRINTER_ID	_T("\\\\?\\USB#VID_0009&PID_0005#")BYTE	CUSB_Device::EnumDeviceInterface(CString * pszDevicePath, CString * pszDeviceID, int nports)
{int           MemberIndex = 0;LONG          Result = 0;DWORD         Length = 0;HANDLE        hDevInfo;ULONG         Required;BYTE	index = 0;PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;SP_DEVICE_INTERFACE_DATA  devInfoData;hDevInfo = SetupDiGetClassDevs((LPGUID)&(GUID_DEVINTERFACE_USBPRINT), NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);if (hDevInfo == INVALID_HANDLE_VALUE){
//		MessageBox(NULL, _T("No hardware device"), NULL, MB_OK);return 0;}devInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);//Step through the available devices looking for the one we want. do{Result = SetupDiEnumDeviceInterfaces(hDevInfo, 0, (LPGUID)&(GUID_DEVINTERFACE_USBPRINT), MemberIndex++, &devInfoData);if (Result != 0){SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, NULL, 0, &Length, NULL);//Allocate memory for the hDevInfo structure, using the returned Length.//			detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)new BYTE[Length * 4];detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(GPTR, Length);;if (detailData != NULL){//Set cbSize in the detailData structure.              detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);//Call the function again, this time passing it the returned buffer size.if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInfoData, detailData, Length, &Required, NULL) == TRUE){CString szID(detailData->DevicePath);szID.MakeUpper();if ((szID.Find(SL_PRINTER_ID, 0) != -1) || (szID.Find(ST_PRINTER_ID, 0) != -1) || (szID.Find(FX_PRINTER_ID, 0) != -1) || (szID.Find(OEM_PRINTER_ID, 0) != -1)){if (nports != 0){if (index < nports){if (pszDevicePath != NULL)pszDevicePath[index] = szID;if (pszDeviceID != NULL){int iPID_POS = szID.Find(_T("PID_"));m_szSerial = szID.Right(szID.GetLength() - iPID_POS - 9);int iret = m_szSerial.Find(_T("#"));m_szSerial = m_szSerial.Left(iret);pszDeviceID[index] = m_szSerial;}index++;}}else{index++;}}}GlobalFree(detailData);}}} while (Result != 0 && MemberIndex < 127);SetupDiDestroyDeviceInfoList(hDevInfo);if (!Result && (MemberIndex >= 127)){
//		MessageBox(NULL, _T("Can not Open USB port"), NULL, MB_OK);return 0;}return index ;
}

系統有可能連接多臺打印機,所以我們只要枚舉需要控制的打印機端口,下面代碼就是用來判斷是否是我們需要控制的打印機端口。

if ((szID.Find(SL_PRINTER_ID, 0) != -1) || (szID.Find(ST_PRINTER_ID, 0) != -1) || (szID.Find(FX_PRINTER_ID, 0) != -1) || (szID.Find(OEM_PRINTER_ID, 0) != -1))

?下面代碼用于打開USB打印端口:

						m_hDevice = CreateFile(detailData->DevicePath,GENERIC_READ | GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);

二)、寫USB打印端口

DWORD CUSB_Device::writePort(BYTE *buff, DWORD len)
{DWORD writtedLen,idx,waitTimes,n,tempLen;BOOL bResult;ASSERT(buff);if( !(buff && len && this->openPort()))return 0;writtedLen = 0;idx = 0;waitTimes = 0;m_percent = 0;tempLen = len;OVERLAPPED overlapped;memset(&overlapped,0,sizeof(OVERLAPPED));overlapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);while(len){n = tempLen - idx;if( n > _SEND_BLOCK_SIZE)n = _SEND_BLOCK_SIZE;if (!::WriteFile(m_hDevice, &buff[idx], n, &writtedLen, &overlapped)){if (GetLastError() == ERROR_IO_PENDING)//GetLastError()函數返回ERROR_IO_PENDING,表明串口正在進行操作{//使用WaitForSingleObject函數等待,直到讀操作完成或延時已達到1秒鐘//當串口操作進行完畢后,overlapped的hEvent事件會變為有信號while(WaitForSingleObject(overlapped.hEvent,2000) != WAIT_OBJECT_0){waitTimes++;if(waitTimes > 6){BYTE	lpstatus[_MAX_USB_RECEIVED];if (GetPrinterStatus(lpstatus) > 0){if ((lpstatus[0] & 0xff) == 0x98){MessageBox(NULL, NULL, _TEXT("讀寫USB口出錯!"), MB_OK | MB_ICONINFORMATION );return	idx;}}}}waitTimes = 0;bResult = GetOverlappedResult(m_hDevice, &overlapped, &writtedLen, FALSE);if (!bResult) break; }else{if(waitTimes > 1)break;waitTimes++;writtedLen = 0;m_hDevice = INVALID_HANDLE_VALUE;this->openPort();}}idx += writtedLen;len -= writtedLen;m_percent = (BYTE)(idx * 100 / tempLen);}return idx;
}

三)、讀打印端口

DWORD CUSB_Device::readPort(BYTE *buff, DWORD len)
{DWORD readLen,dataLen,waitTimes = 0;
//	BOOL bResult;BYTE *lpBuff;ASSERT(buff);if( !(buff && len && this->openPort()))return 0;OVERLAPPED overlapped;memset(&overlapped,0,sizeof(OVERLAPPED));overlapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//	bResult = TRUE;readLen = 0;dataLen = 0;lpBuff = buff;while(true){::ReadFile(m_hDevice, lpBuff, len, &readLen, &overlapped);if (GetLastError() == ERROR_IO_PENDING)//GetLastError()函數返回ERROR_IO_PENDING,表明串口正在進行操作{//使用WaitForSingleObject函數等待,直到讀操作完成或延時已達到1秒鐘//當串口操作進行完畢后,overlapped的hEvent事件會變為有信號
#if	1BOOL	timewait=TRUE;while(timewait){switch(WaitForSingleObject(overlapped.hEvent,6000)){case WAIT_OBJECT_0:timewait = FALSE;break;case WAIT_TIMEOUT:case WAIT_ABANDONED:default:return 0;}}
//			GetOverlappedResult(m_hDevice, &m_ReadOvlp, &curLen, TRUE);
#elsewhile(WaitForSingleObject(overlapped.hEvent,2000) != WAIT_OBJECT_0){waitTimes++;if(waitTimes > 6){::CloseHandle(overlapped.hEvent);break;}}
#endifwhile (!GetOverlappedResult(m_hDevice, &overlapped, &readLen, FALSE));
//			if (!bResult) 
//				break;dataLen += readLen;if(dataLen < len){lpBuff += readLen;len -= readLen;continue;}elsebreak;}else{if(waitTimes > 1)break;waitTimes++;m_hDevice = INVALID_HANDLE_VALUE;this->openPort();}}	if(dataLen != len)return 0;return dataLen;
}

?四)、獲取打印機狀態

BOOL Control_Info(HANDLE hDevice,DWORD cntrlCode,LPTSTR buff,DWORD &len)
{BOOL	retFlag;DWORD	retLen;retFlag = DeviceIoControl(hDevice,		//HANDLE hDevice,cntrlCode,//DWORD cntrlCode,NULL,			//LPVOID lpInBuffer,0,				//DWORD nInBufferSize,buff,			//LPVOID lpOutBuffer,len,			//DWORD nOutBufferSize,&retLen,			//LPDWORD lpBytesReturned,NULL			// LPOVERLAPPED lpOverlapped);len = retLen;return retFlag;
}BYTE	CUSB_Device::GetPrinterStatus(BYTE * lpsts)
{
//	return 1;DWORD	len = _MAX_USB_RECEIVED;TCHAR	lptemp[_MAX_USB_RECEIVED];if( !(this->openPort()))return 0;if (Control_Info(m_hDevice,IOCTL_USBPRINT_GET_LPT_STATUS,lptemp,len)){*lpsts = (BYTE)lptemp[0];return (BYTE)len;}elsereturn 0;
}

本來想上傳完整源代碼的,但不知道為什么,一直顯示上傳中斷,無法上傳,有需要的朋友可以聯系我。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/79292.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/79292.shtml
英文地址,請注明出處:http://en.pswp.cn/web/79292.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CDGP數據治理主觀題評分標準與得分策略

1.數據模型題目評分標準 1)準確理解題目中所描述的業務邏輯和需求得[1分] 2)正確使用模型設計方法,使用信息工程、信息建模集成定義、巴克符號、陳氏符號等其中一種得[1分] 3)正確設計實體和屬性,題目中涉及的實體數量為25-30個,10個以內得[2分],10-20個得[3分],25個…

工業設計破局密碼:3D 可視化技術點燃產業升級引擎

3D可視化是一種將數據、信息或抽象概念以三維圖形、模型和動畫的形式呈現出來的技術。3D可視化技術通過構建三維數字孿生體&#xff0c;將設計思維轉化為可交互的虛擬原型&#xff0c;不僅打破了傳統二維設計的空間局限&#xff0c;更在效率、精度與用戶體驗層面開創了全新維度…

Qt中在子線程中刷新UI的方法

Qt中在子線程中刷新UI的方法 在Qt中UI界面并不是線程安全的&#xff0c;意味著在子線程中不能隨意操作UI界面組件&#xff08;比如按鈕、標簽&#xff09;等&#xff0c;如果強行操作這些組件有可能會導致程序崩潰。那么在Qt中如何在子線程中刷新UI控件呢&#xff1f; 兩種方…

為了摸魚和吃瓜,我開發了一個網站

平時上班真的比較累&#xff0c;摸魚和吃瓜還要跳轉多個平臺的話&#xff0c;就累上加累了。 所以做了一個聚合了全網主流平臺熱搜的網站。 目前市面上確實有很多這種網站了&#xff0c;所以目前最主要有兩點和他們不同&#xff1a; 給熱搜列表增加了配圖&#xff0c;刷的時候…

操作系統學習筆記第2章 (竟成)

第 2 章 進程管理 【考綱內容】 1.進程與線程&#xff1a; (1) 進程 / 線程的基本概念&#xff1b; (2) 進程 / 線程的狀態與轉換&#xff1b; (3) 線程的實現&#xff1a;內核支持的線程&#xff1b;線程庫支持的線程&#xff1b; (4) 進程與線程的組織與控制&#xff1b; (5)…

77.評論日記

房間要經常搞衛生&#xff0c;不然會很多灰&#xff0c;很多頭發&#xff0c;很多垃圾。 當然&#xff0c;即使一直搞衛生&#xff0c;在一些看不到的角落也是會慢慢囤積垃圾。 想要把那些角落也打掃干凈&#xff0c;沒別的辦法&#xff0c;只有把那個角落上所有的東西都移開&a…

語音合成之十二 TTS聲學編解碼器的演進

TTS聲學編解碼器的演進 1 引言&#xff1a;聲碼器/聲學編解碼器在現代TTS中的關鍵作用2 奠定基石&#xff1a;從早期聲碼器到神經合成的曙光3. HiFi-GAN: 革新高效高保真波形生成4. 新的疆域&#xff1a;面向富語義TTS的先進聲學編解碼器5. XCodec2.0: 統一聲學與語義信息6.BiC…

大學之大:悉尼科技大學2025.5.10

悉尼科技大學&#xff1a;從技術先驅到全球創新樞紐的百年征程 一、歷史沿革&#xff1a;從技工培訓到世界百強名校的蛻變 1. 工業革命的技術火種&#xff08;1843-1945&#xff09; 悉尼科技大學的歷史可追溯至1843年成立的悉尼機械學院&#xff08;Sydney Mechanics’ Scho…

安裝阿里云的yum源并且下載軟件(CentOS7版本)

目錄 1. 進入root模式: 2. 進入yum.repos.d文件下 3.備份 4. 安裝阿里云的yum源 5. 安裝dnf 6. 安裝epel-release 7. 清除緩存,并新建緩存 8. 安裝智能拼音軟件包 8.1安裝 8.2 進入應用程序 -- 系統工具 -- 設置 8.3重啟后就可以打中文啦~ (需要重新啟動才能)…

Discriminative and domain invariant subspace alignment for visual tasks

用于視覺任務的判別性和域不變子空間對齊 作者&#xff1a;Samaneh Rezaei&#xff0c;Jafar Tahmoresnezhad 文章于2018年12月4日收到&#xff0c;2019年5月24日被接受&#xff0c;2019年6月3日在線發表于Iran Journal of Computer Science期刊&#xff0c;DOI: 10.1007/s42…

用jsp簡單實現C語言標準化測試系統

C語言標準化測試系統 在Web編程技術的學習過程中&#xff0c;我們小組為了深入理解相關技術原理&#xff0c;提升實踐能力&#xff0c;開發了一個基于動態Web工程框架的C語言標準化考試系統。現在&#xff0c;就來和大家分享一下我們的項目經歷。 一、實驗目的剖析 這個項目…

QMK鍵盤固件自定義指南 - 打造你的專屬鍵盤體驗

QMK鍵盤固件自定義指南 - 打造你的專屬鍵盤體驗 &#x1f680; 前言 在機械鍵盤的世界里&#xff0c;QMK固件讓你的鍵盤不再只是簡單的輸入設備&#xff0c;而是可以按照你的意愿定制的強大工具。本文將深入淺出地介紹如何自定義QMK鍵盤的行為&#xff0c;從基礎概念到高級應…

5.9培訓

文件上傳 先找文件上傳的地方&#xff0c;打開代理鏈接BP&#xff0c;它需要一個xls文件 我們創建一個sqzr.xls bp攔截了之后&#xff0c;我們修改請求&#xff0c;把后綴改成php&#xff0c;發送請求 找到我們的靜態資源所在的位置 訪問http://192.168.1.100:81/static/upload…

【FAQ】HarmonyOS SDK 閉源開放能力 — PDF Kit

1.問題描述&#xff1a; 預覽PDF文件&#xff0c;文檔上所描述的loadDocument接口&#xff0c;可以返回文件的狀態&#xff0c;并無法實現PDF的預覽&#xff0c;是否有能預覽PDF相關接口&#xff1f; 解決方案&#xff1a; 1、執行loadDocument進行加載PDF文件后&#xff0c…

AutoDL實現端口映射與遠程連接AutoDL與Pycharm上傳文件到遠程服務器(李沐老師的環境)

文章目錄 以上配置的作用前提AutoDL實現端口映射遠程連接AutoDLPycharm上傳文件到遠程服務器以上配置的作用 使用AutoDL的實例:因本地沒有足夠強的算力,所以需要使用AutoDL AutoDL端口映射:當在實例上安裝深度學習的環境,但因為實例的linux系統問題,無法圖形化顯示d2l中的文件…

【Linux系列】跨平臺安裝與配置 Vim 文本編輯器

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

CountDownLatch 并發編程中的同步利器

CountDownLatch 并發編程中的同步利器 文章目錄 CountDownLatch 并發編程中的同步利器一、CountDownLatch 基礎概念1.1 什么是 CountDownLatch&#xff1f;1.2 CountDownLatch 的核心方法1.3 基本使用示例 二、CountDownLatch 實戰應用2.1 應用場景一&#xff1a;并行任務協調2…

Linux 內核鏈表宏的詳細解釋

&#x1f527; Linux 內核鏈表結構概覽 Linux 內核中的鏈表結構定義在頭文件 <linux/list.h> 中。核心結構是&#xff1a; struct list_head {struct list_head *next, *prev; }; 它表示一個雙向循環鏈表的節點。鏈表的所有操作都圍繞這個結構體展開。 &#x1f9e9; …

分書問題的遞歸枚舉算法

分數問題的遞歸枚舉算法 一、問題引入二、解題步驟1.問題分析思維導圖2.解題步驟 三、代碼實現1.代碼2.復雜度分析 四、個人總結 一、問題引入 分書問題是指&#xff1a;已知 n 個人對 m 本書的喜好&#xff08;n≤m&#xff09;&#xff0c;現要將 m 本書分給 n 個人&#xf…

密碼學--AES

一、實驗目的 1、完成AES算法中1輪加密和解密操作 2、掌握AES的4個基本處理步驟 3、理解對稱加密算法的“對稱”思想 二、實驗內容 1、題目內容描述 &#xff08;1&#xff09;利用C語言實現字節代換和逆向字節代換&#xff0c;字節查S盒代換 &#xff08;2&#xff09;利…