入门学习计算机第十三天—初识指针

本文介绍了C语言中的指针概念,包括指针的定义、类型、运算以及指针与数组的关系。讲解了指针作为变量存储地址的特性,指针类型对解引用操作的影响,以及指针运算中的步长问题。同时,讨论了野指针的成因及避免方法,并通过实例展示了如何使用指针操作数组和字符串。最后,提到了二级指针和指针数组的概念。
摘要由CSDN通过智能技术生成

入门学习计算机第十三天—初识指针

编译器:Microsoft Visual Studio 2010

前言 记录第十三天学习C语言的博客。

1、指针是什么

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

内存地址
一个字节0xFFFFFFFF
一个字节0xFFFFFFFE
一个字节0x00000004
一个字节0x00000003
一个字节0x00000002
一个字节0x00000001
一个字节0x00000000
int main()
{
  int a = 10;//在内存开辟一块空间
  int* p = &a;//这里取出变量a的地址,可以使用&取地址操作符
              //将a的地址存放在p变量中,p就是一个指针变量
  return 0;
}

总结: 指针就是变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)
指针变量的大小在32位机器上是4个字节,64位机器上是8个字节。

2、指针和指针类型

int main()
{
   printf("%d\n",sizeof(char*));
   printf("%d\n",sizeof(short*));
   printf("%d\n",sizeof(int*));
   printf("%d\n",sizeof(double*));

  return 0;
}

输出的结果都是4。

大小都是一样的,为什么还要对指针的类型进行区分?

int main()
{
   int a = 0x11223344;
   int* pa = &a;
   //char* pc =&a;
   *pa = 0;
   //*pc = 0;
   
}

在VS2010编译器下,char* pc = &a;会进行报错。所以在兼容性不高的编译器下,使用错误的指针类型会导致代码无法正常运行

在VS2013编译器下,

int* pa = &a;
char* pc =&a;

会存储相同的值(a的地址)。

 *pa = 0;
 *pc = 0;

但在解应用时,a的值修改不一样。在调试状态下,打开内存监视窗口。
可以看出*pa = 0,修改的是四个字节的值
在这里插入图片描述

而 *pc修改的只是一个字节的值。
在这里插入图片描述

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

int* p//能够访问4个字节
char* p//能够访问1个字节
double* p//能够访问8个字节

所以指针类型的使用,一定要正确!!

调试状态下,调试无内存窗口选项解决方法

指针±整数

int main()
{
    int a = 0x11223344;
    int* pa = &a;
    char* pc = &a;
    printf("%p\n",pa);
    printf("%p\n",pa+1);
    printf("%p\n",pc);
    printf("%p\n",pc+1); 
}

输出的结果是
0095FB58
0095FB5C
0095FB58
0095FB59
58->5C 跳过了4个字节,58->59跳过了1个字节。
所以当指针类型不同,指针±整数,跳过的字节数不同。
指针类型决定了:指针走一步走多远(指针的步长)

野指针

概念:野指针就是指针指向的位置是不可知的。(随机的、不正确的、没有明确限制的)

野指针成因:
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;//超过了数组的范围
   }
  return 0;
}

3、指针指向的内存空间释放

int* text()
{
   int a =10;
   return &a;
}

int main()
{
    int* p = test();
    *p =20;
    return 0;
}

当&a的值返回给p时,函数内部已经被销毁,地址已经还给了系统,虽然p存了a的地址,但当*p解引用时,访问的空间已经不再是之前存储a的空间。


如何避免野指针
1、指针初始化

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

2、小心指针越界
3、指针指向空间释放即使置NULL

int main()
{
   int a = 10;
   int* pa = &a;
   *pa = 20;
   pa = NULL;//不指向a,不指向任何有效的空间
   return 0;
}

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


2、指针的运算

  • 指针±整数
  • 指针±指针
  • 指针的关系运算

指针±整数

int main()
{
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  int i = 0;
  int sz =sizeof(arr)/sizeof(arr[0]);
  int* p = &arr;
  for(i = 0; i< 5;i++)
  {
   printf("%d\n", *p);
     p = p + 1}
  return 0;
}

输出的值是1,2,3,4,5,6,7,8,9,10

指针±指针

int main()
{
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 printf("%d\n", &arr[9] - &arr[0]);
  return 0;
}

输出的结果是9,所以在两个指针之间的元素个数。

!!!指针相加减的运算,指针一定要是指向同一块空间。


int main()
{
  char ch[5] = {0};
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
 printf("%d\n", &arr[9] - &ch[5]);
  return 0;
}

在这里插入图片描述

这种就是错误的写法,结果是不可预知的。

例子:
不用strlen函数,并且用指针的方式求出字符串的长度

int my_strlen(char* str)
{
  char* start = str;
  char* end = str;
  while(*end !='\0')
  {
     end++;
  }
   return end - start;
}
int main()
{
  char arr[] = "GPUNNB!";
  int len = my_strlen(arr);
  printf("%d\n",len);
   return 0;
}

输出的结果是7。

指针的关系运算

指针的大小比较,相等或者不等于。

#define N_VALUES 5
float values[N_VALUES]
float *vp
for(vp = &values [N_VALUES]; vp>&values[0];)
{
  *--vp = 0;
}

上述代码简化:

for(vp = &values [N_VALUES]; vp>=&values[0];vp-- )
{
   *vp = 0;
}

但是推荐写第一种方式,因为:
标准规定
允许指向数组的元素与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前那个位置的指针进行比较。

3、指针和数组

数组名是什么?
首元素的地址

int main()
{
   int arr[10] = {0};
   printf("%p\n",arr);
   printf("p\n",arr[0]);
   //1、&arr- &数组名- 数组名不是首元素地址-数组名表示整个数组-&数组名 取出的是整个数组的地址
   //2、sizeof(arr)-sizeof(数组名)-数组名表示整个数组-sizeof(数组名) 计算是整个数组的大小
  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("%d ",*(p+i));
   }
   return 0; 
}

输出的结果是0,1,2,3,4,5,6,7,8,9

3、二级指针

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
对指针变量进行取地址,并存储在另一个指针变量中,这就是二级指针

int main()
{
  int a = 10;
  int* pa = &a;
  int** ppa = &pa;//ppa就是二级指针
  **ppa = 20;
  printf("%d\n",**ppa);
  printf("%d\n",a);
  return 0;
}

输出的结果是
20
20

指针数组
本质是数组,存放指针的数组

int mian()
{
   int a = 10;
   int b = 20;
   int c = 30;
   int* arr[3] = {&a,&b,&c};//指针数组
   int i =0;
   for(i=0; i<3; i++)
   {
     printf("%d",*(arr2[i]));
   }
   return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值