電商專業(yè)學(xué)習(xí)嵌入式軟件開發(fā)第六十四天

  • C基礎(chǔ)第四天

今天講的是指針和字符串?dāng)?shù)組,不知道是之前留下的印象還是確實(shí)難理解,講到這里的時(shí)候思維就自然而然的跟不上了。只能多接觸試試了。

指針
**1、地址指針的概念
**
** 變量的指針和指向變量的指針
**
** 定義一個(gè)指針變量
**
** 指針變量的引用
**
**2、指針變量做函數(shù)參數(shù)
**
3、數(shù)組指針和指向數(shù)組的指針變量
**
** 指向數(shù)組元素的指針
**
** 通過指針引用數(shù)組元素
**
** 指向多維數(shù)組的指針和指針變量
**
**
**
** 在計(jì)算機(jī)中所有的數(shù)據(jù)都是存放在存儲(chǔ)器中的,存儲(chǔ)器被劃分為一個(gè)一個(gè)的內(nèi)存單元,為了正確的找到這些信息,必須為每一個(gè)內(nèi)存單元進(jìn)行編號(hào),內(nèi)存單元的編號(hào)就是地址。地址通常也稱為指針。

** 舉個(gè)具體的例子: 我們?nèi)ャy行存取款,銀行的工作人員根據(jù)我們的賬號(hào)找到我們的存款單。找到以后進(jìn)行存取款操作,并做相關(guān)記錄。這里,賬號(hào)就是存單指針,存款數(shù)就是存單的內(nèi)容.
**
**
**
**如何定義一個(gè)指針變量?
**
**對(duì)指針變量的定義包括三個(gè)內(nèi)容:
**
**1、指針類型的說明,定義變量為一個(gè)指針變量;
**
**2、指針變量名;
**
**3、變量值(指針)所指向的數(shù)據(jù)類型;
**
**
**
**指針變量定義的一般形式為:
**
** 類型說明符 *變量名;
**
*注: 表示這個(gè)變量為指針變量,變量名即為定義的指針變量名,類型說明符表示本指針?biāo)赶虻淖兞康臄?shù)據(jù)類型。
**
**例:int *p;
**
**表示p是一個(gè)指針變量,它指向某個(gè)整型變量,他的值是某個(gè)整型變量的地址;p具體指向那一個(gè)整型變量,由向p賦值的地址來決定;
**

例:
int *p2;    /*p2是指向整型變量的的指針變量*/
float *p3; //p3是指向浮點(diǎn)型變量的指針變量
char *p4; //p4是指向字符型變量的指針變量

**注:一個(gè)指針只能指向同類型的變量,p2只能指向浮點(diǎn)型變量 。
**
**
**
**指針變量的使用:
**
**指針變量和普通變量一樣,使用之前必須要定義說明和賦值。未經(jīng)賦值的指針變量不能使用,否則會(huì)造成系統(tǒng)混亂,甚至是死機(jī)。
**
**指針變量的賦值只能是地址,決對(duì)不能賦其他任何數(shù)據(jù)。
**
**
**
**兩個(gè)相關(guān)的運(yùn)算符: &:取地址運(yùn)算符; *:指針運(yùn)算符(或間接訪址運(yùn)算符)。
**
**C語言中提供了地址運(yùn)算符&,表示變量的地址;
**
**使用的一般形式為:
**
** &變量名;
**
**例:&a 表示變量a的地址,&b表示b的地址,變量本身必須事先說明。
**
**(1)、指針變量的初始化方法
**

 int a;
 int *p=&a;

**(2)、指針變量的賦值
**

 int a;
 int *p;
 p=&a;

**不允許把一個(gè)賦值給指針變量,int *p; p=1000; 這樣的做法是錯(cuò)誤的。
**

被賦值的的指針變量前面不能再加'*'說明符,如:*p=&a;

**
**
**我們定義兩個(gè)整形變量和一個(gè)指針變量:
**

int i=200,x; int *ip; //i,x中存放的是整型變量,ip中只能存放整型變量的地址。

**
**
**此時(shí)指針變量ip指向整型變量i,假設(shè)i的地址是1800,這個(gè)賦值語句可以理解為

**
Paste_Image.png
其中*ip和i是等價(jià)的,*p可以完全代替i,
x=*ip;   //ip通過指針間接訪問變量i地址,等價(jià)于  x=i;
指針變量和一般的變量一樣,存放的值是可以改變的
int i,j,*p1,*p2;
i='a';
j='b';
p1=&i;
p2=&j;

建立如下的對(duì)應(yīng)關(guān)系

Paste_Image.png

這時(shí)賦值表達(dá)式p2=p1;//p2與p1指向同一對(duì)象i,此時(shí)p2就等價(jià)于i;*
Paste_Image.png

如果執(zhí)行p2=p1;//表示把p1指向的內(nèi)容賦值給p2;**
Paste_Image.png

#include <stdio.h>
int main()
{
    int i=3,j=7;
    int  *p1,*p2;
    p1=&i;
    p2=&j;
    p2=p1;//分別執(zhí)行p2=p1 和 *p2=*p1
    //*p2=*p1;
  printf("i=%d,j=%d,*p1=%d,*p2=%d,p1=%p,p2=%p\n",i,j,*p1,*p2,p1,p1); 
    return 0;
}

*''和'&'使用注意事項(xiàng)
**
*''是指針運(yùn)算符,間接訪問運(yùn)算符,'&'是取地址運(yùn)算符。
**
**初始化 int *p=&i; 兩個(gè)符號(hào)必須同時(shí)在
**
**賦值時(shí) p=&i; 只能有一個(gè)取地址符號(hào)在
**
***p和一個(gè)整型變量等價(jià),&i和一個(gè)指針變量等價(jià)。
**

**指針變量作為函數(shù)的參數(shù)
**
**函數(shù)的參數(shù)除了時(shí)整型、字符型、浮點(diǎn)型等,還可以是指針類型的。
**
指針類型的參數(shù)的作用是把一個(gè)變量的地址傳入函數(shù)中。

#include <stdio.h>
void swap(int *pa,*pb)
{
    int temp;
    temp=*pa;
    *pa=*pb;
    *pb=temp;
}
int main()
{
    int a,b;
    int *pa,*pb;
    printf("請(qǐng)輸入a和b的值\n");
    printf("a=");
    scanf("%d",&a);
    printf("b=");
    scanf("%d",&b);
    pa=&a;
    pb=&b;
    swap(pa,pb);
    printf("a=%d,b=%d",a,b);
    return 0;
}

**指針變量的運(yùn)算
**
**1、賦值運(yùn)算。
**
** (1)指針變量的初始化和賦值前面?zhèn)€已經(jīng)介紹過了
**
** (2)把一個(gè)變量的地址賦值給指向相同數(shù)據(jù)類型的指針變量
**

     int a ,*pa;
     pa=&a;//把整型變量a的地址復(fù)制給整型指針變量pa

** (3)把一個(gè)指針變量的值賦給另一個(gè)指針變量(二者類型相同)
**

    int a,*pa,*pb;
    pa=&a;
    pb=pa; //把a(bǔ)的地址賦給pb,pa,pb類型相同可以相互賦值;

** (4)把數(shù)組的首地址賦給指向數(shù)組的指針變量
**

        int a[5],*pa;
        pa=a;//注意:這里不需要取地址符,a表示數(shù)組的首地址
        //等價(jià)于 pa=&a[0];數(shù)組第一個(gè)元素的地址也是整個(gè)數(shù)組的首地址

** (5)把字符串的首地址賦給指向字符類型的指針變量
**

  char *p;
  p="C program";//這里不是吧整個(gè)字符串裝入指針變量,而是把存放該字符串的字符數(shù)組的首地址裝入指針變量。

** (6)把函數(shù)的入口地址賦給指向函數(shù)的指針變量
**

           int (*pf)();
           pf=f;  //f為函數(shù)名

**2、指針變量的加減法
**
** 指針的加減法主要的運(yùn)算對(duì)象是數(shù)組。
**
** 指針變量加上或減去一個(gè)整數(shù)n的意義是把指針指向的當(dāng)前位置(某數(shù)組元素)向前向后移動(dòng)n個(gè)位置。
**
**數(shù)組指針變量移動(dòng)一個(gè)位子,和地址加一減一的概念是不同的。數(shù)組是不同類型的,所以數(shù)組元素所占字節(jié)數(shù)也是不同的,指針變量加一,即向后移動(dòng)一個(gè)位置,表示指針指向下一個(gè)數(shù)組元素的首地址。而不是在原地址上加一。
**

    int a[5],*pal
    pa=a; //pa指向數(shù)組的第一個(gè)元素a[0]
    pa=pa+2;//pa向后移動(dòng)兩個(gè)位置,指向數(shù)組的第三個(gè)元素,a[2];

**指針變量的加減法只能對(duì)數(shù)組指針變量進(jìn)行,對(duì)指向其他數(shù)據(jù)類型的指針變量加減操作是毫無意義的.
**
**3、兩個(gè)指針變量間的運(yùn)算:只有指向同一數(shù)組的兩個(gè)指針變量之間才能夠進(jìn)行運(yùn)算,否則是毫無意義的。
**
** (1)兩指針變量相減:兩指針變量相減所得之差是兩個(gè)指針?biāo)冈刂g相差的元素個(gè)數(shù)。實(shí)際上就是兩個(gè)指針值(地址)相減的差值再除以該數(shù)組元素的長度。
**
** 注:兩指針之間不能進(jìn)行加操作,加操作毫無意義
**
** (2)兩指針之間的關(guān)系運(yùn)算: 指向同一數(shù)組的兩個(gè)指針變量進(jìn)行關(guān)系運(yùn)算可表示它們指向的數(shù)組元素之間的關(guān)系。
**

    pf1==pf2;//表示pf1和pf2指向同以數(shù)組元素。
    pf1>pf2;//表示pf1處于高地址位
    pf1<pf2;//表示pf1處于低地址位

** 指針變量還可以與0進(jìn)行比較,
**
** 當(dāng)p為指針變量時(shí),p==0;表示p時(shí)空指針,它不指向任何變量。
**
** P!=0; 表時(shí)指針 不為空
**
** 空指針是對(duì)指針變量賦0得到的。
**
** 對(duì)指針變量賦0和不賦值是不同的。指針變量未賦值,可以是任意值,是不能使用的,否則將造成意外錯(cuò)誤。指針變量賦0值以后,則可以使用,只是它不指向具體的變量而已。
**

例:
int main()
{
    int a=10,b=20,s,t,*pa,*pb;
    pa=&a;
    pb=&b;
    s=*pa+*pb;//求和
    t=*pa * *pb;//求積
    printf("a=%d\nb=%d\na+b=\na*b=%d\n",a,b,a+b,a*b);
    printf("s=%d\ns=%d\n",s,t);
}

**數(shù)組指針和指向數(shù)組的指針變量
**
**一個(gè)變量有一個(gè)地址,一個(gè)數(shù)組包含若干個(gè)元素,每個(gè)數(shù)組元素都在內(nèi)存中占用存儲(chǔ)單元,他們都有相應(yīng)的地址。所謂數(shù)組的指針是指數(shù)組的起始地址,數(shù)組元素的地址是數(shù)組元素的地址。
**
**
**
*指向數(shù)組元素的指針
**
一個(gè)數(shù)組是由連續(xù)的一塊內(nèi)存單元組成的。數(shù)組名就是這塊連續(xù)內(nèi)存單元的首地址。一個(gè)數(shù)組也是由各個(gè)數(shù)組元素(下標(biāo)變量)組成的。每個(gè)數(shù)組元素按其類型不同占有幾個(gè)連續(xù)的內(nèi)存單元。一個(gè)數(shù)組元素的首地址也是指它所占有的幾個(gè)內(nèi)存單元的首地址定義一個(gè)指向數(shù)組元素的指針變量的方法,與以前介紹的指針變量相同。例如:int a[10]; /不定義a為包含10個(gè)整型數(shù)據(jù)的數(shù)組/intp; /定義p為指向整型變量的指針
/應(yīng)當(dāng)注意,因?yàn)閿?shù)組為int型,所以指針變量也應(yīng)為指向int型的指針變量。下面是對(duì)指針變量賦值:p=&a[0];把a(bǔ)[10]元素的地地賦給指針變量p。也就是說,p指向a數(shù)組的第0號(hào)元素.
**

Paste_Image.png

**C語言規(guī)定數(shù)組名代表的就是數(shù)組的首地址,也就是第0號(hào)元素的地址,
**
**p=&a[0]; 等價(jià)于 p=a;
**
**在定義指針變量時(shí)可以賦給初值
**
int *p=&a[0]; 等價(jià)于 int *p; p=&a[0]; 同時(shí)等價(jià)于 int *p=a;
**從圖中的關(guān)系可以卡出 p,a,&a[0]均指向同一單元,他們是數(shù)組a的首地址,也就是0號(hào)元素a[0]的首地址。需要注意的是p是變量,a,&a[0]是常量。
**
**
**
**通過指針引用數(shù)組元素。
**
**C語言規(guī)定:如果指針變量p已經(jīng)指向數(shù)組中的一個(gè)元素,則P+1指向同數(shù)組的下一個(gè)元素。
**
**引入指針變量以后我們就可以用兩種方法來訪問數(shù)組元素。
**

如果P的初值為&a[0],則
(1)P+i和a+i就是a[i]的地址,或者說他們指向a數(shù)組的第i個(gè)元素;
(2)*(p+i)或*(a+i)就是p+i或a+i所指向的數(shù)組元素,即a[i].例如*(p+5)或*(a+5)就是a[5];
(3)指向數(shù)組的指針變量也可以帶下標(biāo),p[i]與*(p+i)等價(jià);
所以說,引用數(shù)組可以使用下標(biāo)法和指針法
1、下標(biāo)法:即用a[i]的形式訪問數(shù)組元素,
2、指針法:即采用*(a+i),*(p+i)形式,用間接訪問的方法來訪問數(shù)組元素,其中a是數(shù)組名,p是指向數(shù)組的指針變量,p=a;
int main()
{
    int a[10],i;
    for(i=0;i<10;i++)
        *(a+i)=i
    for(i=0;i<10;i++)
        printf("a[%d]=%d\n",i,*(a+i));
}

指針數(shù)組的概念:

一個(gè)數(shù)組的所有元素都是指針則是數(shù)組指針,指針數(shù)組是一組有序的指針的集合。

指針數(shù)組的所有元素必須是具有相同存儲(chǔ)類型和指向相同數(shù)據(jù)類型的指針變量。
**指針數(shù)組的一般形式:
類型說明符 * 數(shù)組名[數(shù)組長度];
**
其中類型說明符為指針指向的變量的類型:

*例如:int pa[3];:pa是一個(gè)指針數(shù)組,他有三個(gè)數(shù)組元素,每個(gè)元素都是一個(gè)指針,指向整型變量。


指向指針的指針:如果一個(gè)人指針變量中存放的另一個(gè)指針變量的地址,則稱這個(gè)指針變量為指向指針的指針變量。

int i;
int *p;
int a[n];
int *p[n];
int (*p)[n];
int f();
int *p();
int (*p)();
int **p;

**
**
**二、函數(shù)指針
**
**指向函數(shù)的指針包含了函數(shù)的地址,可以通過它來調(diào)用函數(shù)。聲明格式如下:
類型說明符 (*函數(shù)名)(參數(shù))
**
**其實(shí)這里不能稱為函數(shù)名,應(yīng)該叫做指針的變量名。
**
**這個(gè)特殊的指針指向一個(gè)返回整型值的函數(shù)。
**
**指針的聲明筆削和它指向函數(shù)的聲明保持一致。
**
**指針名和指針運(yùn)算符外面的括號(hào)改變了默認(rèn)的運(yùn)算符優(yōu)先級(jí)。
**
**如果沒有圓括號(hào),就變成了一個(gè)返回整型指針的函數(shù)的原型聲明。
**
**
**
*void (fptr)();
**
**
**
**把函數(shù)的地址賦值給函數(shù)指針,可以采用下面兩種形式:
**
**
**
**fptr=&Function; fptr=Function;
**
**
**
**取地址運(yùn)算符&不是必需的,因?yàn)閱螁我粋€(gè)函數(shù)標(biāo)識(shí)符就標(biāo)號(hào)表示了它的地址,
**
**如果是函數(shù)調(diào)用,還必須包含一個(gè)圓括號(hào)括起來的參數(shù)表。
**
**可以采用如下兩種方式來通過指針調(diào)用函數(shù):
**
*x=(fptr)(); x=fptr();
**
**第二種格式看上去和函數(shù)調(diào)用無異。
**
**但是有些程序員傾向于使用第一種格式,因?yàn)樗鞔_指出是通過指針而非函數(shù)名來調(diào)用函數(shù)的。
**

void (*funcp)();              //一個(gè)函數(shù)指針
void FileFunc(),EditFunc();        //聲明兩個(gè)函數(shù)
main()  
{
    funcp=FileFunc;          //把函數(shù)的地址賦值給函數(shù)指針
    (*funcp)();                //利用函數(shù)指針調(diào)用函數(shù)
    funcp=EditFunc;          //把函數(shù)的地址賦值給函數(shù)指針
    (*funcp)();                //利用函數(shù)指針調(diào)用函數(shù)
}  
void FileFunc()                //FileFunc函數(shù)的定義
{   
    printf("FileFunc\n");
}
void EditFunc()                //EditFunc函數(shù)的定義
{  
    printf("EditFunc\n");  
}
程序輸出為:
FileFunc  EditFunc
FileFunc  EditFunc

**一、指針函數(shù)
**
** 當(dāng)一個(gè)函數(shù)聲明其返回值為一個(gè)指針時(shí),實(shí)際上就是返回一個(gè)地址給調(diào)用函數(shù),
**
** 以用于需要指針或地址的表達(dá)式中。
**
**
格式:
類型說明符 * 函數(shù)名(參數(shù))
**
**當(dāng)然了,由于返回的是一個(gè)地址,所以類型說明符一般都是int。
**
**例如:
**
int *GetDate(); int * aaa(int,int);
**函數(shù)返回的是一個(gè)地址值,經(jīng)常使用在返回?cái)?shù)組的某一元素地址上。
**

int * GetDate(int wk,int dy); 
void main()
{  
    int wk,dy;
    do     {  
            printf("Enter week(1-5)day(1-7)\n");  
            scanf("%d%d",&wk,&dy);
        }while(wk<1||wk>5||dy<1||dy>7);
    printf("%d\n",*GetDate(wk,dy));  
}
    int * GetDate(int wk,int dy)  
    {
        static int calendar[5][7]=  {
       {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,-1}  };
        return &calendar[wk-1][dy-1];  
}

程序應(yīng)該是很好理解的,子函數(shù)返回的是數(shù)組某元素的地址。輸出的是這個(gè)地址里的值。

字符數(shù)組
1、字符數(shù)組的定義:與數(shù)組的定義相同
例如:char c[10].
2、字符數(shù)組的初始化
字符數(shù)組也允許在定義的時(shí)候初始化賦值:
例:char c[10]={'C',' ','p','r','o','g','r','a','m'};
賦值后各元素的值為:
c[0]為‘C’,
c[1]為‘ ’,
c[2]為'p'
........
c[8]='m';
c[9]默認(rèn)賦值為0;

3、字符數(shù)組的引用

#include <stdio.h>
int main()
{
int i,j;
chara[][5]=
{
{'B','A','S','I','C'},
{'d','B','A','S','E'}
};
for(i=0;i<=1;i++)
{
for(j=0;j<5;j++)
{
printf("%c ",a[i][j]);
}
printf("\n");
}
}

字符串和字符串結(jié)尾標(biāo)志
在C語言中沒有專門的字符串變量,通常用一個(gè)字符數(shù)組來存放一個(gè)字符串。當(dāng)把一個(gè)字符串存入數(shù)組時(shí),也把結(jié)束符‘\0’存入數(shù)組,并以此作為該字符串的結(jié)束標(biāo)志。有了‘\0’以后,就不必再用字符數(shù)組的長度來判斷字符串的長度了。
C語言允許使用字符串的方式對(duì)數(shù)組作初始化賦值。
例:char c[]={'C',' ','p','r','o','g','r','a','m'};
可寫為:char c[]={"C program"};或去掉{} 寫為:char c[]="C program";
用字符串賦值要比用字符逐個(gè)賦值多占一個(gè)字節(jié),用于存放字符串結(jié)束標(biāo)志'\0'.
'\0'是由C編譯系統(tǒng)自動(dòng)加上的,由于采用'\0'結(jié)束標(biāo)志,所以在用字符串賦初值時(shí)一般無須指定數(shù)組的長度,而由系統(tǒng)自行處理。

字符數(shù)組的輸入輸出:
除了上述賦值方法以外還可以使用printf,scanf函數(shù)直接輸入輸出;

int main()
{   
char string[]="TIAN YONG";
printf("%s\n",string);
return 0;
}
int main()
{
char str[20];
printf("intput str:");
scanf("%s",str);
printf("%s\n",str);
return 0;
}

空格以后的字符都不能輸出。

字符串處理函數(shù):
1:puts()字符串輸出函數(shù)
一般形式:puts(字符數(shù)組名)
功能:把字符數(shù)組中的字符串輸出到顯示器:

int main()
{
char c[]="string666";
puts(c);
return 0;
}

2:gets()字符串輸入函數(shù)
一般格式:gets(字符數(shù)組名)
功能;從標(biāo)準(zhǔn)輸入設(shè)備上輸入一個(gè)字符串

int main()
{
cahr st[15];
printf("input st:");
gets(st);
puts(st);
return 0;
}

3:strcat:字符串連接函數(shù)
一般形式:strcat(字符數(shù)組名1,字符數(shù)組名2)
功能:把字符串2中的字符串連接到字符數(shù)組1中字符串后面,并刪除數(shù)組1中的‘\0’.
例題連接“my nane is XXX”
4:strcpy:字符串拷貝函數(shù)
一般形式:strcpy(字符數(shù)組名1,字符數(shù)組名2)
功能:把字符數(shù)組2中的字符串拷貝到字符數(shù)組1中。結(jié)束標(biāo)志‘\0’也一同拷貝。注意:要求字符數(shù)組1要足夠長,否則不能全部裝入所拷貝的字符串。
5:strcmp:字符串比較函數(shù)
一般形式:strcmp(字符數(shù)組名1,字符數(shù)組名2)
按照ASCII嗎順序比較兩個(gè)數(shù)組中的字符串,并由函數(shù)返回值返回比較,相等返回0,1>2返回值大于,否則返回值小于0;
6:strlen:測(cè)試字符串長度
一般形式:strlen(字符數(shù)組名)
功能:測(cè)試字符串的實(shí)際長度(不含字符串結(jié)束標(biāo)志‘\0’)并作為函數(shù)返回值。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運(yùn)用指針編程是C語言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,473評(píng)論 3 44
  • 一、框架 1、Mac系統(tǒng)及常用工具、進(jìn)制;C數(shù)據(jù)類型、常量變量、運(yùn)算符、表達(dá)式、格式化輸入輸出 2、關(guān)系運(yùn)算符、邏...
    師景福閱讀 733評(píng)論 0 2
  • 大偵探福爾摩斯接到一張奇怪的字條:“我們約會(huì)吧! 3485djDkxh4hhGE 2984akDfkkkkggEd...
    小路_閱讀 162評(píng)論 0 0
  • 昨天(12月20日)本來是定好三個(gè)人第一次旅行的日子,初衷是打算著,給自己二十幾天“瘋狂”備考CET的獎(jiǎng)勵(lì),為著不...
    Wxu在簡書閱讀 257評(píng)論 0 0
  • 七月豪情似流火, 沙場(chǎng)閱兵壯山河! 萬眾矚目威武師, 三軍亮劍朱日和。 南昌城頭槍聲起, 鐘山風(fēng)雨...
    祁鷹閱讀 363評(píng)論 3 5