C語言筆記 07_枚舉&指針

emum(枚舉)

枚舉是 C 語言中的一種基本數據類型,它可讓數據更簡潔,更易讀。html

枚舉語法定義格式爲:程序員

enum 枚舉名 {枚舉元素1,枚舉元素2,……};

舉個例子,好比:一星期有 7 天,若是不用枚舉,咱們須要使用 #define 來爲每一個整數定義一個別名:spring

#define MON  1
#define TUE  2
#define WED  3
#define THU  4
#define FRI  5
#define SAT  6
#define SUN  7

這個看起來代碼量就比較多,接下來咱們看看使用枚舉的方式:編程

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};

這樣看起來是否是更簡潔了。數組

注意:第一個枚舉成員的默認值爲整型的 0,後續枚舉成員的值在前一個成員上加 1。咱們在這個實例中把第一個枚舉成員的值定義爲 1,第二個就爲 2,以此類推。dom

能夠在定義枚舉類型時改變枚舉元素的值:函數

enum season {spring, summer=3, autumn, winter};

沒有指定值的枚舉元素,其值爲前一元素加 1。也就說 spring 的值爲 0,summer 的值爲 3,autumn 的值爲 4,winter 的值爲 5操作系統

枚舉變量的定義

前面咱們只是聲明瞭枚舉類型,接下來咱們看看如何定義枚舉變量。指針

咱們能夠經過如下三種方式來定義枚舉變量code

一、先定義枚舉類型,再定義枚舉變量

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;

二、定義枚舉類型的同時定義枚舉變量

enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

三、省略枚舉名稱,直接定義枚舉變量

enum
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;

實例

#include<stdio.h>
 
enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};
 
int main()
{
    enum DAY day;
    day = WED;
    printf("%d",day); // 3
    return 0;
}

在C 語言中,枚舉類型是被當作 int 或者 unsigned int 類型來處理的,因此按照 C 語言規範是沒有辦法遍歷枚舉類型的。

不過在一些特殊的狀況下,枚舉類型必須連續是能夠實現有條件的遍歷。

如下實例使用 for 來遍歷枚舉的元素:

#include<stdio.h>
 
enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
int main()
{
    // 遍歷枚舉元素
    for (day = MON; day <= SUN; day++) {
        printf("枚舉元素:%d \n", day);
    }
}

以上實例輸出結果爲:

枚舉元素:1
枚舉元素:2
枚舉元素:3
枚舉元素:4
枚舉元素:5
枚舉元素:6
枚舉元素:7

如下枚舉類型不連續,這種枚舉沒法遍歷。

enum
{
    ENUM_0,
    ENUM_10 = 10,
    ENUM_11
};

枚舉在 switch 中的使用:

#include <stdio.h>
#include <stdlib.h>
int main()
{
 
    enum color { red=1, green, blue };
 
    enum  color favorite_color;
 
    /* ask user to choose color */
    printf("請輸入你喜歡的顏色: (1. red, 2. green, 3. blue): ");
    scanf("%d", &favorite_color);
 
    /* 輸出結果 */
    switch (favorite_color)
    {
    case red:
        printf("你喜歡的顏色是紅色");
        break;
    case green:
        printf("你喜歡的顏色是綠色");
        break;
    case blue:
        printf("你喜歡的顏色是藍色");
        break;
    default:
        printf("你沒有選擇你喜歡的顏色");
    }
 
    return 0;
}

以上實例輸出結果爲:

請輸入你喜歡的顏色: (1. red, 2. green, 3. blue): 1
你喜歡的顏色是紅色

將整數轉換爲枚舉

如下實例將整數轉換爲枚舉:

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
 
    enum day
    {
        saturday,
        sunday,
        monday,
        tuesday,
        wednesday,
        thursday,
        friday
    } workday;
 
    int a = 1;
    enum day weekend;
    weekend = ( enum day ) a;  //類型轉換
    //weekend = a; //錯誤
    printf("weekend:%d",weekend);
    return 0;
}

以上實例輸出結果爲:

weekend:1

指針

經過指針,能夠簡化一些 C 編程任務的執行,還有一些任務,如動態內存分配,沒有指針是沒法執行的。

每個變量都有一個內存位置,每個內存位置都定義了可以使用連字號(&)運算符訪問的地址,它表示了在內存中的一個地址。請看下面的實例,它將輸出定義的變量地址:

#include <stdio.h>
 
int main ()
{
   int  var1;
   char var2[10];
 
   printf("var1 變量的地址: %p\n", &var1  );
   printf("var2 變量的地址: %p\n", &var2  );
 
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

var1 變量的地址: 0x7fff5cc109d4
var2 變量的地址: 0x7fff5cc109de

經過上面的實例,咱們瞭解了什麼是內存地址以及如何訪問它。接下來讓咱們看看什麼是指針。

什麼是指針?

指針是一個變量,其值爲另外一個變量的地址,即,內存位置的直接地址。就像其餘變量或常量同樣,您必須在使用指針存儲其餘變量地址以前,對其進行聲明。指針變量聲明的通常形式爲:

type *var-name;

在這裏,type 是指針的基類型,它必須是一個有效的 C 數據類型,var-name 是指針變量的名稱。用來聲明指針的星號 * 與乘法中使用的星號是相同的。可是,在這個語句中,星號是用來指定一個變量是指針。如下是有效的指針聲明:

int    *ip;    /* 一個整型的指針 */
double *dp;    /* 一個 double 型的指針 */
float  *fp;    /* 一個浮點型的指針 */
char   *ch;     /* 一個字符型的指針 */

全部實際數據類型,不論是整型、浮點型、字符型,仍是其餘的數據類型,對應指針的值的類型都是同樣的,都是一個表明內存地址的長的十六進制數。

不一樣數據類型的指針之間惟一的不一樣是,指針所指向的變量或常量的數據類型不一樣。

如何使用指針?

使用指針時會頻繁進行如下幾個操做:定義一個指針變量、把變量地址賦值給指針、訪問指針變量中可用地址的值。這些是經過使用一元運算符 ***** 來返回位於操做數所指定地址的變量的值。下面的實例涉及到了這些操做:

#include <stdio.h>
 
int main ()
{
   int  var = 20;   /* 實際變量的聲明 */
   int  *ip;        /* 指針變量的聲明 */
 
   ip = &var;  /* 在指針變量中存儲 var 的地址 */
 
   printf("Address of var variable: %p\n", &var  );
 
   /* 在指針變量中存儲的地址 */
   printf("Address stored in ip variable: %p\n", ip );
 
   /* 使用指針訪問值 */
   printf("Value of *ip variable: %d\n", *ip );
 
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Address of var variable: bffd8b3c
Address stored in ip variable: bffd8b3c
Value of *ip variable: 20

C 中的 NULL 指針

在變量聲明的時候,若是沒有確切的地址能夠賦值,爲指針變量賦一個 NULL 值是一個良好的編程習慣。賦爲 NULL 值的指針被稱爲指針。

NULL 指針是一個定義在標準庫中的值爲零的常量。請看下面的程序:

#include <stdio.h>
 
int main ()
{
   int  *ptr = NULL;
 
   printf("ptr 的地址是 %p\n", ptr  );
 
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

ptr 的地址是 0x0

在大多數的操做系統上,程序不容許訪問地址爲 0 的內存,由於該內存是操做系統保留的。然而,內存地址 0 有特別重要的意義,它代表該指針不指向一個可訪問的內存位置。但按照慣例,若是指針包含空值(零值),則假定它不指向任何東西。

如需檢查一個空指針,您可使用 if 語句,以下所示:

if(ptr)     /* 若是 p 非空,則完成 */
if(!ptr)    /* 若是 p 爲空,則完成 */

C 指針詳解

在 C 中,有不少指針相關的概念。下面列出了 C 程序員必須清楚的一些與指針相關的重要概念:

概念 描述
指針的算術運算 能夠對指針進行四種算術運算:++、--、+、-
指針數組 能夠定義用來存儲指針的數組。
指向指針的指針 C 容許指向指針的指針。
傳遞指針給函數 經過引用或地址傳遞參數,使傳遞的參數在調用函數中被改變。
從函數返回指針 C 容許函數返回指針到局部變量、靜態變量和動態內存分配。

指針的算術運算符

C 指針是一個用數值表示的地址。所以,您能夠對指針執行算術運算。能夠對指針進行四種算術運算:++、--、+、-。

每編譯一次代碼,所儲存的內存位置都會發生改變,因此想觀察到遞增(減)的改變只能將它寫在一份源代碼中編譯,不要分紅兩次編譯對比結果,兩個緊挨的整數值中間差爲4個二進制位

遞增一個指針

咱們喜歡在程序中使用指針代替數組,由於變量指針能夠遞增,而數組不能遞增,數組能夠當作一個指針常量。下面的程序遞增變量指針,以便順序訪問數組中的每個元素:

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;
 
   /* 指針中的數組地址 */
   ptr = var;
   for ( i = 0; i < MAX; i++)
   {
 
      printf("存儲地址:var[%d] = %p\n", i, ptr );
      printf("存儲值:var[%d] = %d\n", i, *ptr );
 
      /* 移動到下一個位置 */
      ptr++;
   }
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

存儲地址:var[0] = bf882b30
存儲值:var[0] = 10
存儲地址:of var[1] = bf882b34
存儲值: var[1] = 100
存儲地址:of var[2] = bf882b38
存儲值:var[2] = 200

遞減一個指針

一樣地,對指針進行遞減運算,即把值減去其數據類型的字節數,以下所示:

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;
 
   /* 指針中最後一個元素的地址 */
   ptr = &var[MAX-1];
   for ( i = MAX; i > 0; i--)
   {
 
      printf("存儲地址:var[%d] = %x\n", i-1, ptr );
      printf("存儲值:var[%d] = %d\n", i-1, *ptr );
 
      /* 移動到下一個位置 */
      ptr--;
   }
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

存儲地址:var[2] = 518a0ae4
存儲值:var[2] = 200
存儲地址:var[1] = 518a0ae0
存儲值:var[1] = 100
存儲地址:var[0] = 518a0adc
存儲值:var[0] = 10

指針的比較

指針能夠用關係運算符進行比較,如 ==、< 和 >。若是 p1 和 p2 指向兩個相關的變量,好比同一個數組中的不一樣元素,則可對 p1 和 p2 進行大小比較。

下面的程序修改了上面的實例,只要變量指針所指向的地址小於或等於數組的最後一個元素的地址 &var[MAX - 1],則把變量指針進行遞增:

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;
 
   /* 指針中第一個元素的地址 */
   ptr = var;
   i = 0;
   while ( ptr <= &var[MAX - 1] )
   {
 
      printf("Address of var[%d] = %p\n", i, ptr );
      printf("Value of var[%d] = %d\n", i, *ptr );
 
      /* 指向上一個位置 */
      ptr++;
      i++;
   }
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Address of var[0] = bfdbcb20
Value of var[0] = 10
Address of var[1] = bfdbcb24
Value of var[1] = 100
Address of var[2] = bfdbcb28
Value of var[2] = 200

指針數組

先看一個實例,它用到了一個由 3 個整數組成的數組:

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int i;
 
   for (i = 0; i < MAX; i++)
   {
      printf("Value of var[%d] = %d\n", i, var[i] );
   }
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200

可能有一種狀況,咱們想要讓數組存儲指向 int 或 char 或其餘數據類型的指針。下面是一個指向整數的指針數組的聲明:

int *ptr[MAX];

在這裏,把 ptr 聲明爲一個數組,由 MAX 個整數指針組成。所以,ptr 中的每一個元素,都是一個指向 int 值的指針。下面的實例用到了三個整數,它們將存儲在一個指針數組中,以下所示:

#include <stdio.h>
 
const int MAX = 3;
 
int main ()
{
   int  var[] = {10, 100, 200};
   int i, *ptr[MAX];
 
   for ( i = 0; i < MAX; i++)
   {
      ptr[i] = &var[i]; /* 賦值爲整數的地址 */
   }
   for ( i = 0; i < MAX; i++)
   {
      printf("Value of var[%d] = %d\n", i, *ptr[i] );
   }
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200

您也能夠用一個指向字符的指針數組來存儲一個字符串列表,以下:

#include <stdio.h>
 
const int MAX = 4;
 
int main ()
{
   const char *names[] = {
                   "Zara Ali",
                   "Hina Ali",
                   "Nuha Ali",
                   "Sara Ali",
   };
   int i = 0;
 
   for ( i = 0; i < MAX; i++)
   {
      printf("Value of names[%d] = %s\n", i, names[i] );
   }
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali

指向指針的指針

指向指針的指針是一種多級間接尋址的形式,或者說是一個指針鏈。一般,一個指針包含一個變量的地址。當咱們定義一個指向指針的指針時,第一個指針包含了第二個指針的地址,第二個指針指向包含實際值的位置。

一個指向指針的指針變量必須以下聲明,即在變量名前放置兩個星號。例如,下面聲明瞭一個指向 int 類型指針的指針:

int **var;

當一個目標值被一個指針間接指向到另外一個指針時,訪問這個值須要使用兩個星號運算符,以下面實例所示:

#include <stdio.h>
 
int main ()
{
   int  var;
   int  *ptr;
   int  **pptr;

   var = 3000;

   /* 獲取 var 的地址 */
   ptr = &var;

   /* 使用運算符 & 獲取 ptr 的地址 */
   pptr = &ptr;

   /* 使用 pptr 獲取值 */
   printf("Value of var = %d\n", var );
   printf("Value available at *ptr = %d\n", *ptr );
   printf("Value available at **pptr = %d\n", **pptr);

   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Value of var = 3000
Value available at *ptr = 3000
Value available at **pptr = 3000

傳遞指針給函數

C 語言容許您傳遞指針給函數,只須要簡單地聲明函數參數爲指針類型便可。

下面的實例中,咱們傳遞一個無符號的 long 型指針給函數,並在函數內改變這個值:

#include <stdio.h>
#include <time.h>
 
void getSeconds(unsigned long *par);

int main ()
{
   unsigned long sec;


   getSeconds( &sec );

   /* 輸出實際值 */
   printf("Number of seconds: %ld\n", sec );

   return 0;
}

void getSeconds(unsigned long *par)
{
   /* 獲取當前的秒數 */
   *par = time( NULL );
   return;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Number of seconds :1294450468

能接受指針做爲參數的函數,也能接受數組做爲參數,以下所示:

#include <stdio.h>
 
/* 函數聲明 */
double getAverage(int *arr, int size);
 
int main ()
{
   /* 帶有 5 個元素的整型數組  */
   int balance[5] = {1000, 2, 3, 17, 50};
   double avg;
 
   /* 傳遞一個指向數組的指針做爲參數 */
   avg = getAverage( balance, 5 ) ;
 
   /* 輸出返回值  */
   printf("Average value is: %f\n", avg );
   
   return 0;
}

double getAverage(int *arr, int size)
{
  int    i, sum = 0;      
  double avg;          
 
  for (i = 0; i < size; ++i)
  {
    sum += arr[i];
  }
 
  avg = (double)sum / size;
 
  return avg;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Average value is: 214.40000

從函數返回指針

必須聲明一個返回指針的函數,以下所示:

int * myFunction()
{
}

另外,C 語言不支持在調用函數時返回局部變量的地址,除非定義局部變量爲 static 變量。

看下面的函數,它會生成 10 個隨機數,並使用表示指針的數組名(即第一個數組元素的地址)來返回它們,具體以下:

#include <stdio.h>
#include <time.h>
#include <stdlib.h> 
 
/* 要生成和返回隨機數的函數 */
int * getRandom( )
{
   static int  r[10];
   int i;
 
   /* 設置種子 */
   srand( (unsigned)time( NULL ) );
   for ( i = 0; i < 10; ++i)
   {
      r[i] = rand();
      printf("%d\n", r[i] );
   }
 
   return r;
}
 
/* 要調用上面定義函數的主函數 */
int main ()
{
   /* 一個指向整數的指針 */
   int *p;
   int i;
 
   p = getRandom();
   for ( i = 0; i < 10; i++ )
   {
       printf("*(p + [%d]) : %d\n", i, *(p + i) );
   }
 
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

1523198053
1187214107
1108300978
430494959
1421301276
930971084
123250484
106932140
1604461820
149169022
*(p + [0]) : 1523198053
*(p + [1]) : 1187214107
*(p + [2]) : 1108300978
*(p + [3]) : 430494959
*(p + [4]) : 1421301276
*(p + [5]) : 930971084
*(p + [6]) : 123250484
*(p + [7]) : 106932140
*(p + [8]) : 1604461820
*(p + [9]) : 149169022

參考自:https://www.runoob.com/cprogramming/c-tutorial.html

相關文章
相關標籤/搜索