《C语言》-(指针)

指针:

  • 格式:

    变量类型  *变量名;  如:int *p;

  • 注意点:

1.指针变量只能存储地址

2.指针就一个作用,能够根据一个地址值,访问对应的存储空间;

3.指针变量p前面的int代表p只能指向int类型的数据;

  • 注:

64位编译器中,指针变量都是占用8个字节,但是为什么还要分为:char *p; int *p;等,是因为在取值时,*p会从p存储的地址开始,取一定的字节(如:int就会从p所存储的地址开始向下4个字节

 

一、指针的基本使用

例:

int *p; // 定义了一个指向int类型数据的指针变量p

int a = 90; // 定义了一个int类型的数据a = 90

p = &a; // &a :取得变量a的地址,并且赋值给指针变量p

*p = 10; // 对p所指向的存储空间赋值(*)

解析:a = 90   -->   10;

注意点:

   int *p; 中的*和*p = 10;中的*意思是不一样的;

   int *p;中的*代表一个指针变量(标志

   *p = 10;中的*代表对p指向的存储空间进行赋值

代码练习一:

运行结果:

 

二、指针变量的使用注意

  • 注意点一:

   // 不建议这样写 int *p 只能指向int类型的数据
    // 警告: warning: incompatible pointer types assigning  to 'int *' from 'double *' [-Wincompatible-pointer-types]
    int *p;
    
    double a = 10.0;
    
    p = &a;

 

  • 注意点二:

   // 指针变量只能存储地址
    // 警告(warning: incompatible integer to pointer   conversion assigning to 'int *' from 'int' [-Wint-conversion])
    int *p;
    p = 200;

 

  • 注意点三:

   // 指针变量未经过初始化,不要拿来间接访问其指向的存储空间(不明确)
    // 没有警告、输出0
    int *p;
    
    printf("%d\n", *p);

 

  • 注意点四:

// 定义变量时的*仅仅是一个象征,没有其他特殊含义
    int a = 9;
    int *p = &a; // 定义变量时的*仅仅是一个象征,没有其他特殊含义
    
    // *p = &a; // 不正确的写法  
          // 报警(warning: incompatible pointer to integer
                conversion assigning to 'int' from 'int *'; remove & [-Wint-conversion])
p = &a; *p = 20; // 这里的*的作用:访问(赋值)指针变量p指向的存储空间 printf("%d\n", a);

 

  • 代码练习:

 运行结果:

 

 三、指针和数组

1.数组元素的访问方式

  • 数组名[下标];  如:ages[i];

  • 指针变量名[下标];  如:p[i];  // 前提是指针变量p指向数组

例:
int ages[5];
int *p;
p = ages; // 数组名就是数组首元素的地址
  •  *(p + i);

2.指针变量的+1,究竟是加多少取决与指针变量的类型

  • int *p; p + 1 相当于地址值+4;
  • char *p; p + 1 相当于地址值+1;
  • double *p; p + 1 相当于地址值+8;
  • 代码练习:

#include <stdio.h>

/*
 一、数组元素的访问方式
 1.数组名[下标]   如:ages[i]
 2.指针变量名[下标]   如:p[i]   前提是指针变量p指向数组
 3.*(p + i)   前提是指针变量p指向数组
 
 二、指针变量+1究竟加多少,取决于指针的类型
 */

int main()
{
    int ages[5] = {10, 12, 33, 56, 55};
    
    /*
    // 方式1:遍历整个数组
    for (int i = 0; i < 5; i++) {
        printf("%d\n", ages[i]);
    }
     */
    
    // 方式2:通过指针间接访问数组元素
    
    int *p;
    
    p = &ages[0];
    
   // 数组名就是数组的地址,也是数组首元素的地址
    // p = ages;

    printf("%d\n", *p); // 输出  10
    
    // 输出地址值
    // 总结:如果p指向数组首元素(第0个元素),那么p+1指向的就是第1个元素,p+2指向的就是第2个元素,并不是将地址值加1,这里是加4,因为是int类型的指针
    /*
     p   ——> &ages[0]
     p+1 ——> &ages[1]
     p+2 ——> &ages[2]
     
     p+i ——> &ages[i]
     */
    
    printf("%p\n", p); // 输出 0x7fff535e3c30
    
    printf("%p\n", p + 1); // 输出 0x7fff535e3c34
    
    printf("%p\n", p + 2); // 输出 0x7fff535e3c38
    
    // 方式2:通过指针间接访问数组元素
    for (int i = 0; i < 5; i++) {
        printf("%d\n", *(p + i));
    }
    
    // 访问数组元素的三种方式
    // 1.数组名[下标]   如:ages[i]
    printf("%d\n", ages[3]);   // 输出   56
    
    // 2.指针变量名[下标]   如:p[i]
    printf("%d\n", p[3]);      // 输出   56
    
    // 3.*(p + i)
    printf("%d\n", *(p + 3));  // 输出   56
    
    return 0;

 

四、指针和字符串

  • 定义字符串的两种方式:

1.利用数组

char name[] = "itcast";

  • 特点:这个字符串里面的字符可以修改
  • 使用场合:字符串的内容需要经常修改

2.利用指针:

char *name = "itcast";

  • 特点:这个字符串其实是一个常量字符串,里面的字符不允许修改
  • 使用场合:字符串的内容不需要修改,而且这个字符串经常使用;
  •  代码练习:

 

运行结果:

 

五、数组指针及字符串的输入

#include <stdio.h>

int main()
{
    // 一、定义字符串数组的两种方式
    // 方式1:利用2维数组
    char names[3][5] = {"jack", "rose", "jake"};
    
    // 方式2:利用指针数组
    char *names2[3] = {"jack", "rose", "jake"};
    
    // 二、接受用户输入的字符串
    // 1.先定义一个字符串用来存储用户输入的字符串
    char names3[20];
    
    // char *names3; // 这里不能用这种方式来定义一个字符串,因为这么字符串将来要接受用户输入的字符,是要变动
                的,而这种方式定义的时一个字符串常量,运行时会程序奔溃(Segmentation fault: 11)
// 2.提示用户输入一个字符串 printf("请输入一个字符串:\n"); // 3.接受用户输入的字符串 // scanf("%s", &names3); scanf("%s", names3); // 数组名就是地址,这里的%s会将用户输入的字符串从这个地址开始一个一个地存到names3这个字符串变量内 // 4.将接受到的字符串打印出来 printf("%s\n", names3); return 0; }

六、返回指针类型的函数

#include <stdio.h>
char test(); char *test2(); int main() { char *name = test2(); printf("%s\n", name); // 输出 rose return 0; } // 返回char类型的函数 char test() { return 'A'; } // 返回指针(char类型)的函数 char *test2() { return "rose"; // 在前面学过 char *name = "jake"; }

七、指向函数的指针

1.定义指向函数的指针

如:有一个函数: double haha(int a, char *s, double b);

double (*p)(int, char *, double); //定义了一个指向函数的指针

p = haha; // 将这个指向函数的指针指向haha函数 上面的两句可以整合成一句: double (*p)(int, char *, double) = haha;

2.函数的调用

  • 直接调用:

    haha(10, "jake", 12.5);

  • 间接调用:

    p(10, "jake", 12.5);

  • 间接调用:

    (*p)(10, "jake", 12.5); //(*p)这里的小括号千万不能省略,固定格式

 

代码练习:

#include <stdio.h>

void test();

int sum(int n1, int n2);

int main()
{
    // (*p)是固定写法,代表指针变量p将来肯定指向的时函数
    // 左边的void是代表指针变量p指向的函数是没有返回值的
    // 右边的()是代表指针变量p指向函数没有形参
    
    // 1.定义了一个指向函数的指针p
    void (*p)();
    
    // 2.将这个指向函数的指针p指向test函数
    // 函数名就是地址
    p = test;
    
    // 函数的调用
    p(); //1.间接方式
    
    (*p)(); // 2.间接调用,
    
    test(); // 3.直接调用
    
    
    
    // 练习
    // (*p)是固定写法,代表指针变量p将来肯定指向的时函数
    // 左边的int是代表指针变量p指向的函数是返回的时int类型的数据
    // 右边的(int, int)是代表指针变量p指向函数又两个int类型的形参
    int (*p2)(int, int); // 这里形参变量名可以省略
    
    p2 = sum;
    
    int a = p2(10, 12); // 间接调用
    
    // int a = (*p2)(10, 12); // 间接调用
    
    // int a = sum(10, 12); // 直接调用
    
    printf("%d\n", a);
    
    return 0;
}

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


int sum(int n1, int n2)
{
    return n1 + n2;
}

 

 

 

 

 
 
 
 
posted @ 2015-02-03 00:36  深秋的露水  阅读(553)  评论(0编辑  收藏  举报