Bootstrap

day08(C基础)指针

指针

指针的特点

1. 使程序更简洁、紧凑、高效 这个有点不算是指针比较鲜明或者独特的点

2. 有效的表达更复杂的数据结构

3. 动态分配内存 合理利用空间

4. 得到多于一个数的函数返回值 容易实现函数的编写和调用。

一级指针

地址:内存中每一个单元的编号(门牌号)

指针:就是地址,内存地址

指针变量

概念:存储指针的变量

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

例:int *p;//定义了一个指针变量p

int a=10;

int*p=&a;//p中存储的就是a的地址

访问值:*指针变量名 *p

修改值:*指针变量名=新值

指针和变量之间的关系:

int a=5;

int*p=&a; //a===*p &a===p a=10===*p=10

指针操作符:

*:取内容

&:取地址

单目运算:从右往左

int a =10;

*&a;  //10*&两者互逆

&*a; //错误

初始化:

1.将普通变量赋值给指针

int a=20;

int *p=&a;//定义时同时赋值

int *p;//野指针 乱指向

int *p=NULL;

int b=10;

p=&b; //先定义后赋值

2.将数组的地址赋值给指针

char s[]="hello";

char *p=s;

3.将指针变量的值交给另一个指针变量

int a=10;

int *p=&a;

int*q=p:

指针运算
算术运算

+ - ++ --

char s[]="hello";

char *p=s;

p+1:向高地址方向移动一个数据单位

p+n:向高地址方向移动n个数据单位,但是指针本身指向不会发生改变

p=&s[4];

p-1:向低地址方向移动一个数据单位

p-n:向低地址方向移动n个数据单位,但是指针本身指向不会发生改变

数据单位:指针的类型大小

char s[]="hello";

char *p=s;

p++ ----->p=p+1

p++:向高地址方向移动一个数据单位,指针本身指向会发生改变

p--:向低地址方向移动一个数据单位,指针本身指向会发生改变

注意:

1.指针的数据类型要和将要存储的变量的地址相同

例:int a; int *p=&a;

       short a; short*p*&a;

2.指针在+ - ++ --运算时移动的数据单位为指针的类型的大小

   即:指针的偏移地址=n*sizeof(指针的数据类型)

3.两个地址之间的差=两个地址之间间隔的元素的个数

关系运算

> < == !=

指针之间做关系运算时,指向高地址的指针大于指向低地址的指针

注意:

地址之间的比较 同数组之间的比较 指向不同区域的指针之间的比较无意义

#include <stdio.h> //引入头文件 std:标准 i:输入  o:输出 .h:库文件
#include <strings.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    int x[5] = {10, 20 , 30}; // 12 20 30
    int *px = x;
    printf("%d,", ++*px); // 11
    printf("%d\n", *px);  // 11
    px = x;
    printf("%d,", (*px)++); // 11
    printf("%d\n", *px);    // 12
    px = x + 1;
    printf("%d,", *px++); //20   
    printf("%d\n", *px);  // 30  
    px = x+1;
    printf("%d,", *++px); //30 
    printf("%d\n", *px);    //30
    return 0;
}
总结:

在输出或者赋值语句中:

*p++:先取内容,再移动指针的方向(向高地址方向移动一个数据单位)

(*p)++:先取内容*p,再对内容+1

 ++*p:先取内容*p,再对内容+1

 ++(*p):先取内容*p,再对内容+1

 *++p:先取内容,再移动指针的方向(向高地址方向移动一个数据单位)
指针的大小

取决于操作系统的大小 64位 ----8字节

总结:

  • 32位操作系统,指针大小4字节,64位操作系统,指针大小8字节
  • 内存地址是固定的,但是变量的地址不固定的,(栈区变量(局部变量)随机分配)
  • 指针类型根据指针指向空间的数据类型而决定的

指针修饰

const常量化 只读
使用const修饰变量

const int a=10;\\变量a只读

a=100; \\错误

int const a=10;

const修饰指针

const int *p;//修饰*p

int * const p;//修饰p

const int *const*p;//同时修饰p *p

void 空
void不能修饰变量
void修饰指针

void *p;//修饰任意类型的指针

int a=19;

void *p=&a;

如果对任意类型的指针赋值后进行取值 需要强转

int a=19;

void *p=&a;

printf("%d\n",*((int*)p));//强制转换

int a=19;

void*p=&a;

int *p1=(int*)p:

printf("%d\n",p1)://强制转换

段错误

野指针
  1. 指针变量没有赋值
  2. 指针置空后,对空间赋值
  3. 堆区空间free后,指针没有不及时置空
内存泄漏

内存空间溢出或程序结束未释放

对非法空间进行操作

大小端

大端:在低地址存放高字节数据,在高地址存放低字节数据

小端:在低地址存放低字节数据,在高地址存放高字节数据

int ---4字节

int a=0x12345678 起始地址:0x100

0x100

0x101

0x102

0x103

大端

0x12

0x34

0x56

0x78

小端

0x78

0x56

0x34

0x12

内存:

验证电脑大小端

小端存储

二级指针

一级指针:存放变量的地址 二级指针:存放一级指针的地址

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

int **p;//二级指针

int a=10;

int *p1=&a;

int **p2=&p1;

地址:

取a的内容:a *p1 **p2

取a的地址:&a p1 *p2

访问p1的地址:&p1 *p2

指针和数组

访问

直接访问:按变量的地址存取变量的值(通过数据名访问)

间接访问:通过存放变量地址的变量去访问变量(通过指针访问)

指针和一维数组

直接访问:

间接访问:

访问数组元素a[i]的地址:

直接访问:a+i ,&a[i]

间接访问:p+i ,&p[i]

访问数组元素a[i]的值:

直接访问:*(a+i) ,a[i]

间接访问:*(p+i) ,p[i]

注意:

a和p本质不同, a:数组名 地址常量      p:指针变量

指针和二维数组

直接访问:

二维数组的数组名 a:  第一行的首地址

如何表示第一行的其他元素?降级 降级到第一行第一列的地址    使用*

*a 第一行第一列的地址

*a+1 第一行第二列的地址

a

a[0]:第一行第一列的地址

a[0]+1:第一行第二列的地址

a[1]:第二行第一列的地址

a[1]+1:第二行第二列的地址

访问数组元素的地址(a[i][j]):

&a[i][j]      *(a+i)+j           a[i]+j

访问数组元素(a[i][j]):

a[i][j]       *(*(a+i)+j)        *(a[i]+j)

数组指针

定义:本质是指针 指向数组(行指针)

格式:存储类型 数据类型(*数组指针名)[列数]

例:int a[2][2]={1,2,3,4};

       int (*p)[2]=a;//定义一个数组指针

p:第一行的首地址      p+1:第二行的首地址

p+1移动8个字节(列数2*数据类型的大小)

间接访问

访问数组元素的地址(a[i][j]):

&p[i][j]       *(p+i)+j       p[i]+j

访问数组元素(a[i][j]):

p[i][j]        *(*(p+i)+j)        *(p[i]+j)

数组指针的大小p:八个字节

sizeof(数组指针名)

和操作系统有关:64--->8 32--->4

指针数组

定义:本质是数组,里面存放的是指针(地址)

格式:存储类型 数据类型 *指针数组名[元素的个数]

例:int *arrp[3];

1.用于存储普通变量的地址

int a=10,b=20,c=30;

int *arrp[3]={&a,&b,&c};

访问a的地址:arrp[0]

        a的内容:*arrp[0]

访问b的地址:*(arrp+1)

        b的内容:**(arrp+1)

2.存放二维数组每一行每一列的地址

int a[3][3]={1,2,3,4,5,6,7,8,9};

int *p[3]={a[0],a[1],a[2]};

访问:

第二行第一列的地址:p[1]      *(p+1)

第三行第二列的元素:*(p[2]+1 )     *(*(p+2)+1)

3.存放多个字符串

char *p[3]={"hello","asd","ak"}:

打印:”hello“字符串

printf("%s\n",p[0]);

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

打印:k字符

printf("%c\n",p[2][1]);

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

printf("%c\n",*(p[2]+1));   // []:先移动 后降级 p[2]===*(p+2) *(p+2)[1]===*(*(p+2)+1)

命令行参数

int main(int argc, char const *argv[])

{

    return 0;

}

argc:字符串的个数 传递的数据的个数

argv:指针数组 存放字符串

;