C语言之指针与数组总结
和指针相关的问题口诀1:
1. 地址变量得地址,得谁地址指向谁
和指针相关的问题要画图: 内容变量画房子,指针画箭头
---->口
----------------------------------------------------
和指针相关的两个特殊运算符:
一、"&" 取地址运算符,通过&运算符可以取出普通变量的地址;
二、"*" 有两种意义:
1. 为指针标志: 是否为指针标志主要看前面是否有类型,此处有一个int
2. 为指针运算符:
在等号右面为取值。*可以取出指针变量所指向的普通变量的值。
在等号左面为赋值。*可以将指针变量所指向的普通变量的值,修改为其他。
口诀2: 有* 为内容值,不是读就是写。等号左面为赋值, 其余都为取值。
3. 为乘法运算符。当且仅当左右的都为变量时。略。
如
int a, b =20, c=30, d=40, *p; (正确,此处的*为指针标志,只起到定义的左右,没有取值和赋值的作用。是否为指针标志主要看前面是否有类型,此处最前面有一个int)
p=&d; (正确,p指向d的地址)
a=*p; (正确,此处的*为取值。最后结果a的值变为了d的值40)
*p =c; (正确,此处的*为赋值。最后结果d的值变为了C的值30)
*p =&b; (运行错误,左边为内容值,右边为地址,不等价)
--------------------------------------------------------
和指针相关的等价表达式
若指针变量p指向变量a,即将变量a的地址赋给了指针变量p.
如:int a=20, int *p=&a;
则有如下结果:
A、*p <=> a
B、 p <=> &a
C、 &*p <=> &a <=> p
D、*&a <=> *p <=> a
E、 (*p)++ a++
(*p)-- a--
++(*p) ++a ++*p
--(*p) --a --*p
可以看出 * 和 & 是互逆的两个运算符
--------------------------------------------------------
所有的指针变量在内存中分配的字节数相同 sizeof(指针) 永远是 两个字节, 不管指针定义时是 int *, float * 还是 double * . 详细如下
int *p1; 则 p1以后必须指向int 类型的变量。 但指针本身的长度,sizeof(p1) 为2个字节(2*8bit -16bit)
float *p2; 则 p2以后必须指向float 类型的变量。 但指针本身的长度,sizeof(p2) 为2个字节(2*8bit -16bit)
double *p3; 则 p3以后必须指向double 类型的变量。 但指针本身的长度,sizeof(p3) 为2个字节(2*8bit -16bit)
-----------------------------------------------------------
四道例题:
例子1.
void fun (int *x , int *y) {
printf("%d, %d", *x, *y) ;
*x = 3;
*y = 4;
}
main()
{
int x = 1, y = 2
fun(&y, &x);
printf("%d, %d", x, y);
}
结果
2, 1
4, 3
注意main在调用fun函数时, y 和x故意写颠倒了。
--------------------------------------------------------------
例子2.
#include <stdio.h>
void swap(int *p1, int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
main()
{
int a, b;
int * p1 = &a, *p2 = &b;
scanf(%d %d, p1, p2);
swap(p1, p2);
prinf("%d, %d", *p1, *p2);
}
如果在控制台输入 2 和 5
则输出结果为
5, 2
原因: 在调用swap函数时使用了职称,所以在swap函数内部对p1,p2 所引用的内容值的修改,会影响外面的a和b的值。
--------------------------------------------------------------
例子3:
#include <stdio.h>
void swap(int *p1, int *p2)
{
int *temp;
temp = p1;
p1 = p2;
p2 = temp;
}
main()
{
int a, b;
int * p1 = &a, *p2 = &b;
scanf(%d %d, p1, p2);
swap(p1, p2);
prinf("%d, %d", *p1, *p2);
}
和2不同, swap函数中的temp为指针,temp=p1使得temp指向了2,p1=p2使得p1指向了5,p2=temp使得p2指向了5.
但最后的打印结果仍为
2,5
原因是:虽然main中调用swap函数时使用了指针传递,但swap函数中的所有操作都是:将指针本身的修改,而没有再次使用*操作符来修改“指针指向的内容值”
口诀3:没有*的指针操作为地址,地址的赋值意味着改指向。
---------------------------------------------------------------------
例子4:
#include <stdio.h>
void swap(int *p1, int *p2)
{
int *temp;
*temp = *p1;
*p1 = *p2;
*p2 = *temp;
}
main()
{
int a, b;
int * p1 = &a, *p2 = &b;
scanf(%d %d, p1, p2);
swap(p1, p2);
prinf("%d, %d", *p1, *p2);
}
和2很像。但唯一不同是,temp定义为指针而不是普通变量。看上去似乎应该和2的输出结果一样,仍为
2,5 。
但实际运行时编译器会报错:非法的内存写入。
原因是:temp为野指针,并没有预订指向哪里。如果指向系统区,则可能导致操作系统死机或崩溃。
如果temp在定义后,马上给一个初始值,就不会有问题了。
---------------------------------------------------------------------
指针、数组的等价符号
若将数组作为形参,则将数组名作为指针变量来处理。
int fun(int a[10]) <=> int fun(int *a) <=> int fun(int a[])
可以看出,口诀4: &与*互逆。 *与[]等价, &与[]互逆
例子5:
int s[10], a, b;
in d[3][6];
int *p;
p=&a; //p 指向了整数a
p = &s[2]; //p指向了s数组的第二个元素
p= &d[2][4];////p指向了d数组的第二行、第四列的元素。
所以,以上的语句都是对的。
上面的例子:
1. 定义了一个int s[10]; 则 s等同于 &s[0]. 即,看到一个数组,就马上联想到他代表的是数组第一个元素的地址。
在C语言中规定,数据名代表数组的首地址,并且是一个地址常量
2. 另外,如果定义了一个指针 int *ppp = s; 则 ppp 定价于s, 同时等价于 &s[0]。
---------------------------------------------------------------------
指针的加减:
当指针变量指向数组中的某一个地址时,指针变量加1后指向数组的下一个元素,
指针变量减1时指向数组的前一个元素。
例子6:
float a[10]; float *p;
p=&a[4]; 则p-3指向?
先画图:
a[0] | a[1] | a[2] | a[3] | a[4] | ...
p的初始位置指向了 a[4], 则 p-3 为向前3个,指向了 a[1]
口诀5: 指针的加减是向前或向后移动了n个元素
---------------------------------------------------------------------
若
int a[N], *p=a;
则有:
地址三等价:
存在等价表达式:
p+i <=> a+i <=> &a[i] 代表的是第i个元素的地址
元素四等价:
存在等价表达式:
1. *(p+i) <=> *(a+i) <=> a[i] 代表的是第i个元素的值
2. 另外,还有 p[i] <=> a[i] 。 p[i] 的用法不多见,但无任何错误,代表的也是第i个元素的值。原因是p和a完全等价。
整理出来的等价式如下:
a) *(p+i) <=> *(a+i) <=> a[i] <=> p[i]
b) p++ <=> ++p <=> p+=1 <=> p=p+1
c) p-- <=> --p <=> p-=1 <=> p=p-1
d) *p++ <=> *(p++)
说明:* 与 ++ 的运算优先级一样,所以按照从右到左的结合原则,先执行++,后执行*
++在p的后面,为执行后再加。即先把p的值取出,指针再加1.
e) *++p <=> *(++p)
++在p的前面,为先加再执行。即先把指针加1, 再把移动后的p所指向的值取出,
f) (*p)++ <=> ++(*p) <=> ++*p
将p的内容自增
g) (*p)-- <=> --(*p) <=> --*p
将p的内容自减
C语言之指针与数组总结的更多相关文章
- C语言中指针和数组
C语言数组与指针的那些事儿 在C语言中,要说到哪一部分最难搞,首当其冲就是指针,指针永远是个让人又爱又恨的东西,用好了可以事半功倍,用不好,就会有改不完的bug和通不完的宵.但是程序员一般都有一种迷之 ...
- C语言的指针和数组
指针和内存 指针变量也是个变量,不过保存的是另一个变量的地址.另外编译器还会记住指针所指向变量的类型,从而在指针运算时根据变量类型采取不同操作. 例如,char * a 定义了char 类型的指针变量 ...
- c语言,指针与数组--指针与二维数组2
指向一维数组的指针 char (*p)[10] ;指向一维数组的指针类型 typedef char(*TYPE_P2ARRAY)[10] ; 该指针可以指向数组 ,且使用起来效果节本相同, ...
- C语言中指针和数组的区别
看<C专家编程>一书,看到数组与指针并不相同一章,遂做了一段测试: 代码: #include <stdio.h> #include <stdlib.h> int m ...
- C语言中 指针和数组
C语言的数组表示一段连续的内存空间,用来存储多个特定类型的对象.与之相反,指针用来存储单个内存地址.数组和指针不是同一种结构因此不可以互相转换.而数组变量指向了数组的第一个元素的内存地址. 一个数组变 ...
- C语言使用指针表示数组的注意事项
1)数组名是指针常量 如对指针变量可以进行++运算,但是对数组名却不允许,另外,对数组名的赋值运算也是错误的 2)注意指针变量的当前值 指针变量的值在程序运行过程中可能经常改变,要对此注意 3)数组越 ...
- Android JNI编程(四)——C语言多级指针、数组取值、从控制台输入数组
版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:前面我们介绍了一级指针的相关概念和用发,今天我们就来说一说多级指针. 1 ...
- C语言_指针和数组的几种访问形式
敲几行代码来看看几种访问的形式~ #include <stdio.h>;int main() { ] = {, , , , , }; //初始化5个元素的一维数组 int *p = arr ...
- 浅谈C语言 extern 指针与数组
/* * d.c * * Created on: Nov 15, 2011 * Author: root */ #include "apue.h" int a[] = {3,2}; ...
随机推荐
- C语言相关图书推荐
C Primer Plus(第5版 中文版) 作 者 [美] 普拉塔(Prata S.) 著:云巅工作室 编 出 版 社 人民邮电出版社 出版时间 2005-02-01 版 次 1 ...
- MFC学习知识点20160715
1. sizeof() :返回所查询目标所占用字节数 _countof() :返回所查询目标所含有元素个数 _countof 是 C++中计算一个固定大小数组长度的宏,比如: T arr[10] ...
- Nuttx操作系统
前几天答辩的时候看到有同学在用,回来后查了点资料. 来源:天又亮了 1 NuttX 实时操作系统 NuttX 是一个实时操作系统(RTOS),强调标准兼容和小型封装,具有从8位到32位微控制器环境的 ...
- 三、python高级特性(切片、迭代、列表生成器、生成器)
1.python高级特性 1.1切片 list列表 L=['Mli','add','sal','saoo','Lkkl'] L[0:3] #即为['Mli','add','sal'] 从索引0开始 ...
- 批量ping主机脚本
#! /bin/bash for i in `cat test.list`do host=`echo $i|awk -F"," '{print $1}'` app_IP=` ...
- 第二百五十九天 how can I 坚持
晚上,弟弟给我说了下他前几天发生的事,这孩子,有事就不知道说下,自己闷在心里. 刘松打算最近买房了,弟弟和建哥也考虑买,让他俩商量着来吧,早晚都得买. 有点揪心.想结婚不知道该和谁结... 睡觉.烦.
- java.net.BindException: Address already in use: bind
环境:jxse-2.7, netty-3.6.6.Final 现象:每次执行都抛出以下异常 八月 08, 2013 8:45:19 下午 net.jxta.logging.Logging logChe ...
- UVA 11300 Spreading the Wealth
题目大意:n个人手中有些金币,每个人可给相邻两个人一些金币,使得最终每个人手中金币数相同,求被转手的金币最少数 m为最终每个人手中的金币数,a1,a2,a3,...,an为每个人开始时手中的金币数,x ...
- [iOS UI进阶 - 3.1] 触摸事件的传递
A.事件的产生和传递 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发 ...
- HDU 3308 LCIS (线段树区间合并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...