【C】Re05 指针
一、变量 & 指针
变量 = 内存地址 + 存储值
指针变量 = 内存地址 + 存储值【变量的内存地址】
作用: 间接访问内存地址
内存地址 = 地址编号
地址编号:内存中的每个字节唯一的编号,从0开始记录,使用十六进制显示
可以使用指针变量存储变量的地址
不同数据类型就有对应的指针的数据类型
二、使用
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h> void pointer () {
// 指针变量
int * pointer;
// 变量
int varA = 100; printf("pointer -> x16 %x, x10 %d, x8 %o\n", pointer, pointer, pointer);
printf("varA -> %d\n", varA); printf("- - - - - - - - - - - - - - -\n"); // 把varA的地址赋值给指针变量pointer
pointer = &varA;
// 通过指针变量pointer取地址访问varA变量
*pointer = 20; printf("pointer -> x16 %x, x10 %d, x8 %o\n", pointer, pointer, pointer);
printf("varA -> %d\n", varA);
} int main() {
pointer();
return EXIT_SUCCESS;
}
输出格式注意:
// %p显示完整十六进制位数, %x只显示进制数
语法递进:
int tf = (*pointer == *&varA); // 0 false, 1 true
int tf2 = (pointer == &varA);
int tf3 = (*pointer == varA); printf(" %d\n",tf);
printf(" %d\n",tf2);
printf(" %d\n",tf3);
三、空指针& 野指针
空指针定义
void nullPointerAndWildPointer () {
// 定义一个空指针
int * nullPointer = NULL;
}
指向的NULL常量来自于STDLIB标准库头文件的这一段
#else
#define NULL ((void *)0)
#endif
#endif
最后指向的还是一个0而已
void nullPointerAndWildPointer () {
// 定义一个空指针
int * nullPointer = 0;
}
实际上不建议直接写0,容易混淆指针变量与变量
空指针不能被访问到:
void nullPointerAndWildPointer () {
// 定义一个空指针
int * nullPointer = NULL;
printf("nullPointer -> %p", *nullPointer);
} int main() {
nullPointerAndWildPointer();
return EXIT_SUCCESS;
}
因为内存地址编号0 - 255已经被操作系统占用了
空指针的作用:
不知道应该对指针定义多少合适时使用
野指针定义:
void nullPointerAndWildPointer () {
int * wildPointer = 0xffff;
printf("wildPointer -> %p\n", *wildPointer);
}
指针变量存储了非法的、未知的一个内存地址,该地址存储的内容将无法访问
但是允许查看地址
void nullPointerAndWildPointer () {
// 定义一个空指针
// int * nullPointer = NULL;
// printf("nullPointer -> %p\n", *nullPointer); // 定义一个野指针
// int * wildPointer = 0xffff;
// printf("wildPointer -> %p\n", *wildPointer); int * nullPointer = NULL;
printf("nullPointer -> %p\n", nullPointer); int * wildPointer = 0xffff;
printf("wildPointer -> %p\n", wildPointer);
} int main() {
nullPointerAndWildPointer();
return EXIT_SUCCESS;
}
野指针的第二种情况:
也是一样,地址可以访问,但是内部存储的值无法访问
// 野指针的第二种情况
int * wildPointer2;
printf("wildPointer2 -> %p\n", wildPointer2);
// printf("wildPointer2 value -> %d\n", *wildPointer2);
四、无类型指针 和 万能指针
1、Void类型概述
void voidUsage() {
// void 是一个数据类型,所以也具备对于的指针类型 void *
// void 的用途是修饰函数返回类型和形参类型
} // 形参修饰了void 表示 该函数不需要参数
void noNeedParam( void ) { }
2、函数返回类型省略
当函数的返回值类型声明的是void时,我们可以省略,不需要return
不过不建议这样书写,C++并不支持这样的语法
aaa () {
printf("void返回类型省略的函数调用!!!");
} int main() {
aaa();
return EXIT_SUCCESS;
}
如果函数不需要注入任何类型的参数,编写时是可以明确标注void 数据类型即可
3、无类型指针与万能指针:
无类型指针可以强转任意类型接收对于的类型的变量地址
void noTypePointer() {
void * p = NULL;
printf("sizeof p = %d\n", sizeof(p)); // 64位 sizeof p = 8 32位 sizeof p = 4 int num = 10;
p = #
// printf("p = %d\n", *p); int指针类型赋值给void指针类型, 类型不匹配错误
// 使用强转来转换指针类型
printf("p = %d\n", *(int *)p);
}
另外可以作为万能指针使用:
void anyTypePointer() { void * pointer = NULL; int * varA = NULL;
char * varB = NULL; // 一个是int指针类型一个是char指针类型,直接这样赋值不会有语法错误提示
// 但是在编译执行时会有警告提示,另外,如果指针调用了就会报错。。。
// varA = varB;
// 所以需要强转处理
varA = (int *)varB; // void*指针类型的指针可以赋值给任何指针类型,不需要强转【自动转换?】
varA = pointer;
} // 因为void*指针类型 第二用,作为参数类型
void function ( void * sss) { }
五、Const修饰指针变量
void constWithPointer() {
// 1、const修饰的是*, *p 是只读的, p可读可写的
int varA = 100;
const int * pToVarA = &varA; // 如何判断是修饰* 还是 p? 看*还是p靠前,和const近, 等同于 int const * pToVarA = &varA;
// *pToVarA = 20; 不允许访问地址写入了 printf("pointer -> %p\n", pToVarA); int varB = 200;
pToVarA = &varB; // 更改赋值地址是允许的 printf("pointer -> %p\n", pToVarA); // 总结下来就是:指针指向地址的存储值不可以改变,指向地址可以改变 // -------------------------------------------------------------- // 2、const修饰的是p, p 是只读的, *p可读可写的
int c = 150; // 语法
int * const p = &c; // 可以对指向地址的存储值进行写入更改
*p = 20;
// p = &varA; 但是不再允许指向其他地址了 // 指针指向地址的存储值可以修改,但是指针的指向地址不可以修改 // -------------------------------------------------------------- // 3、const修饰的是*和p, *和p都是只读的
int d = 120;
int const * const p2 = &d;
// p2 = &c; 更改指向 不允许
// *p2 = 230; 更改存储值 不允许
} int main() {
constWithPointer();
return 0;
}
六、不同指针类型的区别?
void differFromPointers() {
char * p1 = NULL;
int * p2 = NULL;
double * p3 = NULL; printf("p1 -> %p\n", p1);
printf("p2 -> %p\n", p2);
printf("p3 -> %p\n", p3); // 区别1 不同指针类型 叠加字面值的步长不一样,这取决于他们的数据类型长度
printf("p1 + 1 -> %p\n", p1 + 1); // char指针类型向前移动一个字节
printf("p2 + 1 -> %p\n", p2 + 1); // int指针类型向前移动4个字节
printf("p3 + 1 -> %p\n", p3 + 1); // 区别2 解引用的字节数量也不一样,取到的值也就不一样
int num = 0x01020304; // int num = 0x01020304; int num = 0x21348903;
int * p4 = #
printf("*p4 -> %#x\n", *p4); // *p4 -> 0x1020304 short * p5 = #
printf("*p5 -> %#x\n", *p5); // *p5 -> 0x304 char * p6 = #
printf("*p6 -> %#x\n", *p6); // *p5 -> 0x304
} int main() {
differFromPointers();
return 0;
}
【C】Re05 指针的更多相关文章
- TODO:Golang指针使用注意事项
TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...
- enote笔记法使用范例(2)——指针(1)智能指针
要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...
- C++虚函数和函数指针一起使用
C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...
- C++11 shared_ptr 智能指针 的使用,避免内存泄露
多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...
- c 数组与指针的使用注意事项
数组变量和指针变量有一点小小的区别 所以把数组指针赋值给指针变量的时候千万要小心 加入把数组赋值给指针变量,指针变量只会包含数组的地址信息 而对数组的长度一无所知 相当于指针丢失了一部分信息,我们把这 ...
- Marshal.Copy将指针拷贝给数组
lpStatuss是一个UNITSTATUS*的指针类型实例,并包含SensorDust字段 //定义一个数组类型 byte[] SensorDust = new byte[30] //将指针类型拷贝 ...
- C++智能指针
引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...
- EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针
一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...
- 智能指针shared_ptr的用法
为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...
- 智能指针unique_ptr的用法
unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...
随机推荐
- 使用 Hugging Face 推理终端搭建强大的“语音识别 + 说话人分割 + 投机解码”工作流
Whisper 是当前最先进的开源语音识别模型之一,毫无疑问,也是应用最广泛的模型.如果你想部署 Whisper 模型,Hugging Face 推理终端 能够让你开箱即用地轻松部署任何 Whispe ...
- if语句嵌套
// if语句的嵌套 // 在if语句的{}中,执行程序中,再次有if语句 /* if(){ if(){ ...
- ETL工具-nifi干货系列 第一讲 揭开nifi神秘面纱
1.nifi简介 Apache NiFi 是基于流程编程概念的数据流系统.它支持强大且可扩展的数据路由.转换和系统中介逻辑的有向图.NiFi具有基于Web的用户界面,用于设计.控制.反馈和监控数据流. ...
- k8s介绍
k8s容器编排系统 k8S是谷歌几十年来研发的一套系统,更新了运维领域的玩法. 内容很多,先快速练习玩法,知道是什么就行. 具体[为什么]再花时间慢慢学吧! 0.参考资料 1. k8s能干什么 htt ...
- Apollo启动配置排查,超时时间的配置
Apollo启动配置排查 1.排查下来是 本地的服务 apollo 配置fake发布到线上去了.2.或者是引用的apollo jar包中指向的apollo服务器地址是否正确. 3.超时时间的配置 ## ...
- post请求 restTemplate.postForObject restTemplate.postForEntity java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to xxx POSTpost请求
1.restTemplate调用的两种方式及获取字符串转换对象model的处理,统一按接收字符串,然后gson转换为对象的方式. ResponseData对象包含的属性private String r ...
- .htaccess伪静态规则
Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` .htaccess伪静态规则 日期:2017-12-4 阿 ...
- gerrit权限控制
gerrit权限控制 背景 在公司中使用到了Gerrit作为技术管理,在配置的时候发现一些问题:转载了这篇文章作为学习. 正文开始 原文链接:https://blog.csdn.net/chenjh2 ...
- Freertos学习:05-内核控制
--- title: rtos-freertos-05-kernel-control date: 2020-06-22 11:10:19 categories: tags: - kernel - fr ...
- 算法金 | Transformer,一个神奇的算法模型!!
大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 抱个拳,送个礼 在现代自然语言处理(NLP)领域,Transformer 模型的出现带 ...