指针对变量使对指向变量的指针&运算符产生,对指针使用*运算符则可以返回到原始变量
只要p指向i,那么*p就是i的别名*p不仅仅拥有和i同样的值,而且对*p的改变i的值
*p左值,对它赋值合法
*p = 90;
p
对象 的内存地址
*p 是指向对象的别名
p 存储的是指针
p = &i;
i = 1;
不把间接寻址运算符用于未初始化的指针变量;
int *p;
printf("%d",*p); /* prints garbage */
给*p赋值甚至更糟,p可以指向内存中的任何地方,赋值改变了某些未知的内存单元
int *p;
*p = 1 /* Wrong */
上述赋值改变的内存单元可能属于程序(可能导致不规律的行为)或者属于操作系统--可能导致系统崩溃;
指针赋值
C语言允许使用赋值运算符进行指针复制,两个指针具有相同的类型
指针赋值
允许使用赋值运算符进行指针赋值,两个指针具有相同的类型
int i,j,*p,*q;
p = &i;
p 存储的是变量在内存中的地址
把q指向了和p指向相同的地方;
q = p 指的是内存地址空间的值
*q = *p 指的 是所指向的内存地址空间存储的值相等!
p = &i;
q = &j;
i = 1;
*q = *p;
赋值语句*q = *p是把p指向的值(i的值)赋值到q指向的内存单元(变量j)中;
C语言用值进用变量作为实际参数行参数传递,所以在函数调用中用变量作为实际参数会阻止对变量的改变
需要函数改变变量
C这种特性
指针提供了此问题的解决方法
不再传递变量X作为函数的实际参数
而是&x不再传递变量X作为函数的实际参数,而是采用&x 指向X指针的
申明相应的形式参数p是指针
p &x
*p 是x的别名
函数体内*的每次出现都是对X的间接引用
*p 每次出现都将是对X的间接引用,而且允许函数既可以读取X也可以修改
函数体内*p的每次出现都是对X的间接引用,而且允许函数既可以读取X也可以修改X
decompose
void decompose(float x,int *int_part,float *frac_part);
指针会告诉scanf函数读取的值所放置的位置
没有&运算符,scanf函数将
虽然需要scanf函数的实际参数是指针
但是不是每个实际参数总是需要&运算符
scanf函数传递了指针变量;
int i,*p;
p = &i;
scanf("%d",p);
f(&x); // 地址
希望改变参数的值
可以使用单词const 不会改变传递给函数的指针所指向的 对象
为了允许检查传递的指针指向的实际参数.
void f/(const int *p)
{
*p = 0;
}
const的使用说明p是指向 整型常量指针
int *max(int *a,int *b) //返回指向最大数的指针---变量数的内存地址位置 *a *b 是
{
if (*a > *b)
{
return a; //a 存储的是a指针变量所指向的变量的内存的地址,*a 取指向变量内存地址else
return b;
值
}
}变量的别名 a,b 存储的是变量的内存地址;
调用max函数,传递指向两个int型变量的指针,结果存储在指针变量中;
int *p,x,y;
p = max(*x,*y);
永远不会指向自动
永远不会返回指向自动局部变量的指针
int *f(void)
{
int i;
return &i;
}
void f(const int *p) //常量指针,p存储的 内存地址
到底盘是不给修改p 内存地址还是不给修改 *p p 所指向的变量内存地址的变量数据;
void f(const int *p);
const int *p 常量指针变量
阻所指向的止修改的是指针 变量的值
可以修改p 保存的 内存别的地址!
void f(const int *p)
{
int j;
p = &j;
}
void f(const int *p)
{
//
}指的是不允许修改p 所指向的内存位置的值,为不是不允许修改p 指针变量的值,指针变量可以指向别的内存地址
申明指针类型的形式参数,
void f(int * const p)
const 可以保护p 指向的对象 ,在的类型后面放置const可以保护p本身
void f(const int *p) //保护*p 指不允许修改*p的值,但是可以把指针变量重新指向别的内存地址
void f(int * const p); //保护的是指针变量不能重新赋值别的内存地址 但是*p 却是可以修改
指针变量p的前面放置const可以保护p指向的对象
在p的类型后面放置const保护p本身;
p的类型前面放置const可以保护p指向的对象,p的类型后面放置const 可以保护p本身
void f(int * const p)
{
int j;
*p = 0; //legal
p = &j; //Wrong,p指针变量此时被保护;
}
p很一个少是另一个指针的副本,
既要保护p又要保护*p对象,可以通过p类型的前后都放置const
void f(const int * const p)
{
int j;
*p = 0; //Wrong
p = &j; //Wrong
}
数组指向数组元素,C允许算术运算
引出了对数组进行处理的替换可以是指针对指针进行算术 指针指向数组元素,允许对指针进行
可以使指针代替数组下标进行操作
数组和指针关系
当指针指向数组元素 允许对指针进行算术运算
指针代替数组下标
指针代替数组下标
指针指向数组元素
指针和数组之间的关系
指针处理数组的主要原因是效率
指针的算术运算
如何使用关系运算符合判等运算符进行指针的比较
如何能用指针处理数组元素
数组名字作为指向数据中元素的第一个
数组名指向数组中第一个元素的指针
把指针p指向数组a的元素、
通过在p执行指针算术运算 地址运算 可以访问到数组a的其他元算术素
地址运算 指针运算 访问到数组的其他元素
C支持3中格式的指针
指针加上整数
指针减去整数
两个指针相减
指针算术运算--地址算术运算 可以访问到数组a的其他元素
C支持3种格式的指针算术运算
指针加上整数
指针减去整数
两个指针相减
int a[10],*p,*q,i;
指针 减法运算 减去整数;
p指向数组元素a[i],p - j 指向a[i - j]
指针加上整数
指针减去整数
两个指针相减
指针相减 结果为指针之间的距离计算数组中元素个数
指针相减,结果为指针之间的距离 计算数组中元素 的个数
p指向a[i] q指向a[j] q - q 等于 i -j;
只算术数组元素,指针有p指向p上的 意义结果
只有两个指针指向同一个数组,指针相意义;
减才有
指针比较
用关系运算符< <= > >= 和判等运算符== !=
只有用关系两个指针指向同一个数组 运算符进指针比较菜有意义 比较的结果行的 依赖数组中两个元素 的相对位置
指针用于数值处理
指针的算术运算允许通过对指针变量进行重复自增来数组的元素访问
指针用于数组处理
指针的算术运算允许通过对指针变量进行重复自增来访问数组的元素
指针的算术运算允许通过对指针变量进行重复自增来访问数组的元素
指针的算术允许通过对指针变量进行重复自增来访问数组的元素
程序对数组元素进行求和;
指针变量p初始化指向a[0]
每次被执行循环,p a[0];
p进行自增结果p 指向a[1] p 执行到数组a的最后一个元素后循环终止;
#define N 10 宏名称 typedef int newTypeName;
int a[N],sum,*p;
//
sum = 0;
for (p = &a[0];p < &a[N];p++)
{
sum += *p;
}
关系运算符 判等运算符== != 两个指针指向同一数组 比较的结果依赖数组中两个元素的相对位置
指针相减
两个指针相减
两个指针相减,结果为指针之间的距离 指针之间的距离 指针 加整数 指针减整数
指针相减
结果为指针之间的距离 计算数组中元素的个数
指针相减
指针间接的距离 计算数组中元素的个数
p指向a[i] 且q指向a[j];
指针相减
结果为指针之间的距离 -- 计算数组中元素的个数
p指向a[i] q指向a[j] p - q 等于i - j;
指针减去整数
p指向数组元素a[i] 那么p - j 指针与整数相加减 的作为就是移动指针指向的数据元素的内存地址
p = &a[8];
q = p - 3;
p -= 6;
指整数针减 作为是将指针现在指向的数组元素的内存地址位置向左移动整数个
p = &a[8];
q = p - 3 但此的值是指针变量,存储的是内存的 地址;
p -= 6;
p = p -6 p 指针当前的位置 向左边移动6个元素量;
#define N 10
int a[N],sum,*p;
sum = 0;
for (p = &a[0];p < &a[N];p++)
{
sum += *p;
}
a[] 10个元素数组,sum 整型变量 ,*p整形指针变量
sum = 0;
for (p = &a[0]//整型指针变量指向a数组的第一个元素;p < &a[N];p++) p = p + 1 指针变量与整数相减价 的 作用就移动指针所指向的数组的元素;
p < &a[N] 小于指针指向的数组元素的最后一个元素;
p++ 数据的元素移动;
p < &a[N] 元素不存在
数组a的下标从0 到N - 1对它取地址运算符合法 p = &a[N] 循环终止
*间接引用 运算符 取的是指针指向的内存地址空间的值 ++ 运算符
数组存入数据元素中
数值存入到数组元素中;推进到下一个元素 利用数组下标可以写成
a[i++] = j;
如果p指向数组元素,相应的语句将会是
*p++ = j;
*p = *p + 1 //Wrong
*p++ = *(p++) *(p = p + 1)
计算用的都是指针变量
*p 当使用间接引用的时候,计算的就是 改变间接引用指针所指向的内存地址的变量的值;
把值存入到数组元素中,然后推进到下一个元素
i = i + 1;
利用数组下标;
p指向数组元素
*p++ = j;
*p 指的是 间接取值 p 代表的是变量内存地址的指针变量;
++在* 间接引用前使用 是指针变量的值--其它变量的内存地址 的 位置向后推进
*(p++) = j;
后缀 只有表达式计算出后才自增
*(p++)的值将是*p; p 指向当前对象
(*p)++ 表达式返回p指向的对象值 然后对象进行自增
返回指向对象的 p 本身是不变化 的 p 指向变量 的 内存地址;
*p++ *(p++)自增前表达式的值是 自增前表达式*p(++)
*p++ 指针变量的值在变化 增加 向下一数组元素推进个
*p++ *(p++);
自增的指针变量的值,达到的效果就是指针所指向的内存地址的指向位置推进到数组元素的下一个
(*p)++ `*p`使用间接引用取出指针变量所指向的内存的地址,然后此值进行自增;
*(p++)
自增前
表达式的值
*p++ 计算的是p++
*p
(*p)++
自增前表达式值,然后自增的是什么?
*++p 先自增p 自增后表达式的值是*p
++ *p 先自增
*p++ *(p++) 推进到指针所指向的数组元素的下一个
for (p = &a[0]; p < &a[]N;p++)
指针指向数组的第一个元素,指针p的值小于指针指向的数组元素的最后的值
sum += *p;
p = &a[0];
while (p < &a[N])
sum += *p++;
*p++ *++p ++运算符的优先级别高于 *的 首先计算的是 指针变量的值;
原始版本的栈依赖名为top的整型变量跟踪contents数组栈顶的位置
top整型变量跟踪contents数组栈顶的位置 FILO first input last output
用指针变量替换top
指针变量初始指向contents数组的第0个元素;
指针变量替换top 指针变量初始指向contents数组的第0个元素
指针
int *top_ptr = &contents[0];
指针变量 指针变量初始指向contents数组的第0个元素
int *top_ptr = &contents[0];
void push(int i)
{
if (is_full())
{
stack_overflow();
}
else
{
*top_ptr++ = i;
}
}
int pop(void)
{
if (is_empty())
{
stack_underflow();
}
else
return *--top_ptr;
}
数组名作为指针
指针的算数字和指针之间术运算是 相互关联的一种方法,但不是 用数组的名字作为指向数组第一个元素的指针
数组的数组第一个名字作为指向
数组的名字指向数组第一个元素的指针
数组的名字
关系简化了指针的算术运算 是数组和指针都更加通用
数组名作为指针
用数组名作为指针
指针的算术运算是数组和指针之间相互关联的一种方法 下面是另一种关系;
*a 数组的名字作为指向数组第一个元素的指针
这种关系简化了指针的算术运算,使得数组和指针都更加通用;
int a[10];
用a作为指向数组第一个元素的指针
int a[10];
正新数组 int a[10];
a作为指向数组第一个元素的指针, a作为指向数组第一个元素的指针,修改a[0];
数组名作为指针
int a[10];
a 数组名称 就是整个数组的地址,也是数组元素的第一个元素的地址;
*a = 7;//
*(a + 1) = 12;
数组名作为指针
指针的算术运算 数组的名字 作为指向数组第一个元素指针 关系简化了指针的算术运算
如下形式声明a
int a[10];
a作为指向数组第一个元素指针,修改a[0];
指向数组元素的第一个元素的指针 数组名称 作为指向数组第一个元素的
a 存储的是 数组的地址 也是数组第一个元素的地址
*a = 7; a[0] 都表示数组的第一个元素;
a存储的是数组内存地址 整个数组在内存地址,数组第一个元素在内存地址;
* *(a + 1) = 12
取地址运算
&a[0] = 存储和 取出 的 是变量的内存地址;
a + i &a[i] 指向数组a中i元素的指针
*(a + i) 取值间接引用;
数组的第n个元素;
把数指针算术运算的组的下标看成是格式;
数组名可以用作指针的事实 数组 编写从头数组的循环更加容易
到尾单步操作
for (p = &a[0];p < &a[N];p++)
p 指针变量指向数组的&a[0]第一个元素的指针,p < &a[N] p指针的变量小于数组最后一个元素内存地址
后的一个不存在的数组元素的 到此处时 For 语句已经终止;
a 数组名代替 代表数组的第一个元素,整个数组在内存的第一个
a &a[0]
a + N &a[N] 这个 是为什么呢? a 表示数组的第一个元素, a + N 表示数组元素的地址向下 推进, &a[N]表示数组的第N个元素的内存地址
a + N === &a[N]!!!;
p < a + N p = a 指针的变量 指针 指向 数组元素的第一个 后面a + N p++ 指针变量;
sum += *p;
数组 用作指针
虽然可以把数组名 数组名赋新的值;
试图错误
使数组名指向其他地方
while (*a != 0)
*a 间接 a 地址
a++ a 是内存地址 自增 改变的 效果是 推进 数组 元素位置l
a++ 数组名 使 数组名用作指针 但不能给数组名赋予新的值,试图使数组指错误
向其他
试图使其它地方错误
a++使数组名指向其他 地方 是错误
数组名不能赋予新值;
可以始终 把a复制给指针变量
然后 改变 指针变量p = a
while (*p != 0)
p++ p 指针
数列反向
数列反向 reverse.c 读进10 反序写出这些数 存入数组
程序利用下标访问数组元素
利用下标数组的算术运算代替指针的
原来程序中
scanf函数要求的参数;
p 指向数组的元素,满足scanf函数要求的参数 p指向数组元素 内存地址,满足scanf函数要求参数
&p 指向另一个指针的指针
数组型实际参数
传递给函数,数组名始终作为指针
数组型实际参数,数组名始终作为指针
数组型实际参数,传递函数,数组名始终作为指针,函数返回整型数组中最大元素