【C语言】指针概要

简介: 【C语言】指针概要

一、什么是指针

指针就是地址,口语中说的指针通常指的是指针变量。我们可以通过&(取地址操作符)取出变量的内存起始地址,把地址可以存放到一个变量中,这个变量就是指针变量。

一个指针变量多大?

  • 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。
  • 那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。

二、指针类型

指针的定义方式是: **type + ***

char* 类型的指针是为了存放 char 类型变量的地址。

short* 类型的指针是为了存放 short 类型变量的地址。

int* 类型的指针是为了存放 int 类型变量的地址。

指针类型有什么意义呢?

1. 指针的类型决定了指针向前或者向后走一步有多大(距离)。

int main()
{
 int n = 10;
 char *pc = (char*)&n;
 int *pi = &n;
 printf("%p\n", &n);
 printf("%p\n", pc);
 printf("%p\n", pc+1);
 printf("%p\n", pi);
 printf("%p\n", pi+1);
 return  0;
}

由运行结果可以看出,char型指针加1向后走了1个字节,int型加1向后走了4个字节。

2. 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。

#include <stdio.h>
int main()
{
 int n = 0x11223344;
 char *pc = (char *)&n;
 int *pi = &n;
 *pc = 0;   //观察执行这两句时内存的变化
 *pi = 0;   
 return 0;
}

由结果可看出char* 的指针解引用只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。

三、野指针

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

野指针出现的原因:

  1. 指针未初始化
#include <stdio.h>
int main()
{ 
 int *p;//指针未初始化,默认为随机值
 return 0;
}
  1. 指针越界访问
#include <stdio.h>
int main()
{
    int arr[10] = {0};
    int *p = arr;
    int i = 0;
    for(i=0; i<=11; i++)
   {
        //当指针指向的范围超出数组arr的范围时,p就是野指针
        *(p++) = i;
   }
    return 0;
}
  • 指针指向的空间释放

四、二级指针

指针变量也是变量,是变量就有地址,指针变量的地址被称为二级指针。

  • *pp 通过对pp中的地址进行解引用,这样找到的是 pa, *pp 其实访问的就是 p .
  • **pp 先通过 *pp 找到 p ,然后对 p 进行解引用操作: *p ,那找到的是 a

五、字符指针

在指针的类型中我们把char*这种指针类型称为为字符指针

char str1[]="Hellow world";
char str2[]="Hellow world";
const char* str3="Hellow world";
const char* str4="Hellow world";

字符指针的一般使用方式为:

int main()
{
 char ch = 'w';
 char *pc = &ch;
 *pc = 'w';
 return 0;
}

还有另一种使用方式为:

int main()
{
 const char* pstr = "hello world.";//这一句代码意思是将首字符的地址放在了patr上,而不是把字符串
 printf("%s\n", pstr);
 return 0;
}

六、数组指针

定义

  • 指针数组:存放指针的数组
  • 数组指针:存放数组的地址
int* p1[10];//指针数组
int(*p2)[10];//数组指针

对于int* (p2) [10]

解释:p先和结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。

这里要注意:[ ] 的优先级要高于 * 号的,所以必须加上()来保证p先和 * 结合。

数组名

int arr[10];

数组名通常表示数组首元素地址,两个情况例外:

  1. sizeof(数组名)
  2. &数组名
    这两种情况数组名表示整个数组
#include <stdio.h>
int main()
{
 int arr[10] = { 0 };
 printf("arr = %p\n", arr);
 printf("&arr= %p\n", &arr);
 printf("arr+1 = %p\n", arr+1);
 printf("&arr+1= %p\n", &arr+1);
 return 0;
}

从程序运行结果可以看出&arr和arr,虽然值是一样的,但是意义却不一样。

&arr 表示的是数组的地址,而不是数组首元素的地址

&arr 的类型是: int(*)[10] ,是一种数组指针类型

数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40

七、函数指针

#include <stdio.h>
void test()
{
 printf("Hwllow world");
}
int main()
{
 printf("%p\n", test);
 printf("%p\n", &test);
 return 0;
}

可以看出函数名也表示函数的地址,与&函数名一样,那么函数的地址存储到指针中应该如何表示呢

回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

目录
相关文章
|
23小时前
|
存储 编译器 程序员
从C语言到C++④(第二章_类和对象_上篇)->类->封装->this指针(下)
从C语言到C++④(第二章_类和对象_上篇)->类->封装->this指针
4 0
|
1天前
|
存储 编译器 C语言
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose(下)
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose
7 0
|
1天前
|
C语言
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose(中)
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose
8 0
|
1天前
|
存储 数据库 C语言
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose(上)
C语言进阶⑱(文件上篇)(动态通讯录写入文件)(文件指针+IO流+八个输入输出函数)fopen+fclose
8 0
|
1天前
|
C语言
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror(下)
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror
5 0
|
1天前
|
安全 C语言
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror(中)
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror
11 0
|
1天前
|
C语言
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror(上)
C语言进阶⑬(字符串函数)+(指针编程题)strlen+strcpy+strcat+strstr+strtok+strerror
9 0
|
1天前
|
算法 C语言
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)(下)
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)
5 0
|
1天前
|
C语言
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)(中)
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)
11 0
|
1天前
|
C语言
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)(上)
C语言进阶⑫(指针下)(指针和数组笔试题解析)(杨氏矩阵)
11 0