C的精髓指針,本文基于C程序設計(譚浩強版)所寫。
指針
直接訪問
間接訪問
指針:一個變量的地址稱為該變量的“指針”。
指針變量:存放另一變量地址的變量。
指針變量的值是地址(指針)。
指針變量
類型名 *指針變量名;
類型名 是定義指針變量時必須指定的“基類型”。指針變量時基本數據類型派生出來的類型,它不能離開基本類型而獨立存在。
一個變量的指針包含兩個方面,一是以存儲單元編號表示的地址(如編號為2000的字節(jié)),一是它指向的存儲單元的數據類型(如int,char,float)。
int *a;//a是指向整型數據的指針變量
float *b;//b是指向單精度型數據的指針變量
char *c;//c是指向字符型數據的指針變量
指針類型:int */char */float *
指針變量中只能存放地址(指針),不要將證一個整數賦給一個指針變量。
比如* pointer = 100
是錯誤的。
引用指針變量
- 給指針變量賦值。
p=&a
- 引用指針變量指向的變量。
* p
- 引用指針變量的值。
p
&/*
- & 取地址運算符。
- * 指針運算符。
示例:
#include <iostream>
#include <stdlib.h>
using namespace std;
<!-- 錯誤,交換的是形參a,b的值,即二者地址進行了交換 -->
//void swap(int *a,int *b)
//{
// int *temp;
// temp = a;
// a = b;
// b = temp;
//}
<!-- 正確,交換的是形參a,b所指向地址的值,進而改變主函數中的a,b -->
void swap(int *a,int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int a,b;
a = 5;
b = 3;
swap(&a,&b);
cout<<a<<" "<<b;
system("pause");
return 0;
}
通過指針引用數組
數組元素的指針就是數組元素的地址。
int a[10];
int *p;
p = &a[0];//p的值是a[0]的地址
p = a;//p的值是a首元素(即a[0])的地址。
//**數組名不代表整個數組,只代表數組首元素的地址。**
當指針指向數組元素時,p+1指向同一數組中的下一個元素p-1指向同一數組中的上一個元素。
當兩個指針p1,p2指向統一數組時,p2-p1的值是地址差除以元素的長度。即二者相差的元素的個數。兩地址相加是沒有意義的。
通過指針引用數組元素
- 下標法,a[i]
- 指針法,(a+i);(p+i)
示例(混搭大法好啊_):
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int a[10],i;
int *p = a;
cout<<"請輸入是個整數:"<<endl;
for (i=0;i<10;i++)
{
scanf("%d",p++);//不能用cin>>(p++);語法錯誤
}
p = a;
for (i=0;i<10;i++)
{
printf("%d",*(p++));//cout<<*(p++)<<endl;二者均可
}
system("pause");
return 0;
}
通過指針引用多維數組
以二維數組為例
int a[3][4];
表示形式 | 含義 | 地址 |
---|---|---|
a | 二維數組名,指向一位數組a[0],即0行首地址 | 2000 |
a[0],[a+0],a | 0行0列元素地址 | 2000 |
a+1,&a[1] | 1行首地址 | 2016 |
a[1],*(a+1) | 1行0列元素a[1][0]的地址 | 2016 |
a[1]+2,*(a+1)+2,&a[1][2] | 1行2列元素a[1][2]的地址 | 2024 |
(a[1]+2),(*(a+1)+2),a[1][2] | 1行2列元素a[1][2]的值 | 元素值13 |
通過指針引用字符串
char string[] = "hello";
printf("%s\n",string);
printf("%c\n",string[4]);
printf("%c\n",*(string+4));
字符數組與字符指針變量區(qū)別
- 字符數組由若干個元素組成,每個元素中放一個字符,而字符指針變量中存放的是地址(字符串第一個字符的地址)。
- 可以對字符指針變量賦值,但不能對數組名賦值。正確:
char *a;a="zdy"
;錯誤:char str[10];str = "zdy"
- 初始化方式。
char *a = "zdy";char str[10] = "zdy"
- 存儲單元內容。編譯時為字符數組分配若干存儲單元;對字符指針變量,只分配一個存儲單元(VC 4個字節(jié))。
char *a;scanf("%s",a);//錯誤,將a指向鍵盤輸入的字符串。
char *a,str[10];a = str;scanf("%s",a);//正確。 - 指針變量的值可以改變,但是數組名代表一個固定的值,不能改變。
指針數組
類型名 *數組名[數組長度];
int *p[4];
動態(tài)內存分配
malloc
void *malloc(unsigned int size);
函數返回分配區(qū)域的第一個字節(jié)的地址。指針的基類型為void,即不指向任何類型的數據,只提供一個地址。執(zhí)行失敗返回NULL。
示例:
malloc(100);
calloc(動態(tài)數組)
void *calloc(unsigned n,unsigned size);
在內存動態(tài)從存儲區(qū)中分配n個長度為size的連續(xù)空間??梢詾橐晃粩到M開辟動態(tài)存儲空間。即動態(tài)數組。函數返回所分配域的起始地址的指針,失敗返回NULL。
示例:
p = calloc(50,4);開辟50*4字節(jié),起始地址賦給指針變量p。50個長度為4的數組。
free
void free(void *p);
釋放p所指向的動態(tài)空間。p是最近一次調用calloc或malloc函數時得到的函數返回值。free函數無返回值。
示例:
free(p);
realloc
void *realloc(void *p,unsigned int size);
將p所指向的已分配的動態(tài)空間大小改為size。
示例:
realloc(p,50);//將p所指向的已分配的動態(tài)空間改為50字節(jié)。
示例:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
void check(int *);
int *p;
p = (int *)malloc(5*sizeof(int));// p = malloc(5*sizeof(int));亦可
printf("請輸入五個學生的成績:");
for (int i = 0;i<5;i++)
{
scanf("%d",p+i);
}
check(p);
system("pause");
return 0;
}
void check(int *p)
{
printf("低于60分的有:");
for (int i = 0;i<5;i++)
{
if (p[i]<60)
{
printf("%d ",p[i]);
}
}
}