指针与数组
时间:2022-07-24
本文章向大家介绍指针与数组,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
#include <stdio.h>
#include <limits.h>
void main1(){
int a[5] ={1,2,3,4,5};
// a=0x1233333; a是常量,不能为左值
printf("%x,%d,%xn",a,*a,*(a+1)); //61feac,1,2
//数组名a代表数组的首地址,,*a就是按照int类型往后取出4个字节的数据,按照int类型来解析 %d来解析
//数组名a代表数组的首地址,a+1要按照a的类型给a地址加1,也就是加int类型的四个字节,a+1=&a[1]
for (int i = 0; i < 5; ++i) {
printf("%x,%x",&a[i],a+i); //&a[i]等价于a+i,a+i就是从首地址a开始,每次往后移动i个sizeof(int)个字节数的地址
printf(" %d,%dn",a[i],*(a+i)); // a[i]本质等价于 *(a+i) 然后再从上面的首地址读取int类型的数据
}
//用指针循环方式遍历数组,数组名是一个常量地址 a=a 是错误的,常量无法赋值
int *px =a; //a常量地址赋值给指针变量
for (; px < a+5 ; ++px) { //指针每次自增,往前移动4个字节,也就是一个数组元素,指针自增不要越界,只有在数组内才有意义
printf("%d ",*px); //指针方式循环,px的值会改变
}
printf("nfour ways of presenting array are the same:n");
int *p =a;
for (int i = 0; i < 5; ++i) {
printf("%d,%x ",a[i],&a[i]);
printf("%d,%x ",*(a+i),a+i);
printf("%d,%x ",p[i],&p[i]); //i的方式循环p的值不变
printf("%d,%x n",*(p+i),p+i);
/*four ways of presenting array are the same:
1,61fea4 1,61fea4 1,61fea4 1,61fea4
2,61fea8 2,61fea8 2,61fea8 2,61fea8
3,61feac 3,61feac 3,61feac 3,61feac
4,61feb0 4,61feb0 4,61feb0 4,61feb0
5,61feb4 5,61feb4 5,61feb4 5,61feb4
* */
}
printf("nn");
//指针比较
int num=SHRT_MAX +100;
short *p1 =#
double *p2 =#
if(p1==p2){ //指针可以比较地址,是否相等,地址相等并不意味着其所指向的值相等,还要看他们如何按其类型解析
printf("指针相等n");
printf("%d!=%d",*p1,*p2); //-32669!=32867
}
// 优先级 *p++ 等价于*(p++) ++的优先级比*大,即先引用p的值*p,后自增p++,即: *p, p=p+1,等于于 a[i++]
//*(++p) 先自增++p,后引用*(p=p+1),等价于 a[++i]
//
}
void main2(){
int a[5] ={1,2,3,4,5};
int *p =a;
printf("%xn",p); //61feb8
printf("%d,%xn",*p++,p ); // 1,61febc 优先级 *p++ 等价于*(p++) ++的优先级比*大,即先引用p的值*p,后自增p++,即: *p, p=p+1,等于于 a[i++]
// printf("%d,%xn",(*p)++,p );// 1,61feb8 先取*p,再引用1,后再+1, (*p)++=2,p没有变
//printf("%d,%xn",*++p,p );//2,61febc 等价于 *(++p) 先自增++p,即&a[1],后引用*(p=p+1),等价于 a[++i] = a[2]
int *p1 =&a[1];
int *p2 =&a[3];
printf("%dn",p1-p2); // -2 p1-p2 <0 p1 < p2 p1的下标小于p2的下标
//指针相减多用于同一块内存,如数组或动态申请的内存,结果等于:地址差/sizeof(类型)
}
void main3(){
int *pInt;
double *pDouble;
printf("%d,%d,%d,%d", sizeof(*pInt), sizeof(*pDouble),sizeof(pInt), sizeof(pDouble)); //4,8,4,4
//sizeof(*pInt), sizeof(*pDouble),sizeof(pInt), sizeof(pDouble)
// 4 8 4 4
// *pInt *pDouble pInt pDouble
// int类型数据 double类型数据 int类型指针 double类型指针,指针大小固定为4个字节
}
//指向数组的指针和指向元素的指针 ????
void main4(){
int a[5] ={1,2,3,4,5};
printf("%x,%xn",a,&a); //61feb4,61feb4 a和&a的地址一样,但是他们指向的类型不一样 在a和&a前面加*,即是他们所指向的类型
//printf("%d,%dn", sizeof(a), sizeof(&a)); //20,4 a指向数组首地址,&a是a的地址,这个打印无意义,不用研究
printf("%d,%dn", sizeof(*a), sizeof(*(&a))); //4,20 *a是a指向数组的第一个元素,占4个字节,*(&a)是&a指向整个数组,是20个字节
int *p = a; //指向元素的指针 a=&a[0]
int (*pa)[5] = &a; //指向有5个元素数组的指针.
// 括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [4],这正是 a 所包含的每个一维数组的类型。
// [ ]的优先级高于*,( )是必须要加的,如果赤裸裸地写作int *p[4],那么应该理解为int *(p[4]),p 就成了一个指针数组,而不是二维数组指针
//printf("%d,%dn", sizeof(p), sizeof(pa)); //4,4 指针地址固定4个字节
//printf("%d,%dn", sizeof(p), sizeof(&pa)); //4,4 指针地址固定4个字节
printf("%d,%dn", sizeof(*p), sizeof(*pa)); //4,20 *p指向元素, *pa指向数组
//*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,
// 因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,
// 在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。
}
//指针引用多为数组
void main(){
int a[3][4]={1,2,3,4,
5,6,7,8,
9,11,12};
printf("%p,%p,%pn",a,&a,*a); //打印三者的地址0061FEA0,0061FEA0,0061FEA0 地址一样
printf("%d,%d,%dn", sizeof(*a), sizeof(*&a), sizeof(**a)); //打印三者所指向的类型大小 16,48,4
// a指向二维数组的行元素大小的指针 16 =4 *4 行指针
// &a指向二维数组大小的指针 48 = 12 *4 组指针
// *a指向二维数组的单个元素大小的指针 4 列指针
//打印二维数组
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%d %p, ",a[i][j],&a[i][j]);
}
printf("n");
}
printf("%d,%dn", sizeof(*a), sizeof(**a)); //16 4 a是行指针 *a是列指针 *a=*(a+0)=a[0] a[i]是一个列指针,&a[i]代表行指针
printf("%p,%p,%p n",a,a+1,a+2);
//a,a+1,a+2分别代表二维数组第一,二,三行的首地址,a是行指针
printf("%p,%p,%p n",*a,*a+1,*a+2);
//*a,*a+1,*a+2分别代表二维数组第一行第一、二、三列元素的地址 *a是第一行首列指针 *取列
printf("%p,%p,%p n",*(a+1),*(a+1)+1,*(a+2));
printf("%p,%p,%p n",a[1],a[1]+1,a[3]);
//*(a+1),*(a+1)+1 分别指向第二行第一列和第二行第二列元素的指针 <=> a[1]
//*(a+2) 指向第三行第一列元素的指针 <=> a[3]
// a[i]是一个列指针,第i行第一列的地址;&a[i]代表行指针,第i行的首地址
//结论: a[i][j] = *(*(a+i)+j) &a[i][j] = *(a+i)+j
/*
&a[i]== a+i == p+i &a[i]代表行指针,第i行的首地址
a[i] == p[i] == *(a+i) == *(p+i) a[i]是一个列指针,第i行第一列的地址;
&a[i][j] == &p[i][j] == a[i]+j == p[i]+j == *(a+i)+j == *(p+i)+j
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)
*/
}
- Linux同步机制 - 多线程开发总结
- 谷歌发布升级版语音合成系统,直接从字符合成语音
- 无锁编程 - 大纲
- 无锁编程(一) - Double-checked Locking
- 无锁编程(二) - 原子操作
- 我所理解的Remoting(3):创建CAO Service Factory使接口和实现相互分离
- 无锁编程(三) - 忙等待
- Enterprise Library深入解析与灵活应用(9):个人觉得比较严重的关于CachingCallHandler的Bug
- 无锁编程(四) - CAS与ABA问题
- Linux Kernel CMPXCHG函数分析
- 无锁编程(五) - RCU(Read-Copy-Update)
- 无锁编程(六) - seqlock(顺序锁)
- 无锁编程(七) - 实战
- zookeeper的python客户端安装
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- php遍历目录下文件并按修改时间排序操作示例
- laravel框架学习记录之表单操作详解
- php基于协程实现异步的方法分析
- Laravel框架实现多数据库连接操作详解
- Laravel5.1 框架Request请求操作常见用法实例分析
- 用python实现学生管理系统
- PHP CURL实现模拟登陆并上传文件操作示例
- python定义类的简单用法
- Linux yum 命令安装mysql8.0的教程详解
- 基于Python实现简单学生管理系统
- php 实现svg转化png格式的方法分析
- Python如何合并多个字典或映射
- 用Python 爬取猫眼电影数据分析《无名之辈》
- Python获取浏览器窗口句柄过程解析
- python如何支持并发方法详解