C语言基础九:指针 【重点】

1.引入
    int a;
    a=100;//把100存放的a对应的存储单元中
    b=a; //取变量a的值
    
    访问:
        存储:到对应的地址单元中去存储值  a=100(write)
        取值:从对应的地址单元中去取     b=a    (read)
    访问方式:    
        直接访问:通过变量名去访问变量
        间接访问:通过地址去访问变量
    ======>指针

2.指针的概念
         地址:定义某个变量之后,编译器会给每个变量分配一段空间,每一个字节的空间都对应有一个编号,这个编号就是地址
       ☆指针:指针就是地址
        指针变量:存储指针的变量、存储地址的变量
3.指针变量:
        定义指针变量:
                指向数据的类型  *指针变量名
            ☆  指向:int  a;                        char  b;
                      int *p;                        char *p1;
                      p=&a;//p是指向变量a的         p1=&b;
                      sizeof(p)=4;                   sizeof(p1)=4; 
                     存储了谁的地址,就说它指向谁 
                    ”Int 类型说明符“:决定它要指向的数据的类型
                    int a;
                    1.int *p=&a;
                    2.int *p;
                      p=&a;
                       *p:表示的是p指向的变量a                    
                    
4.如何获取地址
            1.通过&
                &对象名:表示该对象的地址
                    对象:变量,数组元素 Int a[0] (例:a[0]是素组元素)  int a[3][4](例如:a[0][1])
            2.有些对象的名字本身就是地址
                    如:数组名、函数名
5.如何通过指针访问变量(*)    指向运算符

    *指向运算符:
        *地址  <====>该地址对应的变量
        *&a        <====>a这个变量
        ☆*指针变量<======>该指针变量指向的变量
        int a;
        int *p;
        p=&a;
        *p 表示:a这个变量
        
        
        ex.写一个函数,实现2个整型变量交换值
6.指针与函数参数
    如果要在一个函数内部操作“别的函数”的变量,
    但是“别的函数”那个变量的作用域不可见,
    只能通过地址来访问它。
    
7.数组与指针
    ☆1.指针加减:加减它所指向数据类型的长度
    2.如果定义一个指针变量指向数组a
        int a[10]={1,2,3,4,5,6,7,8,9,10};
        int *p=&a[0];
        a.访问a[0]的方式:
            1).a[0]   *a
            2).p[0]   *p
            3)*&a[0]
        b).访问a[1]的方式:
            1).a[1]    *(a+1)                (*a+1):a指向的变量值加1
            2).p[1]    *(p+1)
        补充:a中存储的是&a[0];
                | |
              a是指向a[0]的;
                | |
              *a表示的就是a[0]
        ex.使用指针的方式来遍历一个数组
    3.数组名与指针
        数组名可以看做是一个指针常量
            int    const a=123;//a的存储内容不可以通过变量名的方式来改变,但是可以通过指针的方式来改变
        错误代码示范及结果:
#include<stdio.h>
int main()
{
    
    int const a=123;
    printf("%d",a);
    a++;
    printf("%d",a);
    return 0;
}
        输出结果:
caogao.c: In function ‘main’:
caogao.c:7:2: error: increment of read-only variable ‘a’
  a++;
  ^
        正确代码示范及结果:
#include<stdio.h>
int main()
{
    
    int const a=123;
    printf("%d\n",a);
    int *p=(int *) &a;     ---    ---    ---//特别注意:使用   "int *p=&a;"   是错误的!!!!!!!!!!
    
    *p=5;
    printf("%d\n",*p);
    return 0;
}
    输出结果:
123
5


        1)指针常量
            int * const p;
            p的指向不可改变,
            但是p指向的内容是可以改变的
         错误代码示范及结果:
#include<stdio.h>
int main()
{
    int a=5,b=6;
    int * const p=&a;
    printf("%d\n",*p);
    p=&b;
    printf("%d\n",*p);
    return 0;
}
        输出结果:
caogao.c: In function ‘main’:
caogao.c:7:2: error: assignment of read-only variable ‘p’
  p=&b;
  ^
        正确代码示范及结果:
#include<stdio.h>
int main()
{
    int a=5,b=6;
    int * const p=&a;
    printf("%d\n",*p);
    //p=&b;        ---    ---    ---把"   p=&b;"   注释掉,不能改变p的指向!!!!!
    printf("%d\n",*p);
    return 0;
}
        输出结果:
5
5
        错误代码示范及结果:
#include<stdio.h>
int main()
{
    int a=5,b=6;
    int * const p=&a;    ---    ---//p指向a;
    printf("%d\n",*p);
    *p++;    ---    ---    ---//*p不可改变            ?
    printf("%d\n",*p);
    return 0;
}
        输出结果:
caogao.c: In function ‘main’:
caogao.c:7:2: error: increment of read-only variable ‘p’
  *p++;
  ^

        错误代码示范及结果:
#include<stdio.h>
int main()
{
    int a=5,b=6;
    int * const p=&a;    ---    ---//p指向a;
    printf("%d\n",*p);
    p++;    ---    ---    ---//p++即为(p=p+1);p将指向(p+1);但是p的指向不可变;    所以错误;        ?
    printf("%d\n",*p);
    return 0;
}
        输出结果:
caogao.c: In function ‘main’:
caogao.c:7:2: error: increment of read-only variable ‘p’
  p++;
  ^
        正确代码示范及结果:
#include<stdio.h>
int main()
{
    int a=5,b=6;
    int * const p=&a;    ---    ---//p指向a;
    printf("%d\n",*p);
    a++;    ---    ---    ---//p的内容是a,a可变;
    printf("%d\n",*p);
    return 0;
}
        输出结果:
5
6

        个人总结:指针常量格式为:    int * const p;
                使用格式为:    int a;
                        int * const p=&a;    -------    p指向a;
                在后面的程序中: 1.用  p  进行运算是  错误的,会改变p的指向!!!    比如 :    p++;    p=5;    p=p1;.....
                        2.用  *p  进行运算是  错误的,    会????        比如:    *p++;    *p=5;    *p=*p1;....
                        3.用  a  进行运算是  正确的,会改变p的内容!!!    比如:    a++;    a=5;    a=b;.....


        2)常量指针
            int const *p;
            const int *p;
            p的指向是可以改变的
            但是p指向的内容不可改变

                错误代码示范及结果:
#include<stdio.h>
int main()
{
    int a=40,b=6;
    int const *p=&a;
    printf("%d\n",*p);
    *p=50;    ---    ---     //*p  是指取  p  指向的东西里面的内容,即*p是一个内容,不可改变!!!!!
    printf("%d\n",*p);
    return 0;
}
        输出结果:
caogao.c: In function ‘main’:
caogao.c:7:2: error: assignment of read-only location ‘*p’
  *p=50;
  ^

                错误代码示范及结果:
#include<stdio.h>
int main()
{
    int a=40,b=6;
    int const *p=&a;
    printf("%d\n",*p);
    *p=b;    ---    ----    //  *p  是指取  p  指向的东西里面的内容,即*p是一个内容,不可改变!!!!!
    printf("%d\n",*p);
    return 0;
}
        输出结果:
caogao.2.c: In function ‘main’:
caogao.2.c:7:2: error: assignment of read-only location ‘*p’
  *p=b;
  ^

                正确代码示范及结果:
#include<stdio.h>
int main()
{
    int a=40,b=6;
    int const *p=&a;
    printf("%d\n",*p);
    a=50;    ---    ---    //  p  指向了 a 的地址,即  *p  指向  a  的内容; a 的内容自己改变了,但是并没有通过  *p;
    printf("%d\n",a);
    return 0;
}
        输出结果:
40
50

                正确代码示范及结果:
#include<stdio.h>
int main()
{
    int a=40,b=6;
    int const *p=&a;    ---    ---    //  p  指向了 a 的地址,即  *p  指向  a  的内容;
    printf("%d\n",*p);
    p=&b;    ---    ---    ---//现在  p  重新指向了  b  的地址,但是没有使用  *p  ;?????????
    printf("%d\n",*p);
    return 0;
}
        输出结果:
40
6
                错误代码示范及结果:
#include<stdio.h>
int main()
{
    int a=40,b=6;
    int const *p=&a;
    printf("%d\n",*p);
    p=50;    ---    ---    --//不可以把一个常量赋值给一个地址;
    printf("%d\n",*p);
    return 0;
}
        输出结果:
caogao.c: In function ‘main’:
caogao.c:7:3: warning: assignment makes pointer from integer without a cast [enabled by default]
  p=50;
   ^
        个人总结:常量指针格式:int const *p;    或    const int *p;  
                注意:    int和const谁在前面都一样,不影响语义;所以二者等价;
                    *p  是指取  p  指向的东西里面的内容,即*p是一个内容,不可改变!!!!!
                    p  本身是一个变量,里面存放的是  一个地址  ,在后面的程序中也可以再存放别的地址;


        3)const int *const p;
    4.指针数组与数组指针
        指针数组  int *a[10]//表示每一个元素的数据类型都是int* 
        数组指针  int(*a)[10]//a是一个指针,指向int[10]
        
        int a[10]---->a中存储的是&a[0]  a的指向的数据类型应该是int   a的类型是int*
        &a      ---->a中存储的是&a        &a指向的数据类型应该是a的类型(int[10])  
        int (*p)[10]---->                p的指向的数据类型应该是int[10]  p的类型应该是 int[10] *
        p=&a;//p=&int[10] a;
        
    5.指针与二维数组
        一位数组:
            int a[10];
            int** ------> int* ------ > int //定义时加*号往地址方向走
            
            &a--------->a ------->a[0]
            
            int[10]*    int[10]   int
            ====================================
            a+1               &a[1]
            *(a+1)            a[1]的值
            *(*(&a+1)-1)      a[9]的值     //使用指针变量时加*表示往值的方向走
            &a+1              加了40个字节
            
        
        ===========================
        二维数组:
        
        int a[3][4]         数据类型          指向/存储的地址
        a                    int[3][4]             &a[0]
        &a[0]               int[4]*             &a[0]
        a[0]                int [4]             &a[0][0]
        &a[0][0]            int *               &a[0][0]
        
        ================================================
        a+1                                     &a[1]
        &a[1]                                    &a[1]
        &a                                        &a
        &a+1                                      加了48个字节
        =================================================
        a[1]+2                                    &a[1][2]
        &a[1][2]                                  &a[1][2]
        *(a[1]+2)                                  表示a[1][2]的值
        *(*(a+1)+2)                                 a[1][2]的值
        a[1][2]                                    a[1][2]的值 
        ==================================================
8.字符串与指针
        在C语言中,没有任何类型表示字符串
        ""字符串后面自动添加\0
        "123"
        只需要一个字符指针来存储字符的首地址,便可以找到整个字符串
        char *s="1237";//把"1237"的首地址存储到指针变量s中
        字符串存储在.rodata(只读数据)区域的
        
        char *s="123456";
        s="789"//指向可以改变
        s[0]='p';//error   内容不可改变
        
        char s[10];
        s="123445";//指向被改变  错误
        s[0]='2';//内容可被改变
        
        char *gets(char *s);
            功能:从屏幕上得到一个字符串
            char *s:字符数组首地址,字符指针变量名,
                    把得到的字符串保存到s指向的地址中
            返回值:返回得到字符串的首地址
        int puts(const char *s);
                功能:把字符串输出到屏幕上
                const char *s:你要输出字符串的首地址
                返回值:成功返回被输出字符的个数,失败返回-1
        #include <string.h>
        char *strcpy(char *dest, const char *src);        
                功能:把src地址中的字符串复制到dest中
                src:你要拷贝的字符串首地址
                dest:你要复制到的地址
                返回值:返回dest字符串的首地址
        char *strncpy(char *dest, const char *src, size_t n);
                功能:把src地址中的字符串拷贝n个到dest中
                src:你要拷贝的字符串首地址
                dest:你要复制到的地址
                n: 你要拷贝的字节个数
                返回值:返回dest字符串的首地址
               #include <string.h>
       #include <string.h>
       int strcmp(const char *s1, const char *s2);
                功能:比较s1与s2的字符串大小(把s2与s1中的每个字符逐个比较,直到有个字符串为\0为止,或者2个字符不一致)
                返回值:如果s1==s2   返回值为0
                        如果s1>s2    返回值为 1
                        如果s1<s2    返回值为-1
       int strncmp(const char *s1, const char *s2, size_t n);
                功能:比较s1与s2的字符串大小的前n个
                其他与strcmp相同
            
        #include <string.h>
    
       char *strcat(char *dest, const char *src);
                功能:把src的字符串追加到dest中(从dest的第一个'\0'开始追加)//char a[20]={0};
                        dest:你要追加到的字符串首地址
                        src:源字符串首地址
                返回值:dest字符串的首地址
                        
       char *strncat(char *dest, const char *src, size_t n);
                    功能:把src的字符串追加到dest中(从dest的第一个'\0'开始追加)//char a[20]={0};
                    dest:你要追加到的字符串首地址
                    src:源字符串首地址
                    n:要追加的字符个数
                    返回值:dest字符串的首地址
        ex。给3个字符串排序
9.指针函数与函数指针

        int swap(int a,int b);
        指针函数:int *swap(int a,int b);//swap是一个函数,只是返回值是指针
        函数指针:int (*swap)(int a,int b)//swap是一个指针,指向int(int,int)类型的函数
                定义:返回值类型 (*函数指针名)(参数列表)
                     参数列表:只要需要对应的形参的数据类型
                    例:int (*p)(int ,int );
                赋值:    a)p=&函数名;
                        b)p=函数名;
                使用:(*函数指针名)(实参列表)
                        (*p)(1,2);
10.多级指针
                int ***---->int**    ---->int *--->    int 
11.动态分配内存空间
            void *malloc(size_t size);
                 功能:动态分配内存空间
                 size:分配的字节数大小
                 返回值:分配空间的首地址
                            例子:    int a=10;
                    
                #include<stdio.h>
                #include<stdlib.h>
                #include<string.h>
                int main()
                {
                    int a=10;
                    int *s=&a;//int 我要 到它指向的地址中读4个字节的内容
                    printf("%d",*s);

                    char *s="1234";
                    s=(char *)malloc(10);
                    strcpy(s,"4546");
                    printf("%s",s);
                    return 0;
                }
             void *calloc(size_t nmemb, size_t size);
                功能:动态分配内存空间,并且会把分配的空间初始化成0
                nmemb:分配多少块
                size:每个块分配多少个字节
                返回值:分配空间的首地址,
             void *realloc(void *ptr, size_t size);
                功能:增加分配ptr指向的地址空间
                ptr :指向你要增加的空间首地址
                size:增加的字节数
12.main参数
            int main(int argc,char **argv)
            {
                printf("%d\n",argc);//argc表示运行参数的个数(当输入 ./a.out  123 3242 324 4325时,argc=5)
                printf("%s\n",argv[1]);//表示运行参数的第一个字符串  123
                return 0;
            }
            ex.使用运行参数的形式,把数字字符串  转换成 一个数  
            
补充:
    char *s=“1234”;
保存多个字符串:
        char *s[10]  //  可以存储10个字符串,每个字符串的字符是char *   
            单独输出一个字符串:printf("%s",s[0]);
        char s[10][20];//可以存储10个字符串,每个字符串 char [20]
            单独输出一个字符串:
                printf(“%s”,s[0]);

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值