C语言-指针

扬帆去远航 / 2023-09-03 / 原文

目录
  • 指针
  • 行指针
  • 多级指针
  • void指针
  • const修饰符

指针

  • 前置概述:在计算机内存中最小的操作单元是字节Byte(不是位bit)。每一个字节单元,都有一个编号,称为地址。

  • 指针定义:专门用来存放地址的变量,称为指针变量,通称指针

  • 格式:<存储类型> <数据类型> *<指针变量名>

    int a = 10;
    int * p;
    p = &a;
    // 可以理解为:p指针的目标数据类型是int,p指针自身的数据类型是int *
    // p:指针变量,存的内容是目标的地址
    // *p:是指针的目标的数据
    // &p:指针变量自身所占用存储区的地址,是一个常量
    
    
    // 延申出多级指针
    int * * q;
    q = &p;
    // q:指向目标p的地址
    // q的目标是p,p的数据类型是int *,那么定义q指针就是 int * * q
    
  • 指针的移动

    int a = 10, *p;
    double b = 3, *q;
    
    printf("%p,%p\n",p,p+2); // 移动8个字节
    printf("%p,%p\n",q,q+2); // 移动16个字节
    
  • 使用指针访问数组

    int a[] = {1,2,3,4,5};
    int * p;
    p = a;
    printf("%d,%d,%d,%d\n",a[1],*(p+1),*(a+1),p[1]); //a[1],*(p+1),*(a+1),p[1]具有完全相同的功能
    
    p++; // p是指针变量,可以做运算
    // a++; // error,a是数组名(地址常量),不能做运算
    
  • 延申:指针变量所占用的内存空间是对少?
    根据操作系统来定的,比如操作系统是32bit,32bit/8bit = 4 Byte,那么地址就是用4Byte来表示的,指针占用内存就是4Byte。

  • 字符数组及字符串

    • C语言本身没有内置的字符串类型,字符串本质上是一种特殊类型的数组,它的组成元素类型为char,除此之外不受制与数组长度的限制,以'\0'作为结束标志,作为字符串结束的标志。(\0作为一个特殊字符,它的ASCII值为0,但是它不是'0'字符,'0'字符的ASCII值为48。)
    • 定义字符串如下:
      // 以下两种方式等同
      char a[] = {'h','e','l','l','o','\0'};
      char b[] = "hello";
      printf("%s,%s",a,b);
      
      // 字符串数组,其实就是多维的字符数组
      char c[][3] = {"apple","peach","orange"};
      
    • 字符串常量注意点:当一个字符指针指向一个字符串常量时,不能修改指针指向的对象的值。
      char *p = "hello";
      *p = 'H'; // 报错,字符串常量不能修改
      
      char *p1 = "world";
      char *p2 = "world";
      printf("%p\n",p1); //0x8048500
      printf("%p\n",p2); //0x8048500  地址相同
      
      // 延申:c中全局变量,static修饰的变量,字符串常量,这三种是放在静态区域的,而不是堆栈内存中,程序结束的时候才释放这些内存。
      

行指针

行地址:二维数组名代表数组的起始地址,数组名+1,是移动一行元素。因此,二维数组名常被称为行地址。
行指针(数组指针):存储行地址的指针变量,称为行指针变量。

int a[][3] = {{5,4,7},{3,7,9},{2,5,6}};
int *p;
int (*q)[3];//行指针

p = a; // waring,不兼容的指针类型
q = a;

// 访问值为9的元素?
printf("%d\n",*(p+5));
printf("%d\n",*(*(q+1)+2)); // 使用行指针访问

多级指针

  • 概念:把一个指向指针变量的指针变量,称为多级指针变量。
  • 指针移动:多级指针运算也是以其目标变量为单位进行偏移。
    #include <stdio.h>
    int main(int argc, char const *argv[])
    {
        char *p[] = {"beijing","shanghai","guangzhou"};
        char **q;
        q = p;
    
        puts(q[1]);
        return 0;
    }
    

void指针

  • void指针是一种不确定数据类型的指针变量,它可以通过强制类型转换让该变量指向任何数据类型的变量。
  • 对于void指针,在没有强制类型转换之前不能进行任何指针的算术运算。
    int main(int argc, char *argv[])
    {
    	int a = 10;
    	double b = 3.14;
    
    	void * p, *q;
    	p = (void *)&a;
    	q = (void *)&b;
    
    	//printf("%d,%lf\n",*p,*q);
    	int * r = (int *)p;
    	printf("%d,%lf\n",*r,*(double *)q);
    	return 0;
    }
    

const修饰符

常数化变量的值

  • const int a = 10; a的值不能修改

  • const int * p; p指向的目标值不能修改

  • int const * p = &m; p的地址不能修改,但是可以修改目标的值

    int main(int argc, char *argv[])
    {
    	int m = 10;
    
    	const int * p;
    	p = &m;
    	//*p = 20; // error
    	printf("%d\n",*p);
    	
    	int * const q = &m;
    	//q = &m;  // error
    	*q = 20;
    	printf("%d\n",*q);
    
    	return 0;
    }