C語言部分知識

1標準輸入輸出頭文件的意義?以及main函數的作用?

<>系統頭文件、””自定義頭文件。引入系統的標準頭文件,可以用其中的一些函數,如printf();

main函數是C語言程序的入口(開始執行的位置),{}表示main函數的起止點

2怎樣理解註釋增強代碼的可讀性和可維護性?

   //、/**/對代碼的解釋說明

3C語言中有哪些基本的數據類型,佔的字節數,以及格式化的描述形式?

char 、signed char 、unsigned char 、bool     1    %c

short 、unsigned short    2   %hd

int 、float 、unsigned int    4      %d 、%f

double、 long int 、unsigned long   8    %lf 、%ld

sizeof(數據類型名)  求某種類型的字節數

4變量的本質,變量的命名規則,以及變量初始化的方式?

本質:內存裏的存儲單元。開闢空間、往空間裏面寫內容、從空間裏面讀取內容

命名規則:每個變量必須以字母和下劃線開頭,由字母下劃線數字組成

         大小寫是兩個不同的字符

         不能用C的關鍵字做變量名

初始化:聲明同時進行初始化、先聲明然後在運行時使用賦值表達式初始化、先聲明然後用戶輸入數值進行初始化

5什麼是常量,它的意義?

在變量前面加上const關鍵字,成爲常量。

常量的值必須在創建的同時初始化,且一經初始化就不能改變

6怎樣聲明一個枚舉類型,如何使用,枚舉如何代替宏定義?

enum weekday {Mon, Tue, Wed,Thr, Fri, Sat, Sun } a, b, c;

enum 關鍵字,weekday枚舉名,a,b,c 枚舉變量名

{ , ,}表示這種類型可能取的值,每個值對應一個整數,從0開始,依次加1;

1、enum weekday

{

};  //沒有定義變量

enum weekday a, b, c;  //可以用這種方法定義

2、enum weekday

{

}a,b,c;  //可以增加e, f, g等變量

3、enum

{

}a, b, c;  //沒有枚舉類型名,只能有abc三個變量

{ ,}表示這種類型可能取的值,每個值對應一個整數,從0開始,依次加1;

    可以代替整型的宏定義,增強代碼可維護性;

    枚舉是封裝好的define集合,用便於記憶的字符來代表常量,枚舉類型實質是整型變量,通過枚舉類型將一類有關聯的標識組合起來,增加程序的可讀性和可維護性

枚舉變量可以用在switch語句中作爲常量使用;使用枚舉變量時,應該把枚舉變量的值賦值爲枚舉中常量集合中某個常量的值

7定義初始化一個數組,用下標訪問數組

   int a[5];

   int a[ ]={1, 2, 3, 4};

   int a[5]={1, 2, 3, 4};

8大數分解

萬  12345/10000

千  12345/1000%10  == 12345%10000/1000

百  12345/100%10  == 12345%1000/100

十  12345/10%10  == 12345%100/10

個  12345%10

9 怎麼樣理解前置(後置)自增自減?

當需要使用自增自減的值時,考慮其是前置還是後置

前置:++i 先進行自增自減,再使用增減後的值

後置:i-- 先使用變量當前的值,然後再進行自增自減運算

10怎樣使用&& ||

與、全真爲真,有假則假

或、全假爲假,有真則真

非、非真爲假,非假爲真

11條件表達式

if()

  …

else if ()

  …

else

  …

12隱式和顯示類型轉化?

當某一個操作符擁有不同類型的操作數時,將發生類型轉換

顯式:(數據類型名) 變量名  float i = 1.23;  int j = (int) i;

     i的類型依然是float,只是把i的整數部分賦給了j

隱式:char c = ‘a’;  int i = c;

     賦值表達式,把等號右邊的類型,轉型爲等號左邊的類型;

     在一個表達式中,默認狀態下變量是從低類型向高類型轉化的

13控制流

順序結構:按照語句編寫的順序順序執行

        ;是語句結束的標誌;{}被用在程序塊中,其右側括號後面不加分號;任何可以放置單個語句的地方,都可以用一個複合語句來代替

選擇結構:if:條件爲真時,執行語句,否則跳過不執行

        if-else:條件爲真時執行if分支語句,否則執行else分支語句(嵌套)

        switch:根據條件表達式的值,執行多個動作當中的某一個動作

switch (…)   //表達式或者變量,必須返回整數型(包括字符型)

{

    case 1: …;break;  case:… 必須是常量表達式,且不允許重複

    case 2: …;break;

    default: …; break;

}

循環結構:while:首先初始化循環控制變量while(…//條件爲真)  {…//進入循環體;改變循環控制變量} 

        do/while:後置測試循環,先循環一次,再測試條件  do{…循環體;修改循環控制變量}while (表達式)//控制變量不需要初始化

        for:前置測試循環,先測試條件是否滿足,若滿足再進入循環體執行 for(循環控制變量初始化;條件表達式,爲真則執行循環體語句;修改循環控制變量)   {…循環體語句}  à首先初始化循環控制變量,然後執行條件表達式,爲真則執行循環體語句,然後改變循環控制變量,再執行條件表達式,爲真則執行循環體語句。。。直到條件表達式爲假

14breakcontinue return作用?

break:結束循環,執行循環後面的語句;多層循環只跳出break所在這一層循環;跳出switch結構

continue:跳過本次循環而執行下次循環

return:退出該函數的執行(跳出函數)

15函數作用

可以多人合作開發

單元測試,有利於早發現bug

複用性

16怎樣封裝函數,函數調用的實質;

封裝函數:main.c中需包含自定義的調用函數的頭文件;調用函數頭文件聲明調用函數原型;調用函數.c文件定義、實現調用函數

實質:

17函數的值傳遞

傳值方式,在函數調用時,把實參值的一份拷貝賦值給形參

在被調用函數體內,操作和修改的是形參的值,實參的值不受影響

單向傳遞,從實參到形參

18指針實質,指針訪問變量,指針的類型,野指針,空指針,手動開闢內存空間

指針也是一個變量,它的值是另外一個變量的地址,即指針是存放內存地址的變量

指針類型與它指向的變量的類型保持一致

 char *p = &achar;  //p指針變量名;*表示p是一個指針變量;&取地址運算符,返回變量地址;char*指針變量的類型,p是一個字符型指針,char代表指針指向的變量的類型;%p打印地址,打印指針變量的值;指針是long int,8個字節

解引用運算符,*p:放等號右邊,讀取p指向的變量的值;左邊,給p指向的變量寫入內容

如果定義一個指針沒有初始化,它存儲的是垃圾地址,即爲野指針

當定義一個指針還不確定指向哪個變量,就把它置爲空,空指針是被初始化爲NULL的指針,裏面的地址是0(不要解引用空指針,因0號地址屬於系統級內存空間,不允許用戶級程序訪問)

int * p = (int *) malloc(sizeof(int));

free(p);

19傳地址,傳指針,返回指向局部變量的指針(解決方案),函數返回值

int exchange(int *a, int *b)

{

    int temp = *a;

    *a = *b;

    *b = temp;

}

int main()

{

    int aa=1,bb=2;

    指針int p = &aa, *q = &bb;

    指針exchange(p, q);

    地址exchange(&aa, &bb);

    printf(“..”);

}

111、定義全局變量*p,開闢堆空間,主函數回收開闢的堆上的內存空間

#include <stdio.h>

#include <stdlib.h>

int *p=NULL;

int *Test()

{

    p=(int *)malloc(sizeof(int));

    *p=10;

    return p;

}

int main()

{

    int c=*Test();

    printf("%d\n",c);

    free(p);

    return 0;

}

222static

#include <stdio.h>

int *Test()

{

    static int temp=12;  //加static定義到靜態存儲區,不加則聲明局部變量,調用函數結束時內存回收

    return &temp;  //不能返回一個指向局部變量的指針

}

int main()

{

    int c=*Test();

    printf("%d\n",c);

    return 0;

}

 

20內存分配問題

逐步分析

全局變量:在所有函數體之外聲明的變量,作用於所有源文件,全局區

靜態全局變量:不可用於其他文件

靜態局部變量

局部變量:棧(形參放在棧上)

堆:手動開闢的內存空間

靜態存儲區:變量前加static,生命週期很長,從申請到程序退出

 

21怎樣用指針訪問數組?

數組元素在內存空間中連續分佈,每個元素有相應的內存地址;數組名就是數組首地址,就是指向數組首元素的指針,即a == &a[0];數組名是個指針常量,存儲的地址是不能更改的

p = a;   或 p = &a[0];   則a[1]==*(p+1);

22指針運算和數組?

#include <stdio.h>

int main()

{

   char a[8];

   int b[8];

   float c[8];

   char *pa = a + 1;

   int *pb = b + 4;

   float *pc = c +6;

   printf("%p,%p\n",a,pa);

   printf("%p,%p\n",b,pb);

   printf("%p,%p\n",c,pc);

   printf("%ld,%ld,%ld\n",pa-a,pb-b,pc-c);    //1,4,6

   printf("%ld,%ld,%ld\n",sizeof(pa-a),sizeof(pb-b),sizeof(pc-c));    //8,8,8

   return 0;

}

 

23指針常量的使用

#include <stdio.h>

int main ()

{

   const int a=9;//常量,定義時要初始化

   //a=9;  常量初始化後不能修改,即使賦相同的值也不行

   const int aa = 99;

   int b = 10;

   int c = 11;

   //int pp=&b;

   int * const p = &b;

   //p=pp;  指針常量初始化後不能修改,即使賦相同的值也不行

   //p=&c;  不同的值更不行

   printf("%d\n",*p);

   const int *q = &a;  //指向常量的指針,這個指針最好要指向一個常量

    q= &b;  //也可以指向變量

   printf("%d\n",*q);

   q=&aa;  //指向常量的指針,也可以指向其他常量

   printf("%d\n",*q);

   return 0;

}

 

    int* const p = &a;    //必須在聲明時初始化,且指針常量的值不能再修改,即不能存一個新的地址,不能指向別的變量,但是可以通過指針常量修改它所指向的變量的值

24指向常量指針的使用?

   const int a = 1;

const int *q = &a;    //指向常量的指針,這個指針指向一個常量

q = &b;    //也可以指向變量或者其他常量

25全局變量,函數域,塊域

標識符:變量名、函數名

作用域:能夠訪問某標識符的程序段

全局變量:在所有函數體之外聲明的變量,作用於所有源文件,全局區

局部變量

函數域:標識符只能在它所在的函數被訪問到

函數形參:函數實現時形參的名字可以和函數原型形參名字不同;但類型要一致。函數原型的形參的作用域,只限於函數原型本身

塊域:被大括號{}包圍的範圍叫塊;其作用域:從標識符開始到塊結束,可以被識別

當在塊內部聲明瞭一個與外部標識符同名的標識符時,外部標識符可以被臨時隱藏

就近原則:若有同名標識符,優先使用同一作用域內的標識符

如果想訪問被臨時隱藏的全局變量,要使用全局域操作符::

26鏈接編譯理解

預處理   編譯  鏈接

預處理階段,編譯器以C文件作爲一個單元,首先讀這個C文件,發現包含頭文件,就會在所有搜索路徑中尋找文件,找到之後,就會將相應頭文件中再去處理宏,變量,函數聲明,嵌套的頭文件包含等,檢測依賴關係,進行宏替換,看是否有重複定義與聲明的情況發生,最後將那些文件中全部掃描進這個當前的C文件中,形成一箇中間"C文件"

編譯階段,將中間C文件的所有變量,函數分配空間,將各個函數編譯成二進制碼,按照特定目標文件格式生成目標文件,在這種格式的目標文件中進行各個全局變量,函數的符號描述,將這些二進制碼按照一定的標準組織成一個目標文件

連接階段,將上一步生成的各個目標文件,根據一些參數,連接生成最終的可執行文件,主要的工作就是重定位各個目標文件的函數,變量等,相當於將個目標文件中的二進制碼按一定的規範合到一個文件中

想在多個文件中訪問一個變量,就要在變量前面加上extern關鍵字

27怎樣使用函數指針

函數指針的類型就是指針指向的函數的參數類型和返回值類型

int ( *fp) (int a, intb);    //聲明一個函數指針

int func (int m, intn);    //聲明一個函數

fp = func;  或  fp = &func;

28字符串和字符數組的區別

字符串:用雙引號包圍  “abcde”

字符數組:數組的每一個元素都是字符,字符用單引號包圍

在內存裏用字符數組存儲字符串,字符數組要加一個元素,以空字符\0作爲結尾

定義:字符串就是存入字符的數組,以’\0’作爲結束標誌,%s輸出

區別:字符串用字符數組存儲,但是字符數組不需要有結束標誌’\0’,字符串需要

29怎樣拷貝一個存在靜態常量區的字符串

char c[6] = “hello”;   //聲明之後,首先在靜態存儲區的常量區開闢一塊空間,寫入hello,然後開闢一塊連續的棧空間,把字符串拷貝一份,然後將內容寫入到棧空間,c本身是個變量,所以可以通過c修改他所指向的內存的值

可以把一個字符串賦值給一個char * 類型的指針,但不能通過指針修改這個字符串

char *str = "I am astudent";

//const char *str = "Iam a student";

//把一個字符串賦給一個字符指針,相當於賦給一個指向字符常量的指針

str = "sun";  //可以,改變地址,指向sun

//strcpy(str,"abcde");//錯誤,改變值

30使用strcpy strcmp strcatstrlen等字符串函數的操作

strlen (length) 返回字符串的字符數(長度),不包括\0

strcat (to, from) ,把from”…”連接到to”…”的結尾

strcpy (to, from) ,把from”…”copy到to”…”

strcmp (s1, s2) s1 > s2,返回正數s1 < s2,返回負數s1 = s2,返回0

兩個字符串從前到後,逐個比較每對字符的ASCII碼的大小;若相同,則繼續比較,直到遇到第一對不同的字符,ASCII碼整數大的字符爲大

31 起別名的語法規範

typedef  type IDENTIFIER   關鍵字   已有類型   類型別名,一般全大寫字母

typedef  unsigned int UN;

用來代替自定義的枚舉類型、結構體類型、系統定義的長度較長的類型

32 聲明結構體類型的變量的兩種主要形式,以及初始化

//111

struct  //直接定義結構體變量,結構體本身沒有名字

{

    char name[15];

    int num;

    int age;

}Astu;  //結構體變量的聲明,必須緊跟在結構體定義的後面

//222

struct student  //結構體類型,類型名爲struct student

{

    char name[15];

    int num;

    int age;

}Bstu;  //可以在這裏聲明結構體變量

struct student Cstu;  //也可以用結構體類型名,聲明一個結構體變量

//333

typedef struct  //給結構體類型起一個別名   STU

{

    char name[15];

    int num;

    int age;

}STU;  //結構體別名

STU Dstu;  //通過別名,聲明結構體變量

>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<< 

STU Dstu = {…, …, …};

33 結構體類型的指針訪問結構體類型的變量

    訪問:p = &Astu;     Astu.name     p -> num    (*p).age

34 如何計算結構體類型的變量在系統內存裏佔用的字節數

結構體的值從上往下依次分配,先找到最大字節的變量,然後依次從上到下分配內存,當分配到相應類型時,圖中編號一定要能整除當前類型字節數。(大小要能被每一種類型大小整除)

char a[10];     //0—9

int b;     //12—15

char c;     //16

double a;     //24—31

double 最大,8字節,以8字節爲單位畫內存分配:

0 1 2 3 4 5 6 7

8 9 10 11 12 13 14 15

16 17 18 19 20 21 22 23

24 25 26 27 28 29 30 31

<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>><<<<<<<>>>>>>>>> 

int a;     //0—3

fioat b;     //4—7

char c[15];     //8—22

0      1  2  3

4  5 6  7

8  9  1011

12 13 14 15

16 17 18 19

20 21 22 23

24 25 26 27

35宏替換

#define N 10  //預處理階段,源代碼裏所有的N將被替換成10

#define max(a,b) ((a) >(b) ? (a) : (b))  //宏替換的參數都要加上括號

#define  exchange ( x,  y)\

{\

int temp = *x;\

*x = *y;\

*y = temp;\

}    //替換自定義函數,除最後大括號的結束行,其餘的都要加上”\”

36條件包含

#if  。。。  //如果爲真,則包含後面內容,直到#endif、#elif、#else結束

#ifndef XXX

#define XXX

……

#endif   //避免重複定義同一個頭文件

 

 

#ifdef XXX    //如果宏定義了XXX,執行下面語句

……

#else     //否則,執行else下面語句

……

#endif

#ifndef XXX    //如果沒有宏定義XXX,執行下面語句

……

#else     //否則,執行else下面語句

……

#endif

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