指针填坑

指针

1.指针运算
*(p1 - 1) :p1指向的地址减一个存储单元,也就是后移4个字节的地址中存储的数据
*p1 - 1:p1指向的存储单元值减1

2.指针与函数
2.1指向函数的指针

int max(int x,int y){}
int main(void){
    int (*p)(int,int);
    int a,b,c;
    p = max;
    scanf("%d %d",&a,&b);
    c = (*p)(a,b);
    return 0;
}

int (*p)(int,int);//p是一个指向函数的整型指针 
c = (*p)(a,b);//p指向函数,相当于调用了函数

2.2返回指针的函数
int *max(int *x,int *y);//max函数调用后返回值的数据类型是整型指针

3.void指针类型
void指针类型,可以用来指向一个抽象类型的数据,在将它的值赋给另一个指针变量时要进行强制类型转换,使之适合于被赋值的变量的类型.例:

char *p1;
void *p2;
p1 = (char *)p2;
p1 = (void *)p2;    //可以使用(void *)p1将p1转换成void *类型

不只对变量可以使用void指针类型,也可以将一个函数定义为void *类型

void * fun(char ch1,char ch2);
p1=(char *)fun(ch1,ch2);    //类型转换

4.简单链表

#include <stdio.h>
#include <stdlib.h>

struct list{
    int data;
    struct list *next;
};
typedef struct list node;
typedef node *link;

int main(){
    link ptr,head;                          /*创建指针对象*/
    int num,i;
    ptr = (link)malloc(sizeof(node));       /*分配空间*/
    head = ptr;                             /*分配空间*/
    printf("plesase input 5 numbers==>
"); /*输入数据*/
    for(i=0;i<=4;i++){                      /*循环创建对象*/
        scanf("%d",&num);
        ptr->data = num;                     /*对象赋值*/
        ptr->next = (link)malloc(sizeof(node));/*分配空间*/
        if(i == 4)
            ptr->next = NULL;               /*最后一个指针指向空*/
        else
            ptr = ptr->next;                /*指针指向下一个对象*/
    }
    ptr = head;
    while(ptr != NULL){
        printf("The value is ==>%d
",ptr->data);/*对象不为空就输入值*/
        ptr = ptr->next;
    }
    return 0;
}

5.指针与数组

&grade[3] = &grade[0] + 3 * 4    //含义是grade[3]的地址等于grade[0]的地址加上12
可以写成以下通式
数组中下标为N元素的地址 = 数组的首地址 + N * sizeof(DataType)

使用数组名访问元素使用指针变量一样

5.1指针与多维数组

int array[1][2];
array + 1            //数组下标1 行首地址
&array[1]            //数组下标1 行首地址

array[1]               //等价array[1]+0,指array[1][0]元素的地址
array[1] + 2          //array[1][2]的地址
*(array+1)+2        //array[1][2]的地址

*(*(array + 1) + 2)    //array[1][2]的值
*(array[1] + 2)          //array[1][2]的值

5.2指针与数组参数

6.指针与字符串

字符串的定义自动包含了指针,
例如定义message1[100],为100个字符声明存储空间,并自动创建一个包含指针的常量message1,存储的是message1[0]的地址。与一般的常量一样,指针常量指向是明确的,不能被修改。
字符串,可以不按声明一般数组的方式定义数组的维数和每一维的个数,可以使用新的方法,即用指针创建字符串。例:

char *message2 = "Talk is cheap";
char message1[20] = "Show me the code";

message1与message2不同,message1按照数组定义方式定义,message2用指针创建字符串,message1形式要求有固定的存储该数组的空间,而且,因为message1本身是数组名称,一旦初始化,再执行下面的语句就是错误的:

message1 = "hello !";

message2本身是一个指针变量。通过显式的方式明确了一个指针变量,对于message2执行了初始化后,再执行下面的代码是正确的:

message2 = "hello !";

从分配空间的角度分析,二者也不同。message1指定了一个存储10个字符位置的空间。message2不同,它只能存储一个地址,只能保存指定字符串的第一个字符的地址。

7.指针的指针
使用指针的指针访问字符串数组

int main(){
    char *seasons[]={"winter","spring","summer","fall"};
    char **p;
    int i;
    for(i=0;i<4;i++){
        p=seasons+i;
         printf("%s
",*p);
    }
    return 0;
} 

seasons是指针数组,每个元素都是指针,seasons是字符串"winter"的指针,seasons+i等价与&seasons[i],也就是每个字符串首字符的地址。

8.指针数组和数组指针

指针数组是指数组由指针类型的元素组成。比如 int *p[10],数组p由10个指向整型元素的指针组成;比如p[0],是一个指针变量,使用跟一般指针用法一样,就是这些指针有同一个名字,需要使用下标来区分。

int main(){
    int array[2][3] = {1,2,3,4,5,6};
    int i,j;
    int (*p)[3];
    p = array;
    for(i = 0;i < 2;i++){
        for(j = 0;j < 3;j++)
        printf("array[%d][%d] = %d
",i,j,p[i][j]);
    }
    return 0;
}

/**
**报数游戏
**从第1个报数,报到3的退出,问最后留下来的是哪个
**/

int main(){
    int i,k,m,n,num[nmax],*p;
    printf("输入总人数:");
    scanf("%d",&n);
    p = num;
    for(i = 0;i < n;i++)
        *(p + i) = i + 1;//赋值
    i = 0;k = 0;m = 0;//m:退出的人数  k:报的数  i:地址偏移
    while(m < n - 1){
        if(*(p + i) != 0)
            k++;
        if(k == 3){
            *(p + i) = 0;
            k = 0;//报到3恢复0
            m++;
        }
        i++;
        if(i == n)
            i = 0;//数组结束 重置到数组首地址
    }
    while(*p == 0)
        p++;
    printf("%d 号留下了
",*p);
    return 0;
}
原文地址:https://www.cnblogs.com/OceanF/p/10058117.html