請允許我一點點的去補充,如果有問題可以進行留言
說起c語言想必所有用c語言敲過代碼的人應該都知道main()函數吧
那麼肯定會有人想到爲什麼用c語言寫程序就一定要有main()函數呢
那麼整個程序在執行的時候又是如何進行的呢?
int main()和void main()有什麼區別呢?
main函數的具體作用?實現機制?main()函數又是什麼函數呢(庫函數?系統函數?還是系統調用?)
main()函數的參數?
什麼情況下我們不需要主函數呢?
這裏沒有具體擴展說明不需要主函數的原因
說明:
那麼整個程序在執行的時候又是如何進行的呢?
目標文件並不能直接執行,他首先需要載入到連接器中。連接器確認main函數爲初始進入點(程序開始執行的地方),把符號引用(symbolic reference)綁定到內存地址,把所有的目標文件集中在一起,再加上庫文件,從而產生可執行程序。main函數不能被其他函數調用,main函數不一定要放到代碼的最後,只需要保證在它被運行的時候所調用的其他的函數能被找到就OK(函數聲明)。int main()和void main()有什麼區別呢?
關於main(),因爲C99標準定義了main必須返回一個int值,所以int main是最標準的寫法,但是在C99之前的一些程序,因爲沒有相關規範,所以有可能寫void main,但是這種寫法在一些對c語言標準比較嚴格的編譯器中有可能是導致編譯錯誤的,例如在GCC中,那種寫法至少是一個warning。而且,即使你寫的void main,編譯器編譯的時候,還是會返回一個默認的值的,所以兩者沒有本質的區別。main函數的具體作用?實現機制?main()函數又是什麼函數呢(庫函數?系統函數?還是系統調用?)
(理解中,waiting。。。)main()函數的參數?
main()的參數呢是一個可變參數。對於可變參數在《c和指針》 這本書的134頁提到(後面我也會具體的寫出來)
我們常用到的是int main(int argc, char* argv[])
argc指的是命令行參數的個數,argv就是指每個參數是什麼?還有 int main(int argc, char* argv[], char * envp[] )不常用
前面兩個的意思一樣,envp是指環境變量
舉個在Linux上的例子:
你編寫了一個main.c程序,然後在shell中(當前路徑下,就是你main.c的路徑)輸入:gcc main.c 就會生成main.c的可執行程序a.out,你想運行這個程序就需要在命令行(也是當前路徑)輸入:./a.out
main.c 就被編譯運行了,argc=1;argv[0]=./a.out (這種表現方式你可以與數組進行類比)
main.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int i = 0;
printf("%d\n",argc);
for(;i < argc;i++)
{
printf("%s ",argv[i]);
}
return 0;
}
- 什麼情況下我們不需要主函數呢?
這裏沒有具體擴展說明不需要主函數的原因
舉個列子:對於頭文件想必大家都聽過(頭文件就不需要主函數)
一個最常見的頭文件## stdio.h ##的引用
那麼頭文件又怎麼寫?寫了之後又怎麼用呢?爲什麼說頭文件中不需要主函數?下面我們簡單的建立一個單鏈表的頭文件 list.h (僅僅是爲了舉例實現list.h的建立,所以只有單鏈表少部分功能)
list.h文件
#ifndef LIST_H
#define LIST_H
typedef int ElemType;//自定義數據類型
typedef enum{ERROR=0,OK=1}Status;
typedef struct node{
ElemType data;
struct node* next;
}Node,*PtrNode;
typedef struct list{
PtrNode head;
int cursize;
}List;
//初始化一個單鏈表,具有頭指針,頭結點,頭結點->next=NULL;
Status InitList(List *plist);
//刪除整個鏈表,使頭結點->next=NULL;
Status ClearList(List *plist);
Status DestroyList(List *plist)
//頭插法添加數據;
Status Insert_head(List *plist, ElemType x);
//尾插法添加數據;
Status Insert_tail(List *plist, ElemType x);
int getlength(List *plist); //獲取單鏈表的長度;
Status printList(List *plist); //打印整個鏈表;
//獲取鏈表中第i個位置處節點的數據元素;
ElemType getElem(List *plist,int i);
//從第一個數據開始刪除
Status Del_head(List *plist);
#endif
頭文件list.h的實現還需要一個list.cpp文件
list.cpp
#include "list.h"
#include <stdio.h>
PtrNode BuyNode()
{
PtrNode s = (PtrNode)malloc(sizeof(Node));
if(s == NULL) exit(-1);
memset(s,0,sizeof(Node));//首次給這片空間賦值,相當於初始化
return s;
}
//初始化一個單鏈表,具有頭指針,頭結點,頭結點->next=NULL;
Status InitList(List *plist)
{
if(plist == NULL) return(ERROR);
plist->head = BuyNode();
plist->cursize = 0;
return(OK);
}
//刪除整個鏈表,使頭結點->next=NULL;
Status ClearList(List *plist)
{
if(plist == NULL) return(ERROR);
while(plist->head->next != NULL)
{
PtrNode p = plist->head->next;
plist->head->next = p->next;
free(p);
}
if(plist->head->next == NULL)
return(OK);
}
Status DestroyList(List *plist)
{
if(plist == NULL) return(ERROR);
ClearList(plist);
free(plist->head);
plist->head = NULL;
return(OK);
}
//頭插法添加數據;
Status Insert_head(List *plist, ElemType x)
{
if(plist == NULL) return(ERROR);
PtrNode s = BuyNode();
s->next = plist->head->next;
plist->head->next = s;
s->data = x;
plist->cursize += 1;
return(OK);
}
//尾插法添加數據;
Status Insert_tail(List *plist, ElemType x)
{
if(plist == NULL) return(ERROR);
PtrNode s = BuyNode();
PtrNode p = plist->head;
while(p->next != NULL)
{
p = p->next;
}
p->next = s;
s->data = x;
plist->cursize += 1;
return(OK);
}
int getlength(List *plist) //獲取單鏈表的長度;
{
if(plist == NULL )
{
printf("getlength failed: 鏈表被摧毀或不存在\n");
return;
}
return(plist->cursize);
}
Status printList(List *plist) //打印整個鏈表;
{
if(plist == NULL) return(ERROR);
PtrNode p = plist->head->next;
while(p != NULL)
{
printf("%d\n",p->data);
p = p->next;
}
return(OK);
}
//獲取鏈表中第i個位置處節點的數據元素;
ElemType getElem(List *plist,int i)
{
if(plist == NULL) return(ERROR);
PtrNode p = plist->head->next; //指向第一個有數據的節點
int val = 1;
for(;val < i;val++)
{
p = p->next;// val=1 p指向第二個。當val=i-1 p指向第i個數據節點
}
return(p->data);
}
//刪除第一個數據
Status Del_head(List *plist)
{
if(plist == NULL) return(ERROR);
PtrNode p = plist->head->next;
plist->head->next = plist->head->next->next;
free(p);
p=NULL;
return(OK);
}
當這兩個文件都建立好了,那麼就說明這個頭文件list.h的內容完善了,那麼該如何使用呢?文檔又該放在什麼位置?