初识指针与结构体

目录

指针

指针和指针类型

野指针

1.指针未被初始化

2.指针越界访问

3.指针指向的内存空间被释放

如何避免野指针

二级与多级指针

指针数组

结构体

结构的声明

结构成员的类型

结构体的访问

数据结构


指针

定义:

在计算机科学中,指针(pointer)是编程语言中的一个对象,利用地址它的值直接指向

(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以

说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址

的内存单元。

内存

一个字节 0xFFFFFFFF

一个字节 0xFFFFFFFE

一个字节 0x

一个字节 ......

一个字节 0x00000002

一个字节 0x00000001

一个字节 0x00000000

int main()

{

int a = 10;

int *p = &a;//指针变量

return 0;

}

指针存变量,变量放地址,一般地说指针就是地址

32位平台上有32根地址线,2的32次方byte=4GB,即有4GB空间进行编址

指针在32位平台上是4个字节,在64位平台上是8个字节

指针和指针类型

int main(()

{

printf("%d\n",sizrof(char*));//4

printf("%d\n",sizrof(short*));//4

printf("%d\n",sizrof(intr*));//4

printf("%d\n",sizrof(double*));//4

int a = 0x11223344;

int* pa = &a;

char* pc = &b;

printf("%p\n", pa);//00DDFC20

printf("%p\n", pc); //00DDFC20

&a // 44 33 22 11

&c // 44 33 22 11

*pa = 0; //00 00 00 00 int类型可以操作4个字节

*pc = 0; //00 33 22 11 char类型只能操作1个字节

return 0;

}

总结:指针类型决定了指针进行解引用操作的时候,能够访问空间的大小

int*p: *p能够访问4个字节

char*p *p能够访问1个字节

double*p:*p能够访问8个字节

int main()

{

int a = 0x11223344;

int* pa = &s;

char* pc = &a;

printf("%p\n", pa); 0095FB58

printf("%p\n", pa+1); 0095FB5C +1变成+4个字节

printf("%p\n", pc); 0095FB58

printf("%p\n", pc+1); 0095FB59 +1就是+1个字节

return 0;

}

指针类型决定了:指针走一步走多远(指针的步长,单位是字节)

int* p:p+1 -- > 4

char* p:p+1 -- > 1

double* p+1 --> 8

int main()

{

int arr[10]={ 0 };

int* p = arr;//数组名,首元素的地址

char* p = arr;//不能实现效果,只是访问了10个字节,而数组总共有40个字节

int i = 0;

for(i =0;i < 10; i++)

{

*(p+1) = 1; //将10个元素改成1

}

return 0;

}

野指针

1.指针未被初始化

int main()

{

int a;//局部变量不初始化,默认是随机值

int *p;//局部的指针变量,就被初始化随机值

*p = 20;

return 0;

}

2.指针越界访问

int main()

{

int arr[10] = { 0 };

int *p = arr;

int i = 0;

for(i = 0; i < 12; i++)

{

p++;// 从i=10的时候,数组越界,出现野指针

}

return 0;

}

3.指针指向的内存空间被释放

int* test()

{

int a = 10;

return &a;//出函数时即销毁,int a前面加static可解决问题

}

int main()

{

int *p = test();

*p = 20;

return 0;

}

如何避免野指针

1.指针初始化

2.小心指针越界

3.指针指向空间释放即使置NULL

4.指针使用之前检查有效性

int main()

{

int b = 0;

int a = 10;

int*pa = &a;//初始化

int* p = NULL;//NULL-用来初始化指针的,给指针赋值

int a = 10;

int *pa = &a;

*pa = 20;

//

pa = NULL;

*pa = 10;//发生错误

if( pa != NULL)

{

*p = 20;

}

return 0;

}

int main()

{

int arr[10] = { 0 };

printf("%p\n", arr);//地址-首元素的地址

printf("%p\n",&arr[0]);//

printf("%p\n",&arr);//取出的是整个数组的地址

//1. &arr - &数组名-数组名不是首元素的地址-数组名表示整个数组 - &数组名 取出的是整个数组的地址

//2.sizeof(arr) - sizeof(数组名) - 数组名表示整个数组-sizeof(数组名)计算的是整个数组的大小

printf("%p\n",arr);

printf("%p\n",arr + 1);//上下相差4

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

printf("%p\n",&arr[0]+1);//上下相差4

printf(“%p\n”,&arr);

printf("%p\n",&arr + 1);//上下相差40

return 0;

}

int main()

{

int arr[10] = { 0 };

int* p = arr;

int i = 0;

for (i = 0; i < 10; i++)

{

*(p+i) = i;

}

//for(i = 0; i < 10; i++)

//{

// printf("%p ===== %p\n",p+i,&arr[i]);

//}

二级与多级指针

int main()

{

int a = 10;

int* pa = &a;

int** ppa = &pa;//ppa就是二级指针

int*** pppa = &ppa;//pppa就是三级指针

int****ppppa=&pppa;

printf("%d\n", **pa);//10

**ppa=20;//全部都变成20

return 0;

}

指针数组

int main(()

{

int a = 10;

int b = 20;

int c = 30;

int* pa = &a;

int* pb = &b;

int* pc = &c;

//整形数组 - 存放整形

//字符数组 - 存放字符

//指针数组 - 存放指针

int arr[10];

int* arr2[3] = {&a, &b, &c};//指针数组,存指针的数组

int i = 0;

for(i = 0; i < 3; i++)

{

printf("%d ",*(arr2[i]));

}

return 0;

}

结构体

结构体的基础知识

结构是一些值得集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量。

结构的声明

struct tag

{

member-list;

}variable-list;

//如描述一个学生-一些数据

//名字

//年龄

//电话

//性别

//struct 结构体关键字 Stu - 结构体标签 struct Stu - 结构体类型

struct Stu

{

//成员变量

char name[20];

short age; int 图纸

char tele[12]; 定义结构体类型

char sex[5];

}s1,s2,s3;//s1,s2,s3 是三个全局的结构体变量 盖房子

typedef struct Stu

{

//成员变量

char name[20];//名字

short age;//年龄

char tele[12];//电话

char sex[5];//性别

char id[20];//学号

}s2;//类型(分号不能丢)

int main()

{

struct Stu s1 = {"旺财", 20, "15249287076", "保密"}; 创建结构体变量

Stu s2 = {"张三", 20 , "15249287076", "男"};//局部变量

return 0; int a = 10 房子

}

结构成员的类型

结构的成员可以是标量、数组、指针,甚至是其他结构体

结构体变量的定义和初始化

有了结构体类型,那如何定义变量,其实很简单

struct Point

{

int x;

int y;

}p1; //声明类型的同时定义变量p1

struct Point p2; //定义结构体变量p2

//初始化:定义变量的同时赋初值。

struct Point p3 = {x , y};

struct Stu //类型声明

struct S

{

int a;

char c;

char arr[20];

double d;

};

struct T

{

char ch[10];

struct S s;

char *pc;

};

int main()

{

char arr[ ] = "hello bit\n";

struct T t = {"hehe", {100, 'w', "hello world", 3.14}, arr};//结构体的嵌套

printf("%s\n", t. ch);//hehe

printf("%s\n", t. s. arr);//hello world

printf("%lf\n", t .s .d);//3.14

printf("%s\n", t .pc);//hello bit

return 0;

}

结构体的访问

typedef struct Stu

{

//成员变量

char name[20];

short age;

char tele[12];

char sex[5];

}Stu;//重命名,否则是struct Stu

void Print1(Stu tmp)

{

printf("name: %s\n", tmp.name);

printf("age: %d\n", tmp.age);

printf("tale: %s\n", tmp.tele);

printf("sex: %s\n", tmp.sex);

}

void Print2(Stu* ps)

{

printf("name: %s\n", ps->name);

printf("age: %d\n", ps->age);

printf("tale: %s\n", ps->tele);

printf("sex: %s\n", ps->sex);

}

int main()

{

Stu s = {"李四", 40, "15598886688", "男"};

//打印结构体数据

//Print1和Print2 哪个更好?

Print1(s);

Print2(&s);//用指针接收

//Print2更好,函数传参时,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降

//结论:结构体传参的时候,要传结构体的地址

return 0;

}

数据结构

-------线性数据结构

顺序表

链表 1->2 2->3 3->4 4->5 5->6

栈:先进后出,后进的先出

插入一个元素:压栈

删除一个元素:出栈

栈井进和栈井出

3

2

1

0

栈底

队列

------树形数据结构

二叉树

-----图

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值