alin的学习之路:C语言篇(二)(指针注意事项,数据存储方式,位运算)
@TOC(指针注意事项,数据存储方式,位运算)
1.空指针和野指针
不要操作野指针和空指针
空指针: 不要去操作空指针,对空指针指向的内存赋值等操作
void test01() {char* p = NULL;strcpy(p, "hello");//随便指向一个地址char* p = 0x12345678;strcpy(p, "hello"); } 结果: 报错
野指针:
指针变量未初始化
void test02() {int* p;*p = 10; } 结果: 报错
释放堆区的指针后未置空
void test03() {char* p = malloc(sizeof(char) * 64);strcpy(p, "hello world");printf("%s\n", p);free(p);printf("%s\n", p); } 结果: hello world 葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺葺 (乱码)
空指针可以free,野指针不能free
void test04() {char* p = malloc(sizeof(char) * 64);strcpy(p, "hello world");printf("%s\n", p);free(p);free(p); } 结果: 报错 void test04() {char* p = malloc(sizeof(char) * 64);strcpy(p, "hello world");printf("%s\n", p);free(p);p = NULL;free(p); } 结果: hello world
2.指针的步长
指针+1后向后跳的字节数量不同
void test01() {char* p1 = NULL;printf("%d\n", p1);printf("%d\n", p1+1);int* p2 = NULL;printf("%d\n", p2);printf("%d\n", p2 + 1);double* p3 = NULL;printf("%d\n", p3);printf("%d\n", p3 + 1);} 结果: 0 1 0 4 0 8
解引用取出的字节数量不同
void test02() {char buf[1024] = { 0 };int a = 1000;memcpy(buf+1, &a, sizeof(int));char* p = buf;printf("%d\n", *(int*)(p + 1)); } 结果: 1000
指针步长的练习
struct Person {char a;int b;char buf[64];int d; }; void test01() {struct Person p = { 'a',10,"hello world",1000 };struct Person* p1 = &p;printf("%d\n", offsetof(struct Person, d));printf("%d\n", &p);printf("%d\n", *(int*)((char*)p1 + offsetof(struct Person, d)) ); } 结果: 72 20184152 1000
3.指针的间接赋值
通过指针解引用和外部函数指针解引用完成间接赋值
void changeValue(int* p) {*p = 30; } void test01() {int a = 10;int* p = &a;*p = 20;printf("%d\n", a);int b = 20;changeValue(&b);printf("%d\n", b); } 结果: 20 30
通过解引用已确定的地址值进行间接赋值
默认VS中变量的地址值是随机的会变化的,通过进行设置可以使其固定不变
void test02()
{int a = 10;printf("%d\n", &a); //1703444*(int*)1703444 = 20;printf("%d\n", a);
}
结果:
1703444
20
5.指针做函数参数的输入输出特性
输入特性:主调函数分配内存,被调函数使用
//输入特性,主调函数分配内存,被调函数使用 void test01() {//栈上分配内存char buf[64] = {0};func1(buf);printf("%s\n", buf);}void printString(char* p) {printf("%s\n", p); } //堆上分配内存 void test02() {char* buf = malloc(sizeof(char) * 64);memset(buf, 0, 64);strcpy(buf, "hello world!!!");printString(buf); }
输出特性:被调函数分配内存,主调函数使用
//输出特性,被调函数分配内存,主调函数使用
void allocateSpace(char** pp)
{*pp = malloc(sizeof(char) * 64);memset(*pp, 0, 64);strcpy(*pp, "hello world???");
}
void test03()
{char* p = NULL;allocateSpace(&p);printf("%s\n", p);
}
6.一级指针易错点
指向堆区的指针移动后对其使用free 报错
//指向堆区的指针移动后对其使用free 报错
void test01()
{int* p = malloc(sizeof(int) * 5);int* pp = p;for (int i = 0; i < 5; ++i){*pp = i + 10;printf("%d\n", *pp);pp++;}free(p);p = NULL;
}
7.二级指针做函数参数的输入与输出特性
输入特性:
//二级指针做函数参数的输入特性 void printArray(int** arr, int len) {for (int i = 0; i < len; ++i){printf("%d\n", *arr[i]);} } void test01() {int** pArray = (int**)malloc(sizeof(int*) * 5);int a1 = 10;int a2 = 20;int a3 = 30;int a4 = 40;int a5 = 50;pArray[0] = &a1;pArray[1] = &a2;pArray[2] = &a3;pArray[3] = &a4;pArray[4] = &a5;int len = 5;printArray(pArray, len); } 结果: 10 20 30 40 50
//在栈上分配内存 void test02() {int* arr[5];for (int i = 0; i < 5; ++i){arr[i] = (int*)malloc(sizeof(int));*arr[i] = 100 + i;}int len = sizeof(arr) / sizeof(arr[0]);printArray(arr, len);for (int i = 0; i < len; ++i){free(arr[i]);arr[i] = NULL;} } 结果: 100 101 102 103 104
输出特性:
void allocateSpace(int** p) {int* temp = (int*)malloc(sizeof(int) * 5);for (int i = 0; i < 5 ;++i){temp[i] = i + 10;}*p = temp; } void printarray(int* arr, int len) {for (int i = 0; i < len; ++i){printf("%d\n", arr[i]);} } void freeallocate(int **pp) {free(*pp);*pp = NULL; } //输出特性 void test03() {int* p = NULL;allocateSpace(&p);printarray(p, 5);freeallocate(&p);p = NULL; } 结果: 10 11 12 13 14
8.数据的存取
存数据
- 无符号数据:原码 = 反码 = 补码
- 有符号数据
- 正数:原码 = 反码 = 补码
- 负数:
- 原码:高位是1代表是负数
- 反码:原码符号位不同,其余位取反
- 补码:反码+1
取数据
无符号取:原样的方式进行输出,对于八进制和十六进制,不要考虑正负
有符号取:
- 先看补码高位
- 高位是0:原码 = 反码 = 补码,原样输出数据
- 高位是1:原码 = 补码符号位不动其余位取反+1
- 先看补码高位
简单测试:
void test01() {char num = -15;printf("%d\n", num); //-15printf("%u\n", num & 0x000000ff); //241 }void test02() {char num = 0x9b;printf("%d\n", num); //-101printf("%x\n", num & 0x000000ff); //9bprintf("%u\n", num & 0x000000ff); //155 }
9.位运算
按位取反~
注意:做取反操作时包括符号位。
void test03()
{int num = 2;printf("%d\n", ~num); //-3int num2 = -2;printf("%d\n", ~num2); //1
}
按位与&
同真为真 其余为假
可用于判断奇偶性
void test04()
{int num = 777;if ((num & 1) == 1){printf("num是奇数\n");}else{printf("num是偶数\n");}
}
按位或|
同假为假 其余为真
用于让指定的位赋为1,在Linux下有些类似位图的数据可以使用|来进行指定属性的添加
void test06()
{int num = -100;printf("%d\n", num >> 4); //7
}
按位异或^
相同为假 不同为真
可用于两个变量值得交换
void test06()
{int a = 10;int b = 20;//方法一int temp = a;a = b;b = temp;printf("%d\n", a);printf("%d\n", b);//方法二a = a ^ b;b = a ^ b;a = a ^ b;printf("%d\n", a);printf("%d\n", b);//方法三a = a + b;b = a - b;a = a - b;printf("%d\n", a);printf("%d\n", b);
}
移位操作
左移<<N :相当于原数乘(2的N次方),左移低位补0
右移>>N :相当于原数除以(2的N次方)
- 无符号数:高位用0填充
- 有符号正数:高位用0填充
- 有符号负数:高位用1填充
void test07()
{int num = -100;printf("%d\n", num >> 2); //-25int num2 = -2;printf("%d\n", num2 << 2); //-8
}
移位操作
左移<<N :相当于原数乘(2的N次方),左移低位补0
右移>>N :相当于原数除以(2的N次方)
- 无符号数:高位用0填充
- 有符号正数:高位用0填充
- 有符号负数:高位用1填充
void test07()
{int num = -100;printf("%d\n", num >> 2); //-25int num2 = -2;printf("%d\n", num2 << 2); //-8
}
alin的学习之路:C语言篇(二)(指针注意事项,数据存储方式,位运算)相关推荐
- alin的学习之路(数据库篇:五)(MySQL的相关语句及API的C语言实现)
alin的学习之路(数据库篇:五)(MySQL的相关语句及API的C语言实现) 1. MySQL概述与登陆MySQL mysql 与 oracle 的区别 oracle 是一个数据库实例下有多个用户, ...
- alin的学习之路(数据库篇:二)(select查询,where条件查询,order by排序,单行函数,多行函数,group by分组)
alin的学习之路(数据库篇:二)(select查询,where条件查询,order by排序,单行函数,多行函数,group by分组) 1. SQL语句 1.1 sql语言类型 sql是一门独立的 ...
- alin的学习之路(数据库篇:三)(多表查询,子查询,集合运算,数据处理)
alin的学习之路(数据库篇:三)(多表查询,子查询,集合运算,数据处理) 1. 多表查询 1.1 笛卡儿积 笛卡尔积就是两个集合的乘积计算 . 如果多个表进行联合查询, 得到结果是一个笛卡尔积, 举 ...
- alin的学习之路:序列化与protobuf
alin的学习之路:序列化与protobuf 1. 序列化(串行化) 序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程,与之相对应的过程称之为反序列化(Unser ...
- 个人开发经历--我的java学习之路(学校篇)
个人开发经历--我的java学习之路(学校篇) 个人介绍: 姓名: 不在这里说明 联系信息: 个人历程 jdbc阶段 sql生成器 一代代码生成器 servlet阶段 servlet项目中,sql生成 ...
- alin的学习之路(Linux系统编程:五)(目录操作、进程相关概念)
alin的学习之路(Linux系统编程:五)(目录操作.进程相关概念) 1. 目录操作 1. 查看工作目录 getcwd char *getcwd(char *buf, size_t size) 功能 ...
- alin的学习之路(Linux系统编程:三)(vim,gcc,库,gdb)
alin的学习之路(Linux系统编程:三)(vim,gcc,库,gdb) 1.vim的使用 vim有三种模式:命令模式,末行模式,编辑模式 光标的移动[命令模式] h 向左 ,j 向下,k 向上,l ...
- 学计算机之路写一篇作文,我的学习之路作文(2篇)
我的学习之路作文(2篇) 在我们平凡的日常里,大家对作文都再熟悉不过了吧,作文根据写作时限的不同可以分为限时作文和非限时作文.那要怎么写好作文呢?以下是小编整理的我的学习之路作文,仅供参考,欢迎大家阅 ...
- alin的学习之路:共享内存
alin的学习之路:共享内存 1. 概念 共享内存是进程间通信中效率最高的一种方式. 共享内存: 可以被多个进程同时使用的一块内核的内存 有血缘关系的进程 没有血缘关系的进程 这块内存不属于任何的进程 ...
- alin的学习之路:面试题 计算机网络相关
alin的学习之路:面试题 计算机网络相关 介绍下proactor和reactor reactor:同步IO proactor:异步IO Reactor框架中用户定义的操作是在实际操作之前调用的.比如 ...
最新文章
- UNIX再学习 -- 高级 I/O
- web-8. 多框架页面的创建
- Effective Java学习笔记之第6条 消除过期的引用对象
- springboot中使用websocket_在 Spring Boot 项目中使用 activiti
- 360下拉词电脑端优化推广是怎么做的呢?
- protostuff java_protostuff 及其注意事项
- python批量打印mathcad_Print Conducto全能批量打印工具
- c语言代码自动整理,C语言代码自动整理工具
- matlab去高斯噪声,[转]MATLAB信号中高斯噪声
- 中科院信工所 考研面试经验贴
- H3C如何配置raid1
- iOS 生成证书、描述文件、打包上架Appstore详细流程
- C 语言fseek, ftell调用失败(fseek返回非零值,ftell返回-1)
- javaeye上对李刚的书的差评
- MySQL--数据导入导出
- 树莓派 Raspberry Pi 3B+ 无线路由器, WEB 服务器(Nginx,PHP,Sqlite3),UART 串口数据采集
- 生存模型的C-index(C指数)
- 关于ARM的一些笔记
- 常用的css特效(一)
- 趣味C语言小游戏(四)之连连看
热门文章
- 3.3系统管理-修改密码【斯纳克综合素质评价平台】
- 批量查询域名 到期未续费域名查询
- 2009计算机统考真题,2009年统考计算机考研真题
- 解决win8无法成功安装Windows Phone 7 sdk的问题
- 机械行业ERP选型的两大原则
- 静态HTML网页设计作品——火车票网上预订网站(4个页面) HTML+CSS+JavaScript web网页设计实例作业
- ABB DSQC652 I/O板通讯端子接线图
- 【转】2009年值得去关注的15个国内web2.0网站
- TCP/IP协议栈在Linux内核中的运行时序分析
- 地铁fas系统需要服务器吗,FAS系统(地铁fas系统组成)