C语言重要知识点回顾
太久沒有看C語言相關知識了,開始要整理回顧一些重點知識點啦,因為各大公司筆試還是有許多C語言相關的題,做個復習。
const 關鍵字與指針修飾使用
普通指針使用:
//普通指針使用,我們通過 i 或者 p 指針都能改變變量值 void test1() {int i = 1;int * p = &i;printf("p=%d\n",*p);i = 2;printf("p=%d\n",*p);(*p)++;printf("p=%d\n",*p);printf("i=%d\n",i); }輸出結果:
這個結果是我們好理解的。
接著 const int *p 問題
// const int *p 表示p 所指的對象是只讀不可以改變的,但p 指針可以指向其他地址 void test2() {int i = 1;int j = 100;const int * p = &i;printf("p=%d\n",*p);i = 2;printf("p=%d\n",*p);p = &j;printf("p=%d\n",*p);/*(*p)++;// 出錯 error:increment of read-only lacation '*p'printf("p=%d\n",*p);*/ } 輸出結果:這里我們發現指針p 我們可以隨便調整指向哪塊已知的內存空間,但是不能通過 給*p 復制來改變指針所指的對象。
int const *p 和上面const int *p ?效果一樣這里就不多說啦。
接下來說 int * const p 形式,如下測試代碼:
// int * const p 表示指針p 不可修改,但是指針p 所指向的內容可以修改 void test3() {int i = 1;int j = 100;int * const p = &i;printf("p=%d\n",*p);i = 2;printf("p=%d\n",*p);/*p = &j;// error:assignment of read-only variable 'p'printf("p=%d\n",*p);*/(*p)++;printf("p=%d\n",*p);printf("i=%d\n",i); }輸出結果:
最后一種情況就是上面情況結合在一起const?int * const p 這樣就是p 指針無法修改,p 指針所指的內容也無法修改。
C與指針第六章習題
1.
char * find_char(char const * source , char const *chars) {if(source==NULL || chars==NULL)return NULL;char const * cp;for(;*source!='\0';source++){// 這里每次遍歷chars 中內容for(cp=chars;*cp!='\0';cp++){if(*source == *cp)return (char *)source;}}return NULL; }實現中發現一個問題:char a[] 與 char *a 的區別char a[]在運行時賦值,值會從靜態區賦值到函數的棧中,對它進行修改不會產生任何問題。char *a在編譯時就確定了,a指向靜態區中的值,沒有賦值到函數棧中, 因此對指針的內容進行修改會產生錯誤。
這個問題詳細解釋:http://blog.chinaunix.net/uid-20583479-id-1920067.html
2.
3. void reverse_string(char *str) {if(str == NULL)return;char *p = str;int count = 0;char ch;for(;*p!='\0';p++){count++;}p = str;char * end = p + count -1;while(p < end){ch = *p;*p = *end;*end = ch;p++;end--;}*(str+count) = '\0';printf("%s\n",str); }
指向數組的指針VS指針數組
指向數組的指針:
int vector[10], *vp = vector; 這個聲明是合法的,它為整型數組分配內存,并把vp 聲明為指向整型的的指針。
int matrix[2][3] matrix 并不是指向整型的的指針,而是一個指向整型數組的指針,我們應該如何聲明指向數組的指針?
int (*mp)[3]這里要帶上第二維的數據控制,不是mp指針自增操作不確定能跳過多少長度。
int matrix[2][3] = {{1,2,3},{4,5,6}};int *p = &matrix[0][0];printf("%d\n",*p);printf("%d\n",*++p);printf("%d\n",*++p);如上代碼,指針p 指向數組中第一個元素,然后指針自增1 ,指向了第二個數字,所以上面輸出就是:1,2,3 ,我們一直要確定好一件事情就是指針類型,因為類型決定了指針自增1是能跳動多大的距離。 int matrix[2][3] = {{1,2,3},{4,5,6}};int (*mp)[3];mp = matrix;printf("%d\n",(*mp)[0]);printf("%d\n",(*mp)[1]);printf("%d\n",(*++mp)[0]);
如上代碼:定義mp 為指向擁有3個整型元素的數組的指針,當對mp 與整數相加時,該整數值根據3這個長度調整,所以mp++ 導致指針mp 指向數組下一行數組元素。
所以上述代碼輸出:1,2,4 這里就可以告訴我們如何去對二維數組元素通過指針進行操作。
指針數組:
正如你可以創建整型數組一樣,你也可以聲明指針數組,如下面:
int *api[10] ,api 有十個元素,每個元素是指向int 型的指針。
再看個復雜點結構:
char const *keyword[] = {"do","for","if","register","return","switch","while"};keyword 是一個指針數組,數組中每個元素都指向一個char型數組。當我們需要查找某個關鍵字時可以遍歷該指針數組,如下: int lookup_keyword(char const * const desired_word,char const *keyword_table[],int const size) {char const **kwp;/*char (*p)[10];// 這里搞清楚類型啊,keyword_table 是char ***/// 查找kewword_table中每個單詞for(kwp = keyword_table;kwp < keyword_table + size;kwp++){printf("%s\n",*kwp);*kwp = "hello";//數組中內容可以改變,所以*kwp 可以指向別的內容if(strcmp(desired_word,*kwp) == 0){return kwp - keyword_table;}}return -1; }
這里需要注意為什么kwp 定義為指針的指針? 分析一下,keyword_table 是數組起始位置是指針,而數組中元素也是指針,所以當要引用數組中元素時必須定義為指針的指針來遍歷該數組。
如果上述結構定義為二維數組這樣:
char const keywordMatrix[][9]={"do","for","if","register","return","switch","while"};實現上述查找相同功能則需要進行改動: int lookup_keywordMatrix(char const * const desired_word,char const (*keyword_table)[9],int const size) {char const (*kwp)[9];for(kwp=keyword_table;kwp<keyword_table+size;kwp++){if(strcmp((char *)kwp,desired_word) == 0){return kwp - keyword_table;}}return -1; }
首先傳參就需要改變,這里定義的 char const(*keyword_table)[9] 是指向char型數組的指針,定義kwp同樣需要這樣為:char const (*kwp)[9] ,
所以在使用strcmp 函數時需要類型強制轉換。
小結:
數組名是指向數組第一個元素的指針。這里有兩個例外,sizeof返回整個數組占用的字節而不是一個指針所占用的字節。
int a[] 對 &a 操作返回是指向整個數組的指針。
指針和數組不相等。當我們聲明一個數組時,同時就分配了內存空間,但是聲明一個指針時,只是分配了容納指針本身空間。
當數組名作為函數參數傳遞的,實際傳遞給函數是指向數組第一個元素的指針。 函數所接收的參數實際為原參數的拷貝,所以函數可以對其進行操縱不影響實際參數,但是執行期間修改數組元素會影響原先數組元素。
結構體與內存分配:
結構體最基本的兩種訪問方式,關于內存分配,C語言中使用是malloc 和 free 。
malloc函數從內存池中提取一塊合適的內存,并向調用程序返回一個指向這塊內存的指針。你需要自己手動對這塊內存進行初始化,malloc函數分配是一塊連續的內存,
使用malloc函數時一定要注意malloc分配內存空間是否成功,如果不成功malloc函數會返回NULL,所以好的編程習慣一定是檢查分配內存空間。
此外malloc函數返回是void * 指針,因為這個返回類型問題,我們使用malloc經常會需要強制類型轉換。
動態內存常見錯誤:
NULL指針解引用操作、分配內存操作越界、釋放并非動態分配內存、釋放一塊動態分配內存的一部分、動態內存釋放后繼續使用等。
通過實際對單向鏈表操作來熟悉結構體和內存分配。
#include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std;typedef struct LinkList{int value;LinkList * next; }*ListPoint;void insert_Node(LinkList **head,int value) {ListPoint pre,current;pre = NULL;current = *head;while(current && current->value < value){pre = current;current = current->next;}LinkList * new_node = (LinkList *)malloc(sizeof(LinkList));//好的編程習慣需要每次分配內存檢查if(new_node == NULL){printf("malloc memory error !!!");return;}new_node->value = value;new_node->next = current;// 意味著插入鏈表起始位置if(pre == NULL){printf("test here\n");*head = new_node;}else{pre->next = new_node;} }void Print_LinkList(LinkList *head) {if(head == NULL){printf("empty LinkList\n");return;}while(head !=NULL){printf("%d",head->value);head = head->next;} }int main() {int arr[6] = {3,2,1,6,4,5};ListPoint head = NULL;for(int i=0;i<6;i++){insert_Node(&head,arr[i]);}Print_LinkList(head);for(int i=0;i<6;i++){printf("haha\n");}return 0; }轉載于:https://www.cnblogs.com/huruzun/p/5423881.html
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的C语言重要知识点回顾的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 获取Web.config配置节
- 下一篇: ava method org.apach