Linux第一课:c语言 学习记录day08

四、指针

6、指针的大小

int a = 10;

int *p1 = &a;//8

char ch = 'a';

char *p2 = &ch; //8

sizeof(指针变量名)

#include<stdio.h>
int main()
{
    int a = 10;
    int *p1 = &a;
    printf("%d", sizeof(p1));
    char ch = 'a';
    int *p2 = &ch;
    printf("%d", sizeof(p2));
    return 0;
}

64位操作系统:指针大小8字节

32位操作系统:指针大小4字节

linux优化:把16位优化掉几个0,只显示12位

Windows系统:有16位就显示16位

指针总结

        1、32位操作系统:指针大小4字节,64位操作系统:指针大小8字节

        2、内存地址是固定的,但是变量的地址是固定的,因为栈区变量随机分配

        3、指针类型根据指针指向空间的数据类型不同而不同

7、段错误

Segeentation fault (core dumped)——核心以转储

产生原因:访问不存在的内存地址,访问系统保护的地址,访问只读的内存地址,空指针废弃(eg:malloc 与 free 释放后,继续使用),栈堆溢出,内存越界(数组越界,变量类型不一致等)

7、指针修饰

1、const 常量化

int const a= 10;        const修饰后面的内容

1)const int a = 10;

        int const a= 10;

        a  = 20;        // 错误,a不能改变,可以通过指针间接修改

        int *p = &a;        // 警告,a被const修饰,运行的化a的值会改变

        *p = 20;        //因为 const 修饰的是a,没有修饰*p

2)const int *p;        //修饰*p,指针指向的内容不能修改,但指针指向可以修改

        int const *p;
 

        int a = 10;

        int const *p;

        *p = 20;        // 错误,因为*p被修饰

        int b = 20;

        p = &b;        // 指针指向被修改了

3)int * const p;

        int a = 10;

        int b = 20;

        int *const p = &a;        // 错误

        *p = 30;        //正确,指向不能改变,指针内容可以变

        p = &b;        // 错误,修饰的是p,指针指向不能改变

2、void

void a;       // 不允许修饰普通变量

void *p;        // 允许修饰地址变量(8字节)

使用场景:函数参数或者函数的返回值

注意:通过void *类型的指针变量进行取内容的时候,需要对地址进行强转

转换方式:void * p = NULL;强转:(int *)p  取内容:*(int *)p

int a = 10;

void *p = NULL;

p = &a;

int *q = (int *)p;

printf("%d   %d\n",*q,*(int *)p);        // 10, 10

3、大小端

在计算机进行超过1字节数据进行存储时,会出现存储数据顺序不同的情况即大小端存储

Big-Endian(大端字节序)大端:在低地址存放高字节数据,高地址存放低字节数据

Little-Endian(小端字节序)小端:在低地址存放低字节数据,在高地址存放高字节数据

举例:存储数据:0x12345678

大端小端
0x40000x120x78
0x40010x340x56
0x40020x560x34
0x40030x78

0x1

int a = 0x12345678
char b;
b = (char) a;
printf("%x\n", b);

电脑是小端,网络是大端

电脑向网络传输东西,数据要从小端转成大端,传出去

网络向电脑传输东西,数据要从大端转成小端,接收数据

二级指针

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

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

格式

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

int a = 10;

int *p = &a;

int **q = &p;

访问a的值:

a        *p        **q

访问a的地址:

&a        p        *q

访问p的地址:

&p        q

指针和数组

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

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

1、指针和一维数组

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

int *p = a;

直接访问

#include <stdio.h>
int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *p = a;
    printf("%p %p %p\n",a, a+1, a+2);
    return 0;
}

间接访问

#include <stdio.h>
int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int *p = a;
    printf("%p %p %p\n",p, p+1, p+2);
    return 0;
}

a和p本质上不同,a是地址常量,p是变量,a不能执行++操作,但是p可以

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

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

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

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

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

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

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

int *p = a;

printf("%d\n", *p++);        // 3 再打印一次*p就是2

printf("%d\n", *a++);         // a不能++,a是地址常量

运算方法:

        1)++和*都是单目运算符,优先级相同

        2)运算顺序从右向左进行运算

*(p++)        // 3 实际上指针指向第二个元素的地址

(*p)++        // 3 实际上第一个元素变成了4

++*p        //  4 自加之后的值,从右开始,*p为3,++后变成了4,++在前先赋值再打印

++*(p)        // 同上

*++p        // 2 先++p,++在前,++p之后指针指向为第二个元素,再*(取地址内容)为2

*(++p)        // 同上

指针和二维数组

int a[2][3] = {1, 2, 3, 4, 5, 6};        // a 数组名,表示第一行首地址,a+1表示第二行首地址

在a前面加*,表示将行地址降级为列地址

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

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

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

*(a+1)+1:第二行第二列的地址

*(*(a+1)+1):第二行第二列的值

直接访问:

*(*(a+i)+j):第i+1行第j+1列的元素

*(a[i]+j):第i+1行第j+1列的元素

a[i][j]:第i+1行第j+1列的元素

间接访问:

数组指针

定义:本质上是指针,指向数组的指针,行指针

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

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

int (*p)[3] = a;

p:int (*)[3]:运算时三个三个算的

p 可以代替a进行元素访问,但是本质不同

访问a[i][j]的地址:

&p[i][j]  ==  &a[i][j]

p[i]+j  ==  a[i]+j

*(p+i)+j  ==  *(a+i)+j

访问a[i][j]的值:

p[i][j]

*(p[i]+j)

*(*(p+i)+j)

大小:

sizeof(p);64位,8字节

地址:

a+i

        a:第一行的地址

        a+1:第二行的地址

a[i]+j

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

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

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

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

*(a+i)+j

元素:

a[i][j]

        a[0][0]: 第一行第一列

        a[0][1]: 第一行第二列

*(a[i]+j)

*(*(a+i)+j): 第i+1行第j+1列的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值