C语言之指针
以32为系统为例。
1、指针与地址
指针是一种变量,保存了所指向对象的地址。
1.1 定义
int i = 10;
int *p = &i; //定义了一个指针p,它指向一个int型的变量
&是地址运算符,*是间接引用运算符。
&i是取i在内存中的地址,*p = &i是将i的地址赋值给p,即p的值是i的地址。
1.2 引用
*p = 100 等价于 i = 100,即将i的值改成100
*p += 1 等价于 i += 1,即将i的值加1
*p++改变了p所指向的地址,此时p不再指向i的地址,而是指向i的地址+4的新地址。因为*(间接引用运算符)和++具有相同的优先级,且是从右到左的结合性,所以等价于*(p++)。p++是将指针加1,指向内存中下一个地址。由于这里的p是int型的,实际上是偏移了sizeof(int)=4个字节。例:
int i = 10;
int *p = &i;
*p++;
printf("i=%d, &i=%p, p=%p\n", i, &i, p);
打印结果:i=10, &i=0xbf99bd78, p=0xbf99bd7c
注意:绝对不能这么写*p++ = 111,因为这无意中非法改变了p下一个内存地址的值。
++*p 等价于 i的值加1
*++p 等价于 *p++
*p + 1 等价于 i 的值 加1
*(p + 1) 等价于*p++
2、指针和数组
int a[10];
int *p = &a[0]; //指针p指向数组a的首地址元素a[0]
或者int *p = a; //数组名所代表的就是该数组的第一个元素的地址,直接赋值给p
引用第i个元素:
a[i] 或者 *(a+i) 或者 *(p+i) 或者 p[i]
数组名和指针的差别:
指针是一个变量,可以赋值或者++,如p=a,p++
但数组名不行,不能这样:a=p, a++
指针的运算包括:
相同类型指针之间的赋值运算;指针同整数之间的加减法运算;指向相同数组中元素的两个指针的减法或比较运算;指针赋值为0,或指针与0之间的比较运算。
3、指针数组和指向指针的指针
指针数组:int *p[10]; //p是一个指针数组,具有10个元素,每个元素都是一个指向int型对象的指针。
指向指针的指针: int **p; //p是一个指针,指向一个int *型对象
4、二维数组
int a[10][20]; //二维数组,有10行,每行20列
int a[][20] = {........}; //二维数组,每行20列,行数会根据{...}内的值的个数自动计算,行数={...}中值的个数/20 + 1
二维数组必须要指定列数,行数可以不用指定。
二维数组作函数参数时,函数的声明方式可以是:
f (int a[10][20]) {...} 或者
f (int a[][20]) {...} 或者
f (int (*a)[20]) {...}
不能是f (int *a[20]) {...}
数组指针(行指针):char (*p)[20]是一个指针,指向具有20个char型元素的一维数组。
sizeof(p)=4,占用一个指针的存储空间
char a[10][20];
char (*p)[20];
p=a; //二维数组首地址给p,p指向a[0][0],即第0行的第0个元素
p++; //执行后,p指向a[1][0],即第1行的第0个元素
指针数组:char *p[20]是一个数组,具有20个元素,每个元素都是一个指向char型对象的指针
sizeof(p)=80,占用20个指针的存储空间
char a[10][20];
char *p[20];
p[0]=a[0]; //p[0]指向二维数组a的第0行
p[1]=a[2]; //p[1]指向二维数组a的第2行
两者的引用方式一样,都是:*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]
原因:[]的优先级高于*的优先级。
5、指向函数的指针
int (*f)(int i, int j) 定义了一个函数指针,这个函数有两个参数i和j,函数返回一个int型对象。
圆括号是必须的,否则就变成了int *f(int i, int j),这表示函数f返回一个int *型对象。
6、总结
char **x:x是指向指针的指针
char (*x)[10]:x是一个数组指针,指向一个具有10个元素的数组
char *x[10]:x是一个指针数组,每个元素都是一个指向char型对象的指针
char *x( ):x是一个函数,该函数返回一个指向char型对象的指针
char (*x)( ):x是一个函数指针,该函数返回一个char型对象
char (*(*x( ))[10 ])( ):定义了一个函数,该函数返回一个具有10个元素的数组指针,元素类型是函数x返回的指向char类型对象的指针
char (*(*x[10])())[2]:定义了一个数组,数组有两个元素,每个元素的类型是函数返回的指向一个10个元素的指针数组的指针
C语言之指针的更多相关文章
- 浅谈c语言的指针
对于非计算机专业的同学,c语言的指针往往就是老师的一句“指针不考“就带过了.c语言的指针号称是c语言的灵魂,是c语言中最精妙的部分. 指针本质上也是变量,也就是一段内存,只是他的特殊之处是他存储的数据 ...
- C#委托与C语言函数指针及函数指针数组
C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...
- C语言二重指针与malloc
(内容主要源于网上,只是加入了些自己的剖析) 假设有一个二重指针: char **p; 同时有一个指针数组 char *name[4]; 如何引用p呢? 首先我们有程序代码如下 #include &l ...
- C语言函数指针基础
本文写的非常详细,因为我想为初学者建立一个意识模型,来帮助他们理解函数指针的语法和基础.如果你不讨厌事无巨细,请尽情阅读吧. 函数指针虽然在语法上让人有些迷惑,但不失为一种有趣而强大的工具.本文将从C ...
- 为什么C/C++语言使用指针
这是参加面试时,面试官问的一道开放性题目. 问题是:为什么C/C++语言使用指针? 这个问题一问出来,直接被面试官秒杀了,面试官大神,你怎么不按套路出牌啊? 说好的malloc和new的区别呢?说好的 ...
- C语言的指针变量
C语言的指针变量 在C语言中,变量是固定范围的存储空间,它存储的是赋给他的值, 比如: ; /* 这里是定义一个整型变量a,并把12这个值存储在a的地址空间上 这个地址空间是系统随机分配的,对用户是透 ...
- Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型
Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面 ...
- “对外部(局部)变量的访问”是C语言函数指针的最大弱点
1.“对外部(局部)变量的访问”是C语言函数指针的最大弱点 . #include <stdio.h> #include <stdlib.h> /* 结构体定义 */ struc ...
- go语言学习--指针的理解
Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,array/slice,map,chan, fu ...
- C语言中指针占据内存空间问题
以前一直有个疑问,指向不同类型的指针到底占用的内存空间是多大呢? 这个问题我多次问过老师,老师的答案是"指向不同类型的指针占据的内存空间大小不同",我一直很之一这个答案,今天我就做 ...
随机推荐
- Paginator
Paginator There are several ways to paginate items. The simplest is by using the paginate method on ...
- Android实现资料收藏
1,调web浏览器 Uri myBlogUri = Uri.parse("http://xxxxx.com"); returnIt = new Intent(Intent.ACTI ...
- NekoHTML
1.如何使用NekoHTML? 必须在 Java Build Path里加入 nekohtml.jar , xercesImpl.jar 以及xalan.jar.下载的NekoHTML目录中并没有xe ...
- myeclipse连接数据库遇到的几个问题
1:无效的SQL URL: //将获取的参数插入数据库 Connection conn=null; PreparedStatement stat=null; ...
- BigInteger
首先上模板(不断更新中...)(根据刘汝佳AOAPCII修改) #include <iostream> #include <sstream> #include <cstd ...
- js数组求和
array1.reduce(callbackfn[, initialValue]) callback : 函数执行在数组中每个值 initialValue : 对象作为第一个参数回调的第一次调用使用 ...
- ADO.NET通用数据库访问类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- SQL*PLUS中批量执行SQL语句
SQL*PLUS中批量执行SQL语句 今天由于工作的需要,要在CMD中批量执行大量的SQL语句,对于Oracle学习还处在入门阶段的我,只能硬着头皮到处去寻找资料(主要是网络资料,也包括自己的电子书) ...
- activiti源码解读之心得整编
TaskService.completeTask()的执行内幕是啥? activiti采取了command模式,completeTask会被包装成一个CompleteTaskCmd,一个Cmd执行的时 ...
- 项目开发中常用到的SQL语句
阅读目录 循环示例 循环示例 循环示例 循环示例 1.循环示例 在前端面试中最常见的问题就是页面优化和缓存(貌似也是页面优化),被问了几次后心虚的不行,平然平时多少会用到一些,但突然问我,很难把自己知 ...