第八章-指针(数据类型 *)

指针

*(*x) = 10; <=> a = 10;
/*
析:x = effc5;
*x = p = effc0;
*p = a = 3;
*/

指针与数组

  1. 数组元素的访问方式
    • 数组名[下标] ages[i]
    • 指针变量名[下标] p[i]
    • *(p + i)
     int ages[5];
     int *p;
     p = ages;
    
  2. 指针变量+1,地址值究竟加多少,取决于指针的类型
    • int * => 4
    • char * => 1
    • double * => 8
     int ages[5] = {10, 9, 8, 67, 56};
        
     int *p;
     // 指针变量p指向了数组的首元素
     //p = &ages[0];
     // 数组名就是数组的地址,也是数组首元素的地址
     p = ages;
        
     /*
      p ---> &ages[0]
      p + 1 ---> &ages[1]
      p + 2 ---> &ages[2]
      p + i ---> &ages[i]
      */
        
     printf("%d\n",  *(p+2));
     //p<=>数组名(就是数组的地址)
     printf("%d\n",  p[2]);
    
  3. sizeof区分数组名和指针变量(迷惑点!!!!)
#include<stdio.h>
//注意:int array[]参数会警告:应该用int *array,也就是数这里的array就不是数组名字了,仅仅是个指针变量而已
void test(int array[]){
    int s = sizeof(array);
    //打印结果为:8 ,因为array不是数组了,而是指针变量
    printf("%d\n",s);
    //在这里拿到的count永远是1,就不是数组元素的个数了
    //int count = sizeof(array)/sizeof(int);
    //在这里拿到数组元素的个数,只能多加一个参数了
}

int main(){

    int ages[] = {1,2,3,4,5};
    int *p = ages;
    //这样定义会报警告:将一个数组赋值给了一个指针变量,但是仍然不会报错,因为默认会把数组的第一个元素地址给该指针变量
    int *w = {1,2,3,4,5};
    //但是尽管字符串是字符数组但是这样写却不会警告!!!
    char v[] = "it";
    char *sss= "it";
    //尽管ages是数组地址,但是结果可不是8!!!,因为ages是数组类型
    int s = sizeof(ages);
    //p也是数组地址,但结果是8,因为p是指针类型!!!
    int x = sizeof(p);
    int z = sizeof(w);
    //打印结果:20===8===8
    printf("%d===%d==%d\n",s,x,z);
    /*
     总结:
     虽然数组名(ages)是数组元素的第一个元素的地址,p理论上是与ages一样,但是实际是不一样的!!!,ages仍然是数组名,p仍然是一个指针变量而已!!
     */
    test(ages);
    return 0;
}
test2(){
	//字符串也一样!!!
	//字符指针
	char *sss= "it";
	字符数组
	char vp[] = "it";
	int s = sizeof(sss);
	int x = sizeof(vp);
	//打印结果:8===3
	printf("%d===%d\n",s,x);
}

指针与字符串(重要!!!!)

  1. 内存分5块:常量区/堆/栈/BSS段(静态区)/代码段
    • 常量区:存放一些常量字符串

         特点:省内存
         char *name = "it";
         char *name2 = "it";
         name与name2指向地址相同!!!,即指向同一块地址
         char name3[] = "it";
         char *name4 = "it";
         name3与name4指向的地址可是不一样哦!!!
      
    • 堆:存放对象
    • 栈:存放局部变量 (C语言的数组都是放在栈里面的)
  2. 定义字符串的2种方式
    • 利用数组(放在栈)
      • char name[] = "itcast";
      • 特点:字符串里面的字符是可以修改的
      • 使用场合:字符串的内容需要经常修改
    • 利用指针(放在常量区)
      • char *name = "itcast";
    • 特点:字符串其实是一个常量字符串,里面的字符是不能修改
    • 使用场合:字符串的内容不需要修改,而且这个字符串经常使用
     // 定义字符串数组
     void test2(){
         //int ages[5];
         // 指针数组(字符串数组)与字符数组区分开
         char *names[5] = {"jack", "rose", "jake"};
         // 二维字符数组(字符串数组)
         char names2[2][10] = {"jack", "rose"};
     }
     // 定义字符串
     void test()
     {
         //根据字符串就是特殊的字符数组来分析:
         // 字符串变量(!!!)
         char name[] = "it";
         name[0] = 'T';
         //Tt
         printf("%s\n", name);
         // "it" == 'i' + 't' + '\0'
         // 指针变量name2指向了字符串的首字符
            
         // 字符串常量(!!!)
         char *name2 = "it";
         //常量不可改的!!!
         *name2 = 'T';
         //第一个字符的地址
         printf("%p\n", name2);
         //打印字符串(error 10 程序崩溃!!!!)
         printf("%s\n", name2);
     }
     tests(){
         //也会崩溃!!!
         //这样定义会报警告:将一个数组赋值给了一个指针变量,但是仍然不会报错,因为默认会把数组的第一个元素地址给该指针变量
         int *w = {1,2,3,4,5};
         *w = 5;
         printf("%d",*w);
     }
    

指针数组作为main函数的形参

返回指针的函数

#include <stdio.h>
char *test();
int main(){
    char *name = test();
    
    printf("name=%s\n", name);
    
    return 0;
}
char *test(){
    return "rose";
}

指向函数的指针

 函数:
void test(){
	printf("调用了test函数\n");
}
double haha(double d, char *s, int a){
    
}
/******例1********/
// (*p)是固定写法,代表指针变量p将来肯定是指向函数
// 左边的void:指针变量p指向的函数没有返回值
// 右边的():指针变量p指向的函数没有形参
void (*p)();
// 指针变量p指向了test函数
p = test;
//调用函数的三种方式
p();//因为p=test嘛
(*p)(); // 利用指针变量间接调用函数
test(); // 直接调用函数
/*****例2*******/
// 1.定义指向函数的指针
double (*p)(double, char *, int);
p = haha;
//或者定义时直接赋值
double (*p)(double, char *, int) = haha;
//2.如何间接调用函数
//1>第一种
p(10.7, "jack", 10);
//2>第二种
(*p)(10.7, "jack", 10);

指针变量=NULL

void指针类型

int a = 3;
int *p = &a;
char *p2 ;
void *p3;
//可以不需要(void *),系统自动转换
p3 = (void *)p1;
//可以不需要(void *),系统自动转换
p2 = (char *)p3;
p3 = &a;

如何区别:指针** 与 **指针?

Table of Contents