当前位置: 首页> 健康> 知识 > 注册城乡规划师考试题型_永春网页设计_石家庄关键词优化平台_小学四年级摘抄新闻

注册城乡规划师考试题型_永春网页设计_石家庄关键词优化平台_小学四年级摘抄新闻

时间:2025/8/27 10:26:42来源:https://blog.csdn.net/2402_87467998/article/details/143438008 浏览次数:0次
注册城乡规划师考试题型_永春网页设计_石家庄关键词优化平台_小学四年级摘抄新闻

深入理解指针2

const修饰指针

当const修饰变量时,是无法更该该变量的值的

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{const int a = 10;//const常属性,不能改变的属性a = 1;printf("%d\n", a);return 0;
}

报错:
在这里插入图片描述
a变成了常变量,a的本质还是变量,但是因为被comst修饰,所以不能改变

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{const int n = 10;int arr[n];return 0;
}

报错:
在这里插入图片描述
n是变量,语法限制了n只是不能被修改

在c++中,const int n里的n就是常量

如果想改变用const修饰的变量的值:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{const int a = 10;int* p = &a;*p = 1;printf("%d", a);return 0;
}

但这是违反规则的,因为用const修饰的a是不期望被改变的

此时,如果改为:

 const int* p = &a;

则仍无法进行变量值的修改

const修饰指针变量

有两种形式:

 const int* p = &a;

此时const限制的是*p(指针指向的内容不能改变,但指针变量本身可以改变)

int* const p = &a;

此时const限制的是*p(指针变量本身不能被修改,但指针指向的内容可以通过指针变量改变)

野指针

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

成因:

指针未初始化:
 int* p;//局部变量不初始化的时候,里面放的是随机值*p = 20;//非法访问,p就是野指针
指针越界访问·
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = arr;int sz = sizeof(arr) / sizeof(arr[0]);int i = 0;for (i = 0;i <= sz;i++) {*p = i;p++;}return 0;
}

当循环到第十一次的时候,p指向了数组最后一个元素后面的空间

指针指向的空间释放
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int* test() {int n = 100;return &n;
}
int main()
{int* p = test();printf("%d", *p);return 0;
}

n所占的四个字节的空间,当函数test返回之后,n的空间就还给了操作系统

如何避免野指针

指针初始化

  • 如果指针变量有明确的指向,直接就给明确的地址:
 int a = 10;int* p = &a;
  • 如果指针变量当前还不知道应该指向哪里,只是应该初始化为NULL`
int* p = NULL;

NULL是C语言中定义的一个标识符常量,值是0,0也是地址,这个地址是无法使用的,读写该地址会报错

小心指针越界

指针变量不使用时,及时置NULL,指针使用之前检查其有效性

if (p != NULL)

避免返回局部变量的地址

assert断言

assert.h 头文件定义了宏 assert(),用于在运行时确保程序符合指定条件,如果不符合,就报错终止运行。这个宏常常被称为“断言”

 assert(p != NULL);

上面代码在程序运行到这一行语句时,验证变量p是否等于NULL.如果确实不等于NULL,程序继续运行,否则就会终止运行,并且给出报错信息提示:
在这里插入图片描述

assert()宏接受一个表达式作为参数。如果该表达式为真(返回值非零),assert()不会产生任何作用,程序继续运行。如果该表达式为假(返回值为零),assert()就会报错,在标准错误流 stderr中写入一条错误信息,显示没有通过的表达式,以及包含这个表达式的文件名和行号。

  • 使用assert()有几个好处:
    它不仅能自动标识文件和出问题的行号,还有一种无需更改代码就能开启或关闭assert()的机制。如果已经确认程序没有问题,不需要再做断言,就在#include <assert.h>语句的前面,定义一个宏 NDEBUG.
 #define NDEBUG #include <assert.h>

然后,重新编译程序,编译器就会禁用文件中所有的assert()语句。如果程序又出现问题,可以移除这条#define NDEBUG 指令(或者把它注释掉),再次编译,这样就重新启用了assert()语句

  • assert()的缺点
    因为引入了额外的检查,增加了程序的运行时间

一般我们可以在Debug 中使用,在Release 版本中选择禁用assert 就行,在vs 这样的集成开发环境中,在 Release 版本中,直接就是优化掉了。这样在debug版本写有利于程序员排查问题,在Release版本不影响用户使用时程序的效率

strlen的模拟实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char* str) {size_t count = 0;assert(str != NULL);while (*str) {count++;str++;}return count;
}
int main()
{char arr[] = "abcdef";size_t len = my_strlen(arr);printf("%zd", len);return 0;
}

传值调用和传址调用

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void Swap(int x, int y) {int z = 0;z = x;x = y;y = z;
}
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交换前:%d %d\n", a, b);Swap(a, b);//传值调用printf("交换后:%d %d", a, b);return 0;
}

不能实现交换:

在这里插入图片描述
实参传递给形参的时候,形参是实参的一份临时拷贝,对形参的修改不改变实参

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void Swap(int* pa, int* pb) {int z = 0;z = *pa;*pa = *pb;*pb = z;
}
int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交换前:%d %d\n", a, b);Swap(&a,&b);//传址调用printf("交换后:%d %d", a, b);return 0;
}

传址调用可以让函数和主调函数建立起真正的联系,在函数内部可以修改主调函数的变量,所以:
函数中只是需要主调函数中的变量值来实现计算,就可以采用传值调用,如果函数内部要修改主调函数中的变量的值,采用传址调用

END……

𖠚ᐝʜɪ Nᴏ̆̈ᴠ̆̈ᴇ̆̈ᴍ̆̈ʙ̆̈ᴇ̆̈ʀ̆̈🔅
所有热爱的事情都不要留余地
十一月你好💮️

关键字:注册城乡规划师考试题型_永春网页设计_石家庄关键词优化平台_小学四年级摘抄新闻

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: