這裡蒐索程式師資訊,查找有用的技術資料
當前位置:首頁 » 服務存儲 » 鏈接存儲隱式鏈接
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

鏈接存儲隱式鏈接

發布時間: 2022-04-21 14:06:21

❶ 動態鏈接庫的顯示載入和隱式載入的區別

兩種方法對於你的程序調用動態庫時沒有任何區別,只是你在編程時,步驟是不一樣的。顯式調用麻煩了點,但可以沒有相應的lib庫;隱式調用,使用起來比較簡單,有函數的聲明就可以了,但必須有lib庫。

在VC中兩種方式的具體方法:
一、動態庫的隱示調用:
在 VC 工程中直接鏈接靜態輸入庫XXX.lib,然後即可像調用其它源文件中
的函數一樣調用DLL中的函數了。
二、動態庫的顯式調用:
顯式調用動態庫步驟:
1、創建一個函數指針,其指針數據類型要與調用的 DLL 引出函數相吻
合。
2、通過 Win32 API 函數LoadLibrary()顯式的調用DLL,此函數返回
DLL 的實例句柄。
3、通過 Win32 API 函數GetProcAddress()獲取要調用的DLL 的函數地
址,把結果賦給自定義函數的指針類型。
4、使用函數指針來調用 DLL 函數。
5、最後調用完成後,通過 Win32 API 函數FreeLibrary()釋放DLL 函數。

❷ VC動態鏈接庫的隱式鏈接具體配置

在工程中link選項,添加 libmysql.lib連接。
或在代碼中寫入#pragma comment(lib, "libmysql.lib")

❸ 為什麼鏈接文件不適合隨機存取

鏈接文件分為顯式鏈接和隱式鏈接,隱式鏈接就如我們平常所說的鏈表一樣,無法隨機存取,而現實鏈接也是一種鏈表,但是是用數組表示的鏈表,所以是可以支持隨機「存取」的。

❹ c++沒有lib文件任然可以隱式鏈接

我覺得不需要。
lib是靜態庫。
有h就好了。
#pragma也不要。
-l和-L指定庫就行了。

❺ 1.44mb軟盤fat表佔多大存儲空間

你kb表示錯了吧,應該是KB。表項數=1.44MB/1KB=1.44K.由於每個表項佔12位(bit),1B(byte位元組)=8位。所以fat空間=1.44K*(12/8)B=2.16KB。

❻ 連續組織方式、隱式鏈接、顯式鏈接,可以用生活中的例子說明一下這些分別是什麼意思嗎

想像一下,剛剛月考結束,班主任手裡拿著一份成績排名表。
連續分配,就是按照這份排名表依次排座位,可以先排完第一組,然後排第二組,然後第三組……
隱式鏈接,就是班主任叫一個人的名字,一個人就進教室選座位,座位可以隨意選,只要那個座位上沒有人就行……
顯示鏈接,就是這個班主任比較懶,只記得班上第一名的名字,但是班上每個人都知道自己下一名的名字,於是,班主任叫第一名進教室選座位,然後第一名選好了,第一名叫第二名進教室選座位,班主任可以坐在一邊喝茶了……
操作系統用一張FAT表來記錄第一名和第二名,第二名和第三名之間的聯系。
班主任手中的排名表就是一個順序文件,數據是按照怎樣的方式組織起來就是通過邏輯結構表現出來的,大家排座位的方式就是文件的物理結構。

❼ lib和dll有什麼區別,什麼叫靜態鏈接庫,什麼叫動態連接庫

靜態鏈接庫與動態鏈接庫區別
靜態鏈接庫與動態鏈接庫都是共享代碼的方式,如果採用靜態鏈接庫,則無論你願不願意,lib 中的指令都全部被直接包含在最終生成的 EXE 文件中了。但是若使用 DLL,該 DLL 不必被包含在最終 EXE 文件中,EXE 文件執行時可以「動態」地引用和卸載這個與 EXE 獨立的 DLL 文件。靜態鏈接庫和動態鏈接庫的另外一個區別在於靜態鏈接庫中不能再包含其他的動態鏈接庫或者靜態庫,而在動態鏈接庫中還可以再包含其他的動態或靜態鏈接庫。動態庫就是在需要調用其中的函數時,根據函數映射表找到該函數然後調入堆棧執行。如果在當前工程中有多處對dll文件中同一個函數的調用,那麼執行時,這個函數只會留下一份拷貝。但是如果有多處對lib文件中同一個函數的調用,那麼執行時,該函數將在當前程序的執行空間里留下多份拷貝,而且是一處調用就產生一份拷貝。
靜態鏈接庫與靜態鏈接庫調用規則總體比較如下:
1、 靜態鏈接庫(比較簡單):
首先,靜態鏈接庫的使用需要庫的開發者提供生成庫的.h頭文件和.lib文件。生成庫的.h頭文件中的聲明格式如下:
extern "C" 函數返回類型 函數名(參數表);
在調用程序的.cpp源代碼文件中如下:
#include "../lib.h"
#pragma comment(lib,"..//debug//libTest.lib") //指定與靜態庫一起鏈接
其次因為靜態鏈接庫是將全部指令都包含入調用程序生成的EXE文件中。因此如果用的是靜態鏈接庫,那麼也就不存在「導出某個函數提供給用戶使用」的情況,要想用就得全要!要不就都別要!
2、 態鏈接庫:
動態鏈接庫的使用需要庫的開發者提供生成的.lib文件和.dll文件。或者只提供dll文件。
首先我們必須先注意到DLL內的函數分為兩種:
1) 出函數,可供應用程序調用;
2) LL內部函數,只能在 DLL 程序使用,應用程序無法調用它們。
因此調用程序若想調用DLL中的某個函數就要以某種形式或方式指明它到底想調用哪一個函數。
Ø 對於DLL的導出,可以採用如下方法:
#ifdef WLL_EXPORTS
#define WLL_API __declspec(dllexport)
#else
#define WLL_API __declspec(dllimport)
#endif
這是導出類的宏定義,將導出類必須加上該宏,才能被導出。
此處的WLL_EXPORTS會出現在 projectàsettingsàC++à PreProcessor的PreProcessor definition中,這個MACRO表明其要定義一個導出宏。
當前庫編譯時,加了WLL_API的類將被導出,而包含該頭文件的其他調用DLL或EXE,由於沒有定義WLL_API宏,將申明為導入該類。
Ø 動態庫函數的調用,可以採用靜態鏈接的方式,主要步驟如下:
包含DLL中導出的頭文件。
採用#pragma comment(lib,"..//debug//libTest.lib")導入動態庫生成的*.lib頭文件。或在projectàsettingsàLinkeràInput的Additional Dependencies中加入lib文件。
將動態庫生成的*.dll文件放到EXE或DLL的同一目錄下。
Ø 也可以採用動態載入的方式調用,步驟如下:
Another.dll有一個int Add(int x,int y) 函數。則完整的調用過程如下:
typedef int (* FunPtr)(int,int); //定義函數指針
FunPtr funPtr;
Handle handle =LoadLibrary("Another.dll");
funPtr =(FunPtr)GetProcAddress(handle ,"Add");
funPtr(2,3); // 2+3;
FreeLibrary(handle); // 釋放載入的動態庫
LIB文件
目前以lib後綴的庫有兩種,一種為靜態鏈接庫(Static Libary,以下簡稱「靜態庫」),另一種為動態連接庫(DLL,以下簡稱「動態庫」)的導入庫(Import Libary,以下簡稱「導入庫」)。
靜態庫是一個或者多個obj文件的打包,所以有人乾脆把從obj文件生成lib的過程稱為Archive,即合並到一起。比如你鏈接一個靜態庫,如果其中有錯,它會准確的找到是哪個obj有錯,即靜態lib只是殼子。
動態庫一般會有對應的導入庫,方便程序靜態載入動態鏈接庫,否則你可能就需要自己LoadLibary調入DLL文件,然後再手工GetProcAddress獲得對應函數了。有了導入庫,你只需要鏈接導入庫後按照頭文件函數介面的聲明調用函數就可以了。
導入庫和靜態庫的區別很大,他們實質是不一樣的東西。靜態庫本身就包含了實際執行代碼、符號表等等,而對於導入庫而言,其實際的執行代碼位於動態庫中,導入庫只包含了地址符號表等,確保程序找到對應函數的一些基本地址信息。
這也是實際上很多開源代碼發布的慣用方式:
1、 預編譯的開發包:包含一些.dll文件和一些.lib文件。其中這里的.lib就是導入庫,而不要錯以為是靜態庫。但是引入方式和靜態庫一樣,要在鏈接路徑上添加找到這些.lib的路徑。而.dll則最好放到最後產生的應用程序exe執行文件相同的目錄。這樣運行時,就會自動調入動態鏈接庫。
2、 用戶自己編譯:下載的是源代碼,按照readme自己編譯。生成很可能也是.dll + .lib(導入庫)的庫文件
3、 如果你只有dll,並且你知道dll中函數的函數原型,那麼你可以直接在自己程序中使用LoadLibary調入DLL文件,GetProcAddress獲取函數地址,然後調用。
DLL文件
動態鏈接庫 (DLL) 是作為共享函數庫的可執行文件。動態鏈接提供了一種方法,使進程可以調用不屬於其可執行代碼的函數。函數的可執行代碼位於一個 DLL 中,該 DLL 包含一個或多個已被編譯、鏈接並與使用它們的進程分開存儲的函數。DLL 還有助於共享數據和資源。多個應用程序可同時訪問內存中單個 DLL 副本的內容。
動態鏈接與靜態鏈接的不同之處在於它允許可執行模塊(.dll 文件或 .exe 文件)僅包含在運行時定位 DLL 函數的可執行代碼所需的信息。在靜態鏈接中,鏈接器從靜態鏈接庫獲取所有被引用的函數,並將庫同代碼一起放到可執行文件中。
使用動態鏈接代替靜態鏈接有若干優點。DLL 節省內存,減少交換操作,節省磁碟空間,更易於升級,提供售後支持,提供擴展 MFC 庫類的機制,支持多語言程序,並使國際版本的創建輕松完成。
API 就是應用程序編程介面。它是能用來操作組件、應用程序或者操作系統的一組函數。典型的情況下,API 由一個或多個提供某種特殊功能的 DLL 組成。
DLL 是一個文件,其中包含了在 Microsoft Windows下運行的任何應用程序都可調用的函數。運行時,DLL 中的函數動態地鏈接到調用它的應用程序中。無論有多少應用程序調用 DLL 中的某個函數,在磁碟上只有一個文件包含該函數,且只在它調入內存時才創建該 DLL。 您聽到最多的 API 可能是 Windows API,它包括構成 Windows 操作系統的各種 DLL。每個 Windows 應用程序都直接或間接地與 Windows API 互動。Windows API 保證 Windows 下運行的所有應用程序的行為方式一致。
隨著 Windows 操作系統的發展,現已發布了幾個版本的 Windows API。Windows 3.1 使用 Win16 API。Microsoft Windows NT、Windows 95 和 Windows 98平台使用 Microsoft Win32 API。除 Windows API 外,其他一些 API 也已發布。例如,郵件應用程序編程介面 (MAPI) 是一組可用於編寫電子郵件應用程序的 DLL。API 傳統上是為開發 Windows 應用程序的 C 和 C++ 程序員編寫的,但其他的編程語言(包括VBA)也可以調用 DLL 中的函數。因為大部分 DLL 主要是為 C 和 C++ 程序員編寫和整理說明的,所以調用 DLL 函數的方法與調用 VBA 函數會有所不同。在使用 API 時必須了解如何給 DLL 函數傳遞參數。
警告:調用 Windows API 和 其他 DLL 函數可能會給您的應用程序帶來不良影響。從自己的代碼中直接調用 DLL 函數時,您繞過了 VBA 通常提供的一些安全機制。如果在定義或調用 DLL 函數時出現錯誤(所有程序員都不可避免),可能會在應用程序中引起應用程序錯誤(也稱為通用性保護錯誤,或 GPF)。最好的解決辦法是在運行代碼以前保存該項目,並確保了解 DLL 函數調用的原理。

❽ 比較順序存儲和鏈接存儲兩種存儲結構的優缺點。(參考教材4.1)

/*****************************************************
順序表演算法
嚴格按照《數據結構C語言版》實現
敬請指正
vincent
2006-12-28
******************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10

typedef int Status;
typedef int ElemType;
/*C中的函數指針類型*/
typedef Status (*cmp)(ElemType x,ElemType i);
typedef void (*vis)();

struct SqList{
ElemType *elem;
int length;
int listsize;
};
/*創建新的順序表*/
Status InitList(SqList &L);
/*銷毀順序表*/
Status DestroyList(SqList &L);
/*如果順序表為空TRUE 否則FALSE*/
Status ListEmpty(SqList &L);

/*返回順序表長度*/
int ListLength(SqList &L);
/*返回指定位置的元素*/
ElemType GetElem(SqList &L,int i,ElemType *e);
/*定位指定元素,如果有返回第一個匹配的元素的位置*/
int LocateElem(SqList &L,ElemType e,cmp f);
/*int LocateElem_sq(SqList &L,ElemType e);*/
/*返回當前元素的前一個元素*/
ElemType PriorElem(SqList &L,int pos,ElemType *pre_e);
/*返回當前元素的後一個元素*/
ElemType NextElem(SqList &L,int pos,ElemType *next_e);
/*清空表*/
Status ClearList(SqList &L);
/*在指定位置插入元素*/
Status ListInsert(SqList &L,int i,ElemType e);
/*刪除指定位置的元素*/
Status ListDelete(SqList &L, int i, ElemType e);
/*遍歷順序表*/
Status ListTraverse(SqList &L, vis v);

/*在順序表中比較元素e*/
Status compare(ElemType x,ElemType i);
/*visit 函數在遍歷表時返回當前元素*/
void visit(SqList &L);

main(){
int i,t ;
ElemType a;
int b;
cmp f;
SqList L;
ElemType *e;
if(!InitList(L)){
printf("E001\n");
exit(ERROR);
}

printf("請輸入數字,默認為5個\n");
for(i =1;i <= 5; i++){
int z[5] ;
scanf("%d",&z[i-1]);
if (!ListInsert(L,i,z[i-1])){
printf("E002\n");
exit(ERROR);
}
}
printf("結果是:\n");
for(i = 1 ; i <= L.length;i++){
printf("%d\n",GetElem(L,i,e));
}

/*返回表長*/
printf("%d\n",ListLength(L));

a=3;

printf("%d\n",LocateElem(L,a, f));

DestroyList(L);

}

/*構造一個空表*/

Status InitList(SqList &L) {

L.elem = (ElemType *) malloc(LIST_INIT_SIZE * sizeof(ElemType));
if(!L.elem)exit(OVERFLOW);

L.length = 0;
L.listsize = LIST_INIT_SIZE;
return OK;

}
/*銷毀一個表*/
Status DestroyList(SqList &L) {
if(!L.elem)exit(ERROR);
free(L.elem);
L.elem = NULL;
//L = NULL;
return OK;
}
/*如果順序表為空TRUE 否則FALSE*/
Status ListEmpty(SqList &L){
if(L.elem == NULL){
return TRUE;
}
else {
return FALSE;
}

}
/*返回順序表長度*/
int ListLength(SqList &L){
if(!L.elem)exit(ERROR);
return L.length;
}

/*返回指定位置的元素*/
ElemType GetElem(SqList &L,int i,ElemType *e){
if(!L.elem || i > L.length || i < 1 )exit(ERROR);
/*e = L.elem + sizeof(ElemType)*(i-1);*/
e = L.elem + i - 1;
return *e;
}

/*定位指定元素,如果有返回第一個匹配的元素的位置*/
int LocateElem(SqList &L,ElemType e,cmp f){

//f = compare(ElemType x,int i);
int z,s;
ElemType *y;

if(!L.elem) exit(ERROR);
for(z=0;z<= L.length;z++){

/*y = L.elem + sizeof(ElemType)*z;*/
y = L.elem + z;
s = f(*y,e);
if (s == TRUE) return z;
}

return 0;
}

/*在順序表中比較元素e*/
Status compare(ElemType x,ElemType i){
if (x == i) return TRUE;
return FALSE;
}

/*返回當前元素的前一個元素*/
ElemType PriorElem(SqList &L,int pos,ElemType *pre_e){
if(pos > L.length || pos < 2) exit(ERROR);
pre_e = L.elem + pos -1;
return *pre_e;
}

/*返回當前元素的後一個元素*/
ElemType NextElem(SqList &L,int pos,ElemType *next_e){
if(pos > L.length -1 || pos < 1)exit(ERROR);
next_e = L.elem + pos +1;
return *next_e;
}

/*清空表將表中元素去掉,設置長度為0*/
Status ClearList(SqList &L){
int i;
if(!L.elem)exit(ERROR);
free(L.elem);
L.length = 0;
return OK;
}

/*在指定位置插入元素*/
Status ListInsert(SqList &L,int i,ElemType e){
ElemType *p,*q,*newbase;

if(i <1 || i > L.length +1){
printf("E004\n");
return(ERROR);
}

if(L.length >= L.listsize){
newbase = (ElemType *)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!newbase)exit(OVERFLOW);
L.elem = newbase;
L.listsize += LISTINCREMENT;
}
q = &(L.elem[i -1]);
for(p = &(L.elem[L.length -1]);p >= q; --p) *(p+1) = *p;
*q = e ;
++L.length;
return OK;
}

/*刪除指定位置的元素*/
Status ListDelete(SqList &L, int i, ElemType e){
ElemType *p,*q;
if(i <1 || i > L.length +1)return(ERROR);
p = &(L.elem[i - 1]);
e = *p;
q = L.elem + L.length -1;
for(++p;p <= q;++p) *(p-1) = *p;
--L.length;
return OK;
}

❾ 鏈接分配文件:隱式鏈接 顯示鏈接,求他們的區別

隱式鏈接指針在磁碟上,每一次都要讀取磁碟。顯示鏈接將磁碟上文件的鏈式結構用內存的一張FAT表去描述,查找時可以在內存中進行。定位後再讀磁碟。速度比隱式快很多。

❿ 隱式鏈接分配會有內部碎片嗎也就是說,如果一個文件的末尾部分只分配到一個磁碟塊的一部分,那

隱式鏈接分配的主要問題在於:
其只適合於順序訪問,對隨機訪問的效率及其低效。此外,其可靠性較差,任何一個指針出現問題,都會導致整個鏈的斷開。
可以將幾個盤塊組成一個簇,然後以簇為單位進行分配,會減少查找指定塊的時間,但是會增加內部碎片。
如果將一個邏輯文件存儲到外存上,並不要求為整個文件分配一塊連續的空間,而是可以將文件裝到多個離散的盤塊中,這樣就可以消除連續分配的缺點。
採用鏈接分配方式時,可通過在每個盤塊上的鏈接指針,將同屬於一個文件的多個離散盤塊鏈接成一個鏈表,把這樣形成的物理文件稱為鏈接文件。鏈接分配採取離散分配方式,消除了外部碎片,故而顯著地提高了外存空間的利用率,並且對文件的增、刪、改、查十分方便。鏈接方式可分為隱式鏈接和顯示鏈接兩種形式。