main()函數

請允許我一點點的去補充,如果有問題可以進行留言
說起c語言想必所有用c語言敲過代碼的人應該都知道main()函數吧
那麼肯定會有人想到爲什麼用c語言寫程序就一定要有main()函數呢

  • 那麼整個程序在執行的時候又是如何進行的呢?

  • int main()和void main()有什麼區別呢?

  • main函數的具體作用?實現機制?main()函數又是什麼函數呢(庫函數?系統函數?還是系統調用?)

  • main()函數的參數?

  • 什麼情況下我們不需要主函數呢?
    這裏沒有具體擴展說明不需要主函數的原因

說明:

  1. 那麼整個程序在執行的時候又是如何進行的呢?
    目標文件並不能直接執行,他首先需要載入到連接器中。連接器確認main函數爲初始進入點(程序開始執行的地方),把符號引用(symbolic reference)綁定到內存地址,把所有的目標文件集中在一起,再加上庫文件,從而產生可執行程序。main函數不能被其他函數調用,main函數不一定要放到代碼的最後,只需要保證在它被運行的時候所調用的其他的函數能被找到就OK(函數聲明)。

  2. int main()和void main()有什麼區別呢
    關於main(),因爲C99標準定義了main必須返回一個int值,所以int main是最標準的寫法,但是在C99之前的一些程序,因爲沒有相關規範,所以有可能寫void main,但是這種寫法在一些對c語言標準比較嚴格的編譯器中有可能是導致編譯錯誤的,例如在GCC中,那種寫法至少是一個warning。而且,即使你寫的void main,編譯器編譯的時候,還是會返回一個默認的值的,所以兩者沒有本質的區別。

  3. main函數的具體作用?實現機制?main()函數又是什麼函數呢(庫函數?系統函數?還是系統調用?)
    (理解中,waiting。。。)

  4. 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;
}
  1. 什麼情況下我們不需要主函數呢?
    這裏沒有具體擴展說明不需要主函數的原因
    舉個列子:對於頭文件想必大家都聽過(頭文件就不需要主函數)
    一個最常見的頭文件## 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的內容完善了,那麼該如何使用呢?文檔又該放在什麼位置?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章