C語言之複雜指標簡析
指標陣列和陣列指標
- 指標陣列:首先它是一個數組,陣列的元素都是指標,陣列佔多少個位元組由陣列本身決定。它是“儲存指標的陣列”的簡稱。
- 陣列指標:首先它是一個指標,它指向一個數組。在 32 位系統下永遠是佔 4 個位元組,至於它指向的陣列佔多少位元組,不知道。它是“指向陣列的指標”的簡稱。
那麼下邊倆個分別叫做什麼呢?
int *p1[4];
int (*p2)[4];
第一個我們稱之為指標陣列。“[ ]”的優先順序比“”要高。p1 先與“[ ]”結合,構成一個數組的定義,陣列名為 p1,int 修飾的是陣列的內容,即陣列的每個元素。這是一個數組,其包含 4 個指向 int 型別資料的指標,即指標陣列。
我們可以這樣理解:
第二個我們稱之為陣列指標。在這裡“()”的優先順序比“ []”高,“*”號和 p2 構成一個指標的定義,指標變數名為 p2,int 修飾的是陣列的內容,即陣列的每個元素。陣列在這裡並沒有名字,是個匿名陣列。那現在我們清楚 p2 是一個指
針,它指向一個包含 4 個 int 型別資料的陣列,即陣列指標。
同樣,也可以這樣理解:
函式指標,函式指標陣列和指向函式指標陣列的指標
- 函式指標:就是函式的指標。它是一個指標,指向一個函式。
- 函式指標陣列:它是一個數組,陣列記憶體儲了指向函式的指標。
函式指標陣列指標:它是一個指標,只不過這個指標指向一個數組,這個數組裡面存的都是指向函式的指標。
看如下例子:
char * (pf)(char p1,char * p2);
這個我們稱之為函式指標。” * “號和 pf 構成一個指標的定義,指標變數名為 pf。pf指向一個函式,該函式的返回值型別是char * ,函式引數有兩個,分別為p1和p2,p1和p2都是char * 型別.char * (pf[3])(char p);
這個我們稱之為 函式指標陣列。“[ ]”的優先順序比“*”要高。pf 先與“[ ]”結合,構成一個數組的定義,陣列名為 pf。陣列記憶體儲了 3 個指向函式的指標。這些指標指向一些函式,其中函式返回值型別為指向字元的指標,引數為一個指向字元的指標。char * ((*pf)[3])(char p);
這個稱為 指向函式指標陣列的指標。該 pf 確實是實實在在的指標。這個指標指向一個包含了 3 個元素的陣列;這個數組裡面存的是指向函式的指標;這些指標指向一些返回值型別為 指向字元的指標、引數為一個 指向字元的指標 的函式。
下面通過轉移表瞭解一下函式指標陣列的用法:
void menu()
{
printf("**************************\n");
printf("*******1.add 2.sub*****\n");
printf("********3.mul 4.div*****\n");
printf("****************0.exit*****\n");
printf("請選擇:");
}
int Add(int a, int b)
{
return a + b;
}
int Sub(int a, int b)
{
return a - b;
}
int Mul(int a, int b)
{
return a*b;
}
int Div(int a, int b)
{
return a / b;
}
int main()
{
int x = 0;
int y = 0;
int input = 1;
int ret = 0;
int (*p[5])(int , int ) = { 0, Add, Sub, Mul, Div };//轉移表
do
{
menu();
scanf("%d", &input);
if (input >=1 && input <=4)
{
printf("輸入運算元:");
scanf("%d%d", &x, &y);
ret = p[input](x, y);
}
else
{
printf("輸入錯誤,請重新輸入:");
}
printf("ret=%d\n", ret);
} while (input);
system("pause");
return 0;
}
小試:
(* (void(*) ())0)();
void (* signal(int,void(*)(int)))(int);
第一個為函式呼叫。怎麼理解呢?
首先 void (* )()是一個函式指標,該指標指向一個無引數,返回值型別為void型(即沒有返回值)的函式。
(void (* )())0:就是將0強制轉換成函式指標型別。
(* (void (*)())0):就是取0地址處開始的一段記憶體裡面的內容,其內容就是儲存在首地址為 0 的一段區域內的函式。
(* (void(*) ())0)():就是對函式進行呼叫。
第二個可以理解為:
signal是一個函式,其返回值型別為void (*) (int)型,即函式指標型別;引數有兩個,分別為整形和函式指標型別。可簡寫為:
typedef void (*pfun_t) (int);
pfun_t signal(int , pfun_t);
回撥函式:
就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,就說這是回撥函式。
使用回撥函式,模擬實現qsort。
int int_cmp(const void* p1, const void* p2)
{
if (*(int *)p1 > *(int *)p2)
{
return 1;
}
else if (*(int *)p1 < *(int *)p2)
{
return -1;
}
else
{
return 0;
}
}
void _swap(void *p1, void *p2, int size)
{
int i = 0;
for (i = 0; i < size; i++)
{
char tmp = *((char *)p1 + i);
*((char *)p1 + i) = *((char *)p2 + i);
*((char *)p2 + i)=tmp;
}
}
void mybubble(void *base, int count, int size, int(*cmp)(void *, void*))
{
int i = 0;
int j = 0;
for (i = 0; i < count - 1; i++)
{
for (j = 0; j < count - i - 1; j++)
{
if (cmp((char *)base + j*size, (char *)base + (j + 1)*size)>0)
{
_swap((char *)base + j*size, (char *)base + (j + 1)*size, size);
}
}
}
}
int main()
{
int a[] = { 1, 2, 2, 56, 32, 6, 8, 0 };
char *arr[] = { "aabb", "dddd", "bbbb", "eeee" };
int i = 0;
mybubble(a, sizeof(a) / sizeof(a[0]), sizeof(int), int_cmp);
for (; i < sizeof(a) / sizeof(a[0]); i++)
{
printf("%d ", a[i]);
}
printf("\n");
system("pause");
return 0;
}
指標概述: