第六章     指针


        本章内容:1.指针的声明和使用   2.指针作为函数参数   3.数组与指针    4.动态内存分配   5.字符串与指针   6.指针数组   7.数组指针   8.指向指针的指针


        1.  指针的声明和使用

             指针声明通用的格式:数据类型  *指针变量名称;

             指针的使用:

int  i = 10;
      int  *p;
      p = &i;
   
      也可以如此:
 
      int  i = 10;
      int  *p = &i;

            PS:注意这里,假如第一种赋值写成这样 *p = &i;这样是错误的。原因:*号也成为取值,*号的优先级大于=号,所以首先会进行*p运算,而*p运算是求出p指针指向的内存的值,而p内没有数据,所以*p找不到元素。

            还可以这样赋值: int  *p = 200;   或者写成  int  *p;  *p = 10;

            指针的运算:(*p)++ 执行完毕后p的指向仍然是i  。*p++ 执行完毕后p指向下一个地址,p的指向发生了改变。  

        2.  指针作为函数参数

             

//指针作为函数参数传值
void changxToY(int *arr,int count)
{
    int *satrt=arr,*end=&arr[count-1];
    for (int i=0; i<count/2; i++,satrt++,end--) {
        int temp = *satrt;
        *satrt = *end;
        *end = temp;
    }
    
}

        3.  数组与指针

             3.1  一维数组与指针:

                    初始化:

int  array[5];
         int  *p;

         p = &array[0];
         p = &array[4];
         p = array;


    

                   通过指针元素访问数组:


int  array[] = {1,2,3,4,5};
        int *p;
        p = array;
     
        printf("下标法输出开奖结果:\n");
        for(int i=0 ; i<5; i++)
        {
               printf("%d\n",array[i]);
        }

        printf("使用数组名法输出开奖结果:\n");
        for(int i=0 ; i<5; i++)
        {
               printf("%d\n",*(array+i));
        }

        printf("指针法输出开奖结果:\n");
        for( ; p<array + 5; p++)
        {
               printf("%d\n",*p);
        }



            3.2  二维数组与指针

                   初始化:                   


int  *p;
       int  a[2][4];
      
       p = a[0];
       p = &a[0][0];



                   通过指针访问数组:

int  arr[3][4] = {1,2,3,4,11,22,33,44,111,222,333,444};
       int  *p;
       p = arr[0];   //或者 p = &arr[0][0]
      
       for(int i=0; i<3*4; i++,p++)
       {
               if(i % 4 == 0)
                     printf("\n");
               printf("%d\t",*p);
       }


       //结果为:         1      2       3      4
                        11     22      33     44
                        111    222     333    444

        4.  动态内存分配

             malloc()函数,free()函数,calloc()函数

//输入几个数,然后将这些数字翻转过来然后输出
       int *p,*start ,*end,temp;
       int count;
       printf("请输入要输入的数字个数:\n");
       scanf("%d",&count);
       p = (int *)malloc(count * sizeof(int));
       if(p == (int *)NULL)
      {
             printf("分配内存出错\n");
             exit(0);
      }else{
                    printf("请输入%d个数",count);
                    for(int i=0;i<count;i++)
                    {
                          scanf("%d",p+i);
                    }
                    start = p;
                    end = p+count-1;
                    for(int i=0;i<count/2;i++,start ++,end --)
                    {
                           temp = *start;
                           *start = *end;
                           *end = temp;
                    }
                    printf("翻转后的结果\n");
                    for(int i=0;i<count;i++)
                   {
                        printf("%d",*(p+i));
                   }
                   free(p);   //释放内存
      }

              calloc()函数和malloc()函数功能是一样的,唯一的区别在于:malloc()函数申请到得内存区域内并不初始化为0,而calloc()函数申请到得内存区域初始化为0。

        5.  字符串与指针

              初始化:

char str[] = "hello  word";
       char *p;
       p = str;

       或者
       char  *p = "hello word";
       printf("%s",p);

             二维字符数组和指针:

char string[3][20] = {"hello word","hello coder","hello youths"};
      char *p;
      p = string[0];
      for(int i=0; i<3; i++)
      {
            printf("%s\n",p+i*20);
      }

        6.  指针作为函数返回值



//指针作为函数返回值
int *getArrays()
{
    static int arrays[]={1,2,3,4,5,6,7,8,9,10};
    for (int i=0; i<10; i++) {
        arrays[i] = arrays[i] * 10;
    }
    return arrays;
}

        7.  指针数组

             指针数组代表数组中得每一个元素都是一个指针,而这些指针可以指向其他地址。

             初始化:

int  i=10,j=20,k=30;
        int *p[] = {&i,&j,&k};

             使用:

char *boosName[5]={"C Primer","Objective-C","Visual","Learn Objective-C"};
    sortBookName(boosName, 5);
    for (int i=0; i<5; i++) {
        printf("%s\n",boosName[i]);
    }


//字符 指针数组排序
void sortBookName(char *booksName[],int num)
{
    
    char *temp;
    for (int i=1; i<num; i++) {
        for (int j=0; j<num-i; j++) {
            if (strcmp(booksName[j], booksName[j+1])>0) {
                temp = booksName[j];
                booksName[j] = booksName[j+1];
                booksName[j+1] = temp;
            }
        }
    }
}

        8.  数组指针

             数组指针是值向一个数组的指针变量,就是说我们定义的指针变量中存放的地址必须是一个数组才行,指针数组是一个数组,初始化需要多个数据初始化,而数组指针只需要一个地址数据就可以初始化。

//数组指针
void aaaa()
{
    int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
    int (*p)[4];
    p=a;
    for (int i=0; i<3; i++,p++) {
        for (int j=0; j<4; j++) {
            printf("%d ",* (*p+j) );
        }
        printf("\n");
    }
}

        9.  指向指针的指针             


//指向指针的指针
void bbbb()
{
    int **p;
    int i=10,*p1;
    p1 = &i;
    p = &p1;
    printf("%d\n",**p);
    
    char *names[]={"basic","c plus pluse","c sharp","objective-c"};
    char **p2;
    for (int i=0; i<4; i++) {
        p2 = names+i;
        printf("%s\n",*p2);
    }
}




        下面给出一些小例子:

        1.用指针实现三个数大小问题



//用指针实现三个数大小问题
void zhiZhenCountMax()
{
    int num[3],*p,*max;
    
    for (int i=0; i<3; i++) {
        scanf("%d",&num[i]);
    }
    p=num;
    max = p;
    for (int i=0; i<3; i++,p++) {
        if (*max<*p) {
            *max = *p;
        }
    }
    printf("最大值为:%d",*max);

}

        2.用指针实现排序问题



//用指针实现排序问题(从小到大)
void zhiZhenScore()
{
    int num[100],*p,temp,count;
    p = num;
    printf("要输入几个数count=");
    scanf("%d",&count);
    for (int i=0; i<count; i++) {
        scanf("%d",p+i);
    }
    
    for (int i=1; i<count; i++,p=num) {
        for (int j=0; j<count-i; j++,p++) {
            if (*p > *(p+1)) {
                temp = *p;
                *p = *(p+1);
                *(p+1) = temp;
            }
        }
    }
    
    for (int i=0; i<count; i++) {
        printf("%d ",num[i]);
    }

}

         3. 从第一个字符串中复制长度为n的字符到第二个字符串中



char str1[]="hello word";
    char str2[100]={'\0'};
    copyOneToOne(str1, 5, str2);
    puts(str2);

    //从第一个字符串中复制长度为n的字符到第二个字符串中
void copyOneToOne(char *str1,int n,char *str2)
{
    
    
    for (int i=0;i<n; str1++,i++,str2++)   {
        *str2 = *str1;
    }
}

         4. 从二维数组中找到最大值和最小值



//二维数组中找到最大值和最小值
void searchMaxAndMin()
{
    int arrays[3][4]={0},*p,*max,*min;
    printf("请输入12个数:\n");
    p = arrays[0];
    for (int i=0; i<3*4; i++,p++) {
        scanf("%d",p);
    }
    
    p=arrays[0];
    max = p;
    min = p+1;
    
    for (int i=0; i<3*4; i++,p++) {
        if (*max < *p) {
            *max = *p;
        }
        if (*min > *p) {
            *min = *p;
        }
        
    }
    printf("最大值为max=%d,最小值为:min=%d",*max,*min);
}

         5. 将第二个数组复制到第一个数组中



//mian函数内部
    int a[]={1,2,3,4,5,6},b[]={11,12,44,55};
    int count1 = sizeof(a)/sizeof(a[0]);
    int count2 = sizeof(b)/sizeof(b[0]);
    
    arrayprt(a,count1, b,count2);
    for (int i=0; i<count1; i++) {
        printf("%d\n",a[i]);
    }

    //数组拷贝函数(将第二个数组复制到第一个数组中)
void arrayprt(int *a,int count1,int *b,int count2)
{
    
    if (count1>=count2) {
        for (int i=0; i<count1; i++,a++,b++) {
            if (i<count2) {
                *a = *b;
            }
            else
            {
                for (int i=0; i<count1-count2; i++,a++) {
                    *a = 0;
                }
            }
        }
    }else{
        for (int i=0; i<count1; i++,a++,b++) {
            *a = *b;
        }
    }
}