天天看點

C語言答疑解惑

C語言答疑解惑 C語言中有很多函數、語言特性用的不是很熟悉,特别是涉及指針的操作,總是自己認為怎樣怎樣,卻沒有真正的去使用,沒有使用就沒有發言權。這裡結合使用VS2005探究自己疑惑之所在,以後遇到的繼續補充。 一、函數的使用 (1)malloc和free:malloc和free用于動态記憶體的申請和釋放,對應于C++中的new和delete。 void *malloc(long NumBytes):配置設定NumBytes個位元組,并傳回一個指針指向該區域。如果申請失敗,傳回NULL。 void free(void *FirstByte):用于釋放FirstByte指向的記憶體區域。 程式如下: int* p = NULL; p = (int *)malloc(sizeof(int)*5); memset(p,0,sizeof(int)*5); free(p); p = NULL; 執行p = (int *)malloc(sizeof(int)*5);語句後,p被配置設定記憶體位址和記憶體内容為: 0x003B2F50 cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd fd 執行memset(p,0,sizeof(int)*5);後記憶體情況為: 0x003B2F50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fd int類型占用四個位元組,一共20個位元組全部初始化為0。 執行free後,該位址内容為: 0x003B2F50 ee fe ee fe ee fe ee fe ee fe ee fe ee fe ee fe ee fe ee fe 記憶體位址空間被釋放,但是此時p仍然指向0x003b2f50,執行p = NULL;後,p指向位址0x00000000。 (2)memset:首先明确一點,memset是位元組操作函數,是以其頭檔案是string.h。 void *memset(void *s, int ch, unsigned n):将s開始的n個位元組全部初始化為ch的ascii碼值。 它是逐個位元組進行操作,是以,對于char這種一個位元組的資料類型,可以達到我們的初始化要求。而如果是int資料類型,則會出現不是我們預想的情況: char arr[5]; memset(arr,0,5);

int integer[5]; memset(integer,0,5*sizeof(int)); int integer1[5]; memset(integer1,1,5*sizeof(int)); printf("%d",integer1[0]); 記憶體情況為: Arr:0x0012FF4C 00 00 00 00 00 Integer:0x0012FF30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Integer1:0x0012FF14 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 Int類型占四個位元組,每個位元組用1進行替換,一個位元組包括8bit,是以替換的内容為00000001000000010000000100000001,是以列印輸出integer1[0]時輸出的是這個二進制的十進制表示,也就是16843009。 (3)memcpy和strcpy void* memcpy(void *dest, const void* src, size_t n):從src開始的記憶體位置拷貝n個位元組到dest指向的記憶體位置。仍然是拷貝位元組。 void *strcpy(char* dest, const char* src):拷貝的是字元串,以\0為結束标志(直到遇到\0拷貝停止,\0參與拷貝)。如果碰不到\0,trcpy一直複制,存在危險,是以建議使用strncpy(dest,src,n); 對于char類型而言,memcpy增加了拷貝個數的限制,strcpy完成整個字元串的拷貝。 二、語言特性: (1)字元數組和字元串 char c[] = "Hello"; char *cc = "World"; int a = sizeof(c); int b = strlen(c); int aa = sizeof(cc); int bb = strlen(cc); 字元數組c的數組長度為6,取值a[0]…a[5],包括\0,指針cc指向字元串的長度為5,不包括\0。 Sizeof計算類型所占用的位元組數目,計算指針時等于4,但是數組首位址雖然為指針,但是仍然計算數組所占有的位元組數目,例如int ax[2];sizeof(ax) = 8;strlen計算字元串長度,不包括\0。 上述程式執行結果為:a = 6; b = 5; aa = 4; bb = 5; (2)結構體可以直接指派嗎? struct MyNode myNode; myNode.i = 1; myNode.c = 'c'; struct MyNode myNode1; myNode1 = myNode; 檢視myNode1可以看到其值跟myNode相等,完成了直接指派。但是如果結構體中有指針存在,則直接指派程式設計了“淺拷貝”,使用時需要注意。 三、連結清單的操作 (1)建立連結清單 typedef struct node { int value; struct node* pNext; }Node;

Node *head = NULL; //建立連結清單 bool create() { head = (Node*)malloc(sizeof(Node)); if(NULL == head) { return false; } head->pNext = NULL; head->value = 0; return true; } (2)增加節點: bool add(Node* pNode) { Node * pHead = head; if(pHead == NULL) { return false; } Node * before = NULL; while(pHead != NULL) { before = pHead; pHead = pHead->pNext;

} before->pNext = pNode; pNode->pNext = NULL; return false; } (3)排序 void sort() { //冒泡排序 Node* pHead = head; if(head == NULL) { return; } if(pHead->pNext == NULL) { return; }

Node* pi = pHead->pNext; Node* pj = pi->pNext; for(;pi != NULL;pi=pi->pNext) { for(pj = pi->pNext;pj != NULL;pj=pj->pNext) { if(pj->value>pi->value) { int tmp = pj->value; pj->value = pi->value; pi->value = tmp; } } } } (4)删除 void del(int index) { int len = 0; Node *pHead = head; if(pHead == NULL) { return; } pHead = pHead->pNext; while(pHead!=NULL) { len ++; pHead = pHead->pNext; }

if(index>len) { return; } pHead = head->pNext; Node *before = head; for(int i=0;i<index;i++) { before = pHead; pHead = pHead->pNext; } Node *after = pHead->pNext; free(pHead); before->pNext = after; return; }

繼續閱讀