C语言学习笔记-指针、结构体

一、指针

1. 指针是什么

1.1指针的概念

在计算机科学中, 指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向
(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。

1.2 对指针的理解

#include <stdio.h>
   int main()
{
       int a = 1;//开辟一块地址空间
       int *p = &a;//&是取地址符,将a的地址存放在p变量中,p就是指针变量。
    return 0; 
}

指针就是一个特殊的变量,用来存放内存单元的地址,存放在指针中的值,都会被当做地址处理。

指针的大小在32位平台是4个字节,在64位平台是8个字节。

2. 指针和指针类型

2.1指针类型种类和定义方式

通过之前的学习,我们知道变量有不同类型,如整数型、浮点型等,相对应的,指针也有不同的类型。

当我们需要将某个变量的地址保存在p中时,我们就需要定义指针变量的类型。

char  *pchar = NULL;
int   *pint = NULL;
short *pshort = NULL;
long  *plong = NULL;
float *pfloat = NULL;
double *pdouble = NULL;

指针的定义方式就是 :type + *其实哪种类型的指针就是为了存放哪种类型变量的地址。

2.2指针类型的意义

指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。 比如: char*
指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。

3. 野指针

3.1野指针的概念

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量 在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的。

3.2野指针的成因与规避

成因:(1)指针未初始化

#include <stdio.h>
   int main()
{ 
       int *p;//指针未初始化
       *p = 20;
   return 0; 
}

(2)指针越界访问

#include <stdio.h>
   int main()
{
       int arr[10] = {0};
       int *p = arr;
       int i = 0;
       for(i=0; i<=11; i++) {
        //当指针指向的范围超出数组的范围时,p就是野指针
        *(p++) = i;
   }
    return 0; 
}

(3)指针指向的空间释放

规避:(1)注意指针的初始化

如果有确切的值就给它初始化为相应的值,如果没有,则初始化为NULL。

(2)小心指针越界

编译器不报错,需注意。

(3)指针指向空间释放则将其置为NULL

(4)避免返回局部变量的地址

(5)指针使用之前检查其有效性

4. 指针运算

4.1指针+-整数

*vp++意思是先*vp;再vp++也就是说是对指针地址的++

(*vp)++意思是对解引用的内容进行++

#define N_VALUES 5
   float values[N_VALUES];
   float *vp;
   //指针+-整数;指针的关系运算
   for (vp = &values[0]; vp < &values[N_VALUES];){
     *vp++ = 0;
}

4.2指针-指针

int my_strlen(char *s) {
       char *p = s;
       while(*p != '\0' )
              p++;
       return p-s;
}

指针减去指针得到的绝对值是指针和指针之间元素的个数,不是所有指针都能相减,指向同一块空间的指针才能相减。

5. 指针和数组

数组名表示的是数组首元素的地址
我们可以直接通过指针来访问数组
int main()
{
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    int *p = arr; //指针存放数组首元素的地址
    int sz = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    for (i = 0; i<sz; i++){
        printf("%d ", *(p + i));
  }
    return 0; 
}

6. 二级指针

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
这就是 二级指针
int main(){
    int a = 10;
    int *pa = &a;
    int **ppa = &pa;
  return 0;
}
对于二级指针的运算有:
*ppa 通过对 ppa 中的地址进行解引用,这样找到的是 pa *ppa 其实访问的就是 pa
**ppa 先通过 *ppa 找到 pa , 然后对 pa 进行解引用操作: *pa ,那找到的就是 a .

7. 指针数组

指针数组指的是存放指针的数组

int* arr3[5];

arr3就是一个指针数组,有五个元素,每个元素都是一个整形指针

二、结构体

1.结构体类型的声明

1.1结构的基础知识

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

1.2结构的声明

struct tag
{
 member-list; //中间可以有多个、多种类型
}variable-list;

1.3结构成员的类型

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

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

2.1结构体变量的定义

struct Point {
       int x;
       int y;
}p1    //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2

2.2初始化

//初始化:定义变量的同时赋初值。
struct Point p3 = {x, y};
struct Stu        //类型声明
{char name[15];//名字
 int age;      //年龄
};
struct Stu s = {"zhangsan", 20};//初始化
struct Node
{
 int data;
 struct Point p;
 struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化

3.结构体成员访问

结构体变量访问成员结构变量的成员是通过点操作符(.)访问的 。
struct Stu
{
 char name[20];
 int age;
};
struct Stu s;
strcpy(s.name, "zhangsan");//使用.访问name成员
s.age = 20;//使用.访问age成员

而结构体变量指针用点操作符(->) 访问。

struct Stu
{
 char name[20];
 int age;
};
void print(struct Stu* ps) {
 printf("name = %s   age = %d\n", (*ps).name, (*ps).age);
    //使用结构体指针访问指向对象的成员
 printf("name = %s   age = %d\n", ps->name, ps->age);
}

4.结构体传参

struct S {
 int data[1000];
 int num;
};
struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s) {
 printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps) {
 printf("%d\n", ps->num);
}
int main()
{
 print1(s);  //传结构体
 print2(&s); //传地址
 return 0; 
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值