字符指针

在指针的类型中有一种指针类型位字符指针char*

一般用法

//用字符指针存放字符
int main()
{
    char ch = 'q';
    char * pc = &ch;
    *pc = 'w';

    return 0 ;
}

还有一种用法

//用字符指针存放字符串
int main()
{
    //本质上是把字符串"hello bit"的首字母h的地址放入*ps
    char* ps = "hello bit";
    char arr[]="hello bit";

    //验证指针*ps中存的是字符串首字母的地址
    printf("%c\n",*ps);//h

    //若要打印字符串"hello bit"
    printf("%s\n",ps);
    printf("%s\n",arr);

    return 0 ;
}
int main()
{
    char ch='w'; //定义一个字符w
    char *p=&ch; //定义一个字符类型指针指向字符w / 或者说把字符w的存放地址存入字符类型指针p中 
    const char *p2="abcdef"; //定义一个字符类型指针p2存放字符串的首地址,也就是字符a的地址,只要找到a的地址就能对字符串进行操作 -- const修饰指针p指向的地址
    return 0 ;
}

一道面试题

int main()
{
    char str1[]="hello bit.";//不同数组,地址不同 
    char str2[]="hello bit.";
    char* str3="hello bit.";//常量字符串,地址相同
    char* str4="hello bit.";

    if(str1==str2)
        printf("str1 and str2 are same\n");
    else
        printf("str1 and str2 are not same\n");

    if(str3==str4)
        printf("str3 and str4 are same\n");
    else
        printf("str3 and str4 are not same\n");

    return 0 ;
}

//结果:
//str1 and str2 are not same
//str3 and str4 are same

//分析:
//str1 str2 为两个不同的数组,拥有不同的内存地址,而数组名存的是数组首元素的地址,所以不同
//str3 str4 为两个指针变量,里面都存了字符h的地址,字符串为常量字符串,是固定不可改的。hello bit只有一份,所以相同

//《剑指offer》P49

指针数组

指针数组是一个 存放指针数组

int main()
{
    int arr[10]={0}; //整型数组
    char ch[5]={0};  //字符数组

    int *parr[4];    //存放整型指针的数组 - 指针数组
    //int * :数组的元素类型
    //parr[4] :存放int* 类型元素的数组

    char *pch[5];    //存放字符指针的数组 - 指针数组

    return 0 ;
}

PS

int (*parr3[10])[5];
//将数组名去掉 : int (* )[5]; - 类型 - 有五个元素的整型数组数组指针
//那么int (*parr3[10])[5]; 就是就是一个有10个元素大小的数组parr3  - 存放着每个大小为五个元素的数组指针
int main()
{
    //指针数组
    //数组-数组中存放的是指针(地址)
    int* arr1[10];//存放整型指针的数组
    int a=10;
    int b=20;
    int c=30;
    int* arr3[3]={&a,&b,&c};
    int i=0;
    for(i=0;i<3;i++)
    {
        printf("%d ",*(arr[i]));
    }

    //指针数组
    //指针数组里面放数组的首地址
    int a[5]={1,2,3,4,5};
    int b[]={2,3,4,5,6};
    int c[]={3,4,5,6,7};
    int* arr3[3]={a,b,c};
    int i=0;
    //遍历打印数组内容
    for(i=0;i<3;i++)
    {
        int j=0;
        for(j=0;j<5;j++)
        {
            printf("%d ",*(arr[i]+j));
            //printf("%d",arr[i][j]);
        }
        printf("\n");
    }

    return 0 ;
}
char* arr2[4];//一级字符指针的数组
char** arr3[5];//二级字符指针的数组

数组指针

数组指针是指针。

  • 整型指针 - 指向整型的指针 - 可以存放整型的地址
  • pc是字符指针 - 指向字符的指针 - 可以存放字符的地址
  • 数组指针 - 指向数组的指针 - 存放数组的地址
int main()
{
    int *p = NULL;//整型指针 - 指向整型的指针 - 可以存放整型的地址
    char * pc = NULL;//pc是字符指针 - 指向字符的指针 - 可以存放字符的地址

    //数组指针 - 指向数组的指针 - 存放数组的地址
    int arr[10] = {0};
    //arr是首元素地址
    //&arr[0] - 首元素的地址
    //&arr - 数组的地址

    int arr[10]={1,2,3,4,5,6,7,8,9,10};
    int(*p)[10]=&arr;//数组的地址要存起来
    //&arr : 取数组arr的首地址
    //p = &arr : 定义一个指针p存放arr的首地址
    //int (*p)[10] = &arr : 定义一个整型数组指针*p存放数组,该指针大小为5个int元素大小

    //上面的p就是数组指针

    return 0;
}
int main()
{
    char* arr[5];
    char* (*pa)[5] = &arr;

    int arr2[10]={0};
    int (*pa2)[10]=&arr2;

    return 0 ;
}

&arr arr

实际上:

  • &arr表示的是数组的地址,而不是数组首元素的地址。

  • 数组的地址+1,跳过整个数组的大小,所以&arr+1相对于&arr的差值是40。
int main()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int (*pa)[10]=&arr;
    int i=0;
    /*
    //1
    for(i=0;i<10;i++)
    {
        printf("%d ",(*pa)[i]);  //*pa = arr
    }
    */

    /*
    //2
    for(i=0;i<10;i++)
    {
        printf("%d ",*(*pa+i));  //*pa = arr
    }
    */

    //3
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int *p=arr;
    int i=0;
    for(i=0;i<<10;i++)
    {
        printf("%d ",*(p+i));
    }

    return 0 ;
}
//二维数组的使用
void print1(int arr[3][5],int x,int y)
{
    int i=0;
    int j=0;
    for(i=0;i<x;i++)
    {
        for(j=0;j<y;j++)
        {
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }
}

//参数是指针的使用
void print2(int (*p)[5],int x,int y)
{
    int i=0;
    for(i=0;i<x;i++)
    {
        int j=0;
        for(j=0;j<y;j++)
        {
            printf("%d ",*(*(p+i)+j));
            printf("%d ",(*(p+i))[j]);
        }
        printf("\n");
    }

}

int main()
{
    int arr[3][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};//把二维数组看作一维数组时:第一行就是第一个元素,每一行是一个元素,那么数组名就是第一行的地址,

    print1(arr,3,5);//arr - 数组名 - 数组名就是首元素地址
    print2(int *p[5],int x,int y);

    return 0 ;
}

//当用指针打印数组时的等价用法
int main()
{
    int arr[10]={1,2,3,4,5,6,7,8,9,10};
    int i=0;
    int* p=arr;
    for(i=0;i<10;i++)
    {
        printf("%d ",p[i]);
        printf("%d ",*(p+i));
        printf("%d ",*(arr+i));
        printf("%d ",arr[i]);
    }

    return 0;
}