黑马程序员_iOS开发C语言基础之指针

来源:互联网 发布:mplayerx mac 白屏 编辑:程序博客网 时间:2024/05/18 21:48

1、指针使用常识

#include <stdio.h>

int main()

{

    /*不建议的写法,int* p只能指向int类型的数据

    int* p;

    double d = 10.0;

    p = &d ;

    */

    /*指针变量只能存储地址

    int * p;

    p=200

    */

    /*指针变量未经初始化,不要拿来间接访问其他存储空间

    int * p;

    printf("%d\n",*p);

     */

    /*

    int a =10;

    int a ;

    a = 10;

     */

    /*

    // 定义变量时的*仅仅是一个象征,没有其他特殊含义

    int *p = &a;

    *p = &a;//错误;

     p = &a;// OK

    int *p;

    p = &a;

     */

    return 0;

}

2、指向指针的指针

#include <stdio.h>

int main()

{

    int a =10;

    int *p = &a;

    int **pp = &p;

    //int ***ppp = &pp;

    a = 20;

    *p = 20;

    **pp = 20;// **pp = *(*pp)=*p=a,有几个箭头,访问时就需要几个*

    printf("%d\n",a );

    return 0;

}


3、利用指针实现函数多返回值

#include <stdio.h>

int sumAndMinus(int n1, int n2, int *n3);

int main()

{

    int a = 10;

    int b = 7;

    // 存储和

    int he;

    // 存储差

    int cha;

    // 利用指针实现函数多返回值;

    he = sumAndMinus(a,b,&cha);

    printf("和是%d,差是%d\n",he,cha );

    return 0;

}

/*

// 这个函数无法同时实现差和和的值

int sumAndMinus(int n1, int n2)

{

    return n1+ n2;

}

*/

int sumAndMinus(int n1, int n2, int *n3)

{

    *n3 = n1 - n2;

    return n1+ n2;

}

4、指针使用注意事项

#include<stdio.h>

/*

 0000 0001

 0000 0010

 0000 0000 

 0000 0000

 

 0000 0000 0000 0000 0000 0010 0000 0001  512+1=513

 指针指定类型的原因,就是根据指针类型,从起始地址开始使用类型决定的字节数,存取数据,如char *,int *分别是1个字节和4个字节

 */

int main()

{

    // 0000 0010

    int i = 2;

    // 0000 0001

    char c = 1;

    

    /*

    char *p;

    p = &c; //int*型指针p,指向字符类型变量c

    printf("c的值是%d\n",*p);//输出结果为1

    */

    

    int  *p;

    p = &c; //int*型指针p,指向字符类型变量c

    printf("c的值是%d\n",*p); //输出结果为513why?

    // 因为p指向的是整型数据,所以从指向的地址取前四个数据,而不是只取字符型c一个字节的数值

    //*p = 10;// 它会从p指向的地址开始用四个字节存储10

}

void test()

{

    char c;// 1

    int a;// 4

    long b;// 8

    

    // 任何指针都占有8个字节的存储空间

    char *cp;

    long *ap;

    long *bp;

    // %zd  unsigned long

    printf("cp=%zd,ap=%zd,bp=%zd\n",

           sizeof(cp),

           sizeof(ap),

           sizeof(bp));

}


5、指向数组的指针

#include <stdio.h>

int main()

{

    int ages[5] = {10 , 9867,56};

    int *p;

    //p = &ages[0];

    p = ages;

    printf("%p\n",p);

    printf("%p\n",p+1);

    printf("%p\n",p+2);//指针变量加1,是指向下个元素地址,不是值加1,此处为int型,所以相差4个字节

    printf("%d\n",*(p+2));

    printf("%d\n",ages[2]);

    printf("%d\n",p[2]);//效果同上句,输出8,可以把指针当做数组用

  /*

     p ---> &ages[0]

     p+1 ---> &ages[1]

     p+i ---> &ages[i]

     */

  for (int i = 0; i <5;i++)

    {

        printf("ages[%d]=%d\n",i,*(p+i));

    }

    return 0;

}



/*

 第一种写法的实质是第二种写法

void change(int array[]) //第一种写法

{

    int s = sizeof(array);

    printf("%d\n",s); // s=8,因为把array当做指针了

}

void change(int *array) //第二种写法

{

}

*/

6、指针与字符串

#include<stdio.h>

/*

 内存分5块:

 1、常量区

 存放一些常量字符串,比如"24324",不可以修改

 

 2、堆

 存放对象

 

 3、栈

 存放局部变量,可以修改

 

 4

 5

 */


/*

 1. 定义字符串的2中方式

1>利用数组

    char name[] = "it";

    特点:字符串里面的字符是可以修改的

 2> 利用指针

    char *name = "it";

    特点:这个字符串其实是一个常量字符串,里面的字符是不能修改

 使用场合:

 所以如果你的字符串是经常要修改,则要用字符数组存储,如果是经常使用但是不能修改,则用字符指针存储,节省内存空间。

 大部分使用是用指针形式,如果字符串要修改,就会使用OC字符串了。

 

 */


int main()

{

    char name[20];

    

    printf("请输入姓名:\n");

    scanf("%s",name );

    printf("******\n");

    printf("%s\n",name);


    return 0;

}


// 定义字符串数组,,字符串数组

void test2()

{

    char* name = "jack";

    

    char* name2 = "rose";

    

    // 指针数组(字符串数组)

    char* names[] = {"jack" , "rose"};

    //二维字符串数组(字符串数组)

    //注意必修定义字符串数组的大小和长度

    //char names4[][] = {"jack" , "rose"};编译通不过

    char names4[2][5] = {"jack" , "rose"};

}


//定义字符串,,字符数组

void test()

{

    // 字符串变量

    char name[] = "it";//放在栈里, 可以修改

    name[0] = 'T';

    // "it" == 'i' + 't' +'\0'

    // 指针变量name2指向了字符串的首字符

    

    //字符串常量,不可修改,放在常量区,可以缓存,下次再用到这一常量,指向的是同一个存储地址,不会重新开辟一块空间存储同样的内容,如下所示,name2name3指向同一地址

    char* name2 = "it";// name2指向字符串首地址

    char* name3 = "it";

    printf("name2地址=%p\nname3地址=%p\n",name2 , name3);//输出的地址值是一样的,因为它们被放在常量区。

    //*name2 = 'T';//错,不可以修改,bus error程序运行崩溃

    printf("%c\n",*name2);// 输出'i',因为占位符是%c*name2字符串首地址内容

    printf("%s\n" , name2);// output "it" ,注意此处不能有*,因为占位符是%s,输出字符串,所以传进去的字符串首地址name2,而不是首地址符内容*name2;

}


7、返回指针的函数

/*

 1、返回指针的函数,OC中不常用

 2、指向函数的指针,OC中有替代的语法

 这两项只要求看懂语法。

 */

// 返回指针的函数

#include <stdio.h>

char* test();

int main()

{

    char* name = test();

    printf("%s\n",name);

    return 0;

}

char* test()

{

    return "rose";

}

8、指向函数的指针

//***********************

/*

 1.看懂语法

 2.定义指向函数的指针

    double (*p)(double,char *,int)

    p = haha;

    或者

    double (*p)(double,char * ,int) = haha;

 3.如何间接调用函数

 1> p(10.7,"jack",10)

 2> (*p)(10.7,"jack",10)

 */


//函数也有自己的地址

#include <stdio.h>


void test()

{

    printf("调用了test函数\n");

}


int sum(int a , int b)

{

    return a+b;

}


int main()

{

    /*

    int a =10;

    int* p;

    p = &a;//p已经指向a了。

    *p //调用变量a

    */

    

    //(*p)是固定写法,代表指针变量p将来肯定是指向函数

    // 左边的void:代表变量p指向的函数没有返回值

    // 右边的():指针变量p指向的函数没有形参

    void (*p)();

    

    //p = 函数地址;要想让指针变量p指向函数,就要把函数的地址赋给指针变量。函数名就代表着函数首地址,同样数组名代表着数组首地址。

    //指针变量p指向了test函数

    p = test;

    test(); // 这是之前直接调用函数的方式

    p(); //这又是一种调用方式,和数组指针p[2]有点类似

    //使用指针变量p调用test函数

    (*p)(); // 利用指针变量间接调用函数


    //定义指针变量指向sum函数

    // 左边的int:指针变量p指向的函数返回int类型的数据

    // 右边的(int int):指针变量p指向的函数有2int类型的形参

    int (*p1)(int , int);

    // 把函数的地址赋给指针变量p1

    p1 = sum;

    //调用函数的三种方式

    int sum3 = sum(10,10);

    int sum1 = p1(10,10);

    int sum2 = (*p1)(10,10);

    printf("sum3=%d,sum1=%d,sum2=%d\n",sum3,sum1,sum2);

    return  0;

}



0 0