美文网首页
C语言指针初探

C语言指针初探

作者: 奥尔良小短腿 | 来源:发表于2017-09-25 14:30 被阅读39次

什么是指针?

指针其实也是一个变量,指针变量跟普通变量的区别就是,普通变量存储的是一个具体的值,而指针变量存储的是一个变量在内存中的地址(也可以说是这个指针指向某个变量在内存中的内存空间的首地址).

指针的声明及使用

指针声明的格式:
指针类型 *指针变量名称 = 指针指向变量的地址;

// 声明一个int类型的变量并赋值为10
int a = 10;

// 声明一个int类型的指针变量,指向int类型的变量a的地址
int *ptr1 = &a;

printf("%d\n",*ptr1); // 输出的结果为10 跟 变量a的值一致
printf("%p\n",ptr1);  // 输出的是指针的存储值(也就是变量a的地址) 类似0x7fff5fbff7b4
printf("%p\n",&ptr1); // 输出的是指针变量本身的地址(每个变量都有一个地址,包括指针变量) 类似0x7fff5fbff7a8

// 可以先声明指针变量,再赋值
int *ptr2; // 默认值为NULL
ptr2 = &a;
printf("%d\n",* ptr2); // 输出的结果为10

// 直接操作内存地址存储的值(游戏外挂就会用到)
int a = 10; // a在内存中的地址 0x7fff5fbff7bc
int *p = 0x7fff5fbff7bc; // 直接把a的地址赋值给指针p
*p = 100; // 修改p指向地址的值
printf("a = %d\n", a); // 100;
    

空指针

值为NULL的指针变量就叫空指针

int *ptr = NULL; 

printf("%p\n",ptr);  // 结果0x0
printf("%d\n",*ptr); // 会发生运行时错误
printf("%p\n",&ptr); // 指针变量就算是空指针但是它本身是有地址的 0x7fff5fbff7b0

野指针

指向的是"垃圾"内存(不可用内存)的指针变量叫做野指针

char *ptr = NULL;
    
printf("ptr:%d\n", ptr); // ptr:0
printf("ptr地址:%p\n", &ptr); // ptr地址:0x7fff5fbff7a8
    
if (ptr == NULL) {
    printf("ptr == NULL \n");
} else {
    printf("ptr != NULL \n");
}
// 输出为"ptr == NULL"
    
// 为ptr在堆区分配空间
ptr = (char *)malloc(100);
if (ptr == NULL) { // 若为空直接return出程序
    return;
}
printf("ptr:%d\n", ptr); // ptr:2106560
printf("ptr地址:%p\n", &ptr); // ptr地址:0x7fff5fbff7a8
    
if (ptr != NULL) { // 目的:释放ptr
    free(ptr); // 只释放了ptr指向的堆区空间  并没有将指针ptr置为空
}
    
if (ptr == NULL) {
    printf("ptr == NULL \n");
} else {
    printf("ptr != NULL \n");
}
// 输出为"ptr != NULL"
    
printf("ptr:%d\n", ptr); // ptr:2106560
printf("ptr地址:%p\n", &ptr); // ptr地址:0x7fff5fbff7a8

野指针解决办法

char *ptr = NULL;
    
printf("ptr:%d\n", ptr); // ptr:0
printf("ptr地址:%p\n", &ptr); // ptr地址:0x7fff5fbff7a8
    
if (ptr == NULL) {
    printf("ptr == NULL \n");
} else {
    printf("ptr != NULL \n");
}
// 输出为"ptr == NULL"
    
// 为ptr在堆区分配空间
ptr = (char *)malloc(100);
if (ptr == NULL) { // 若为空直接return出程序
    return;
}
printf("ptr:%d\n", ptr); // ptr:2106560
printf("ptr地址:%p\n", &ptr); // ptr地址:0x7fff5fbff7a8
    
if (ptr != NULL) { // 目的:释放ptr
    free(ptr); // 只释放了ptr指向的堆区空间  并没有将指针ptr置为空
    ptr = NULL; // 重置为NULL
}
    
if (ptr == NULL) {
    printf("ptr == NULL \n");
} else {
    printf("ptr != NULL \n");
}
// 输出为"ptr == NULL"
    
printf("ptr:%d\n", ptr); // ptr:0
printf("ptr地址:%p\n", &ptr); // ptr地址:0x7fff5fbff7a8

如果防止野指针

  • 养成良好习惯,定义指针的同时赋值初始值为NULL
  • 在指针指向的内存空间释放的同时把指针重置为NULL

多级指针(指向指针的指针)

指向指针的指针就叫做多级指针,指针的级数并没有限制,可以无限的指向下去,只是指针的*要与指针的级数一致.

int a = 10;

// 1级指针
int *p = &a; 
printf("%d\n", *p); // 指针p 指向的变量a的值 10
printf("%p\n", p);  // 指针p 指向变量的地址 0x7fff5fbff7bc
printf("%p\n", &p); // 指针p 本身的地址 0x7fff5fbff7b0

// 2级指针   
int **p1 = &p; 
printf("%d\n", **p1); // 指针p1 指向的指针变量p所指向的变量的值 10 p1->p->a 几级指向就用几个*符来取值
printf("%p\n", p1);   // 指针p1 指向指针变量p的地址 0x7fff5fbff7b0
printf("%p\n", &p1);  // 指针p1 本身的地址 0x7fff5fbff7a8

// 3级指针
int ***p2 = &p1; 
printf("%d\n", ***p2);  // 指针p2 指向指针变量p1所指向的指针变量p所指向的变量的值 10 p2->p1->p->a 几级指向就用几个*符来取值
printf("%p\n", p2);     // 指针p2 指向指针变量p1的地址 0x7fff5fbff7a8
printf("%p\n", &p2);    // 指针p2 本身的地址 0x7fff5fbff7a0


指针运算

指针指向的地址是用一个十六进制的数来表示的,因此指针是可以进行运算的.
当对指针变量进行++ -- + - 的时候其实是在对指针指向的地址进行偏移,偏移的量是取决于变量的类型与跟指针变量发生运算的数据相关,在数组中特别明显.
如:一个指向int类型变量的一个指针 + 1, 得到的结果并不是在地址上偏移一位,而是偏移了sizeof(int) * 1 位,减法向低位偏移.

int a = 10;
int *p = &a;
    
printf("%d\n", *p); // 输出指针所指向变量的值 10
printf("%p\n", p);  // 输出指针所指向的地址 0x7fff5fbff7bc
    
printf("%d\n", *p + 1); // 在指针p所指向变量的值上+1  11
printf("%p\n", p + 1);  // 在指针p所指向变量的地址上+1(指针向高位偏移了指针类型所占字节 * 1 个位置) 0x7fff5fbff7c0

指针与const修饰符

指针能否修改取决于 const 所加位置以及所指向的变量的类型

int a = 10;
int b = 20;

// *前const
int const*p = &a; // const int *p 一样
p = &b; // p指向的地址可以修改
*p = b; // p指向地址的值不可以修改 会报错
    
// *后const
int * const p1 = &a;
p1 = &b; // p1指向的地址不可以修改 会报错
*p1 = b; // p1指向的地址的值可以修改

// *前*后const
const int * const p2 = &a;
p2 = &b; // 会报错
*p2 = b; // 会报错

// 指向const修饰的变量
const int a = 10;
int *p3 = &a;
*p3 = 100;

printf("%d\n",*p3); // 100
printf("%d\n",a);   // 10

printf("p3 = %p\n",p3); // p3 = 0x7fff5fbff7bc
printf("&a = %p\n",&a); // &a = 0x7fff5fbff7bc

指向数组的指针

指向字符串的指针

指向函数的指针

函数指针就是一个指向函数首地址的指针

void exchangeVar(int *a, int *b) {
    
    int temp = *a;
    *a = *b;
    *b = temp;
    
}

int a = 10;
int b = 20;
// 定义一个函数指针,指向exchangeVar函数的首地址
void(*pfun)() = &exchangeVar;
(*pfun)(&a,&b);

printf("a = %d b = %d", a,b); // a = 20 b = 10

高阶函数 - (函数中传入函数)

void print_num(num) {
    printf("%d\n", num);
}

void test(void(*pfunc)(), int n) {
    printf("前面的观众!\n");
    (*pfunc)(n);
    printf("后面的观众!\n");
}

test(&print_num, 1233);

/* 输出结果
前面的观众!
1233
后面的观众!
*/

函数指针数组

void fun1() {
    printf("fun1()\n");
}
void fun2() {
    printf("fun2()\n");
}
void fun3() {
    printf("fun3()\n");
}

void(*pFunc1)() = &fun1;
void(*pFunc2)() = &fun2;
void(*pFunc3)() = &fun3;
    
//接下来就是定义一个数组把他们三个装进去。
void(*pFunArr[3])();
    
//在这里呢看着个指针数组,他就是一个具有3个以函数指针为内容的元素的函数指针数组。
pFunArr[0] = pFunc1;
pFunArr[1] = pFunc2;
pFunArr[2] = pFunc3;
    
pFunArr[0](); // 调用结果 fun1()
pFunArr[1](); // 调用结果 fun2()
pFunArr[2](); // 调用结果 fun3()

指向函数指针数组的指针

void (*(*pFunarr2)[3])() = &pFunArr;
(*pFunarr2)[0]();
(*pFunarr2)[1]();
(*pFunarr2)[2]();

指针在函数中的使用

在函数的参数处使用指针可以修改传入实参本身的值.

// 交换两个变量的值
void exchangeVar(int *a, int *b) {
    
    int temp = *a;
    *a = *b;
    *b = temp;
    
}

int main(int argc, const char * argv[]) {
   
    int a = 10;
    int b = 20;
    
    printf("a:%d\n", a); // 10
    printf("b:%d\n", b); // 20
    
    // 调用函数进行交换
    exchangeVar(&a, &b);
    
    printf("a:%d\n", a); // 20
    printf("b:%d\n", b); // 10
    
    return 0;
}

相关文章

  • C语言指针初探

    什么是指针? 指针其实也是一个变量,指针变量跟普通变量的区别就是,普通变量存储的是一个具体的值,而指针变量存储的是...

  • c初探:数据类型、格式化、数组与指针

    c初探:数据类型、数组、内存布局、指针 C 语言教程-RUNOOB.COM C++ 教程-RUNOOB.COM C...

  • C语言05- 指针

    C语言05- 指针 13:指针 指针是C语言中的精华,也是C语言程序的重点和难点。 13.1:指针定义与使用 指针...

  • 02-C语言的指针

    02-C语言的指针 目标 C语言指针释义 指针用法 指针与数组 指针与函数的参数 二级指针 函数指针 指针在C中很...

  • C语言指针总结大学霸IT达人

    C语言指针总结大学霸IT达人 C语言的指针是C语言区别其它语言的最主要的特定之一。有了指针,C语言就可以抛开所有束...

  • 带小白学C语言指针

    C语言里指针才是C语言的开始和指针;C语言里基本所有东西都是由指针演变而成; 指针是指向地址的变量,类型就是指针...

  • 在Swift中使用C语言的指针

    在Swift中使用C语言的指针 在Swift中使用C语言的指针

  • [Swift]结构体指针操作

    C语言的指针操作 在c语言中申明一个变量并通过指针修改该变量的值 a value is 2 c语言操作结构体指针操...

  • Go语言-指针

    Go语言中的指针不同于C语言,Go语言的指针使用方法要简单很多。当然和C语言从指针定义到指针的使用都有很大的不同。...

  • C语言中的指针与数组

    C语言中的指针与数组 @(C语言)[排序算法, 快速排序, C实现] 引言 相信指针与数组是不少同学在初学C语言时...

网友评论

      本文标题:C语言指针初探

      本文链接:https://www.haomeiwen.com/subject/pwirextx.html