读书摘要 C primer plus 指针的基本用法和一些需要清楚的概念(1)

学习C prime plus
指针的基本用法和一些需要清楚的概念(
1
1 .指针变量的声明和初始化
指针就是把内存地址做为其值的变量。
(
1 )指针是一个变量
(
2 )普通变量直接引用了一个值
如:

int  a  =   3 ;
那么a的值就是3。
(
3 )指针变量只存放内存地址
(
4 )指针存放的内存地址往往存放有实际的值,但也可能是另外一个指针
如:

int  a  =   3 ;
int   *  aptr  =   & a; // 把a的地址通过取地址运算符赋给指针变量 aptr
printf ( " %p " , aptr); // 打印出指针的值,用16进制的方式
printf ( " %p " & a); // 打印出a的地址,用16进制的方式
( 5 )指针变量名间接应用了一个值,我们使用间接引用运算符来取得具体的值
printf (”
% d”,  * aptr);

(
6 )指针必须初始化,可以把指针初始化为NULL
NULL在中定义,它的值是0
使用NULL使程序具有可读性。

注意:
&  取地址运算符 取得任何变量的地址
如:

int  a;
int   * aptr;
int  c[ 5 ];
// 使用&运算符取得地址,并打印出来
printf ( " %p\n " & a); // 取得整型变量a的内存地址
printf ( " %p\n " & aptr); // 取得指针变量aptr的内存地址
printf ( " %p\n " & c[ 0 ]); // 取得数组第一个元素的内存地址
*  比较让大家迷惑的是它在这里有两种不同的用法,但实际上它们并不是同样的
(
1 )和具体的数据类型一起构成对应的指针类型
* 在声明语句表示变量是一个指针

int   *
float   *
char   *
double   *
(
2 )间接引用运算符

int  a  =   3 ;
int   *  aptr  =   & a; // 把a的地址通过取地址运算符赋给指针变量 aptr
 
printf (
" %d " * aptr); // 通过a的地址间接引用变量a的值
思考:
仔细分析下面的语句的结果。

int  a  =   8 ;
int   *  aPtr;
aPtr 
=   & a;
 
printf (
" %p\n " &   *  aPtr);
printf (
" %p\n " *   &  aPtr);
提示,一层层分析,可以看做 
& ( * aPtr)
答案在最下面。

二、指针的传引用调用
1 .C语言中所有的函数都是传值调用
为什么,难道指针不是传引用调用吗?
不是,C语言只是把指针的值拷贝一份,传如函数内部。
2 .那么传递数组呢?

void  printArray ( int   * nPtr);


void  printArray ( int  array[]);
的效果都是一样的,都是传一个地址进去。
另外,要注意:
数组名本身就是地址。
3 .指针的传引用调用我们也可称之为模拟传引用调用,因为我们传的是一个地址,
函数调用时,函数的参数会拷贝这个地址,然后通过复引用来操作变量。

int  cubeByReference ( int   *  nPtr) // 计算立方
{
    
* nptr  =   * nptr  *   * nptr  *   * nptr;
}
注意这里,
(
1 ) * (复引用运算符)比 * (乘法运算符)优先级要高。
所以可以不适用括号,但是推荐你使用下面的语句,这样程序更加清晰。
(
2 )nPtr是占用堆栈的,函数cubeByReference会给nPtr这个指针变量分配空间,
然后把传入的指针变量的值赋给它。

int  cubeByReference ( int   *  nPtr) // 计算立方
{
    (
* nptr)  =  ( * nptr)  *  ( * nptr)  *  ( * nptr);
}
4 .传值为什么不改变传入变量的值
因为它是在堆栈中生成一个新的变量,然后把存放的值拷贝过来,最后函数结束的时候把该变量从堆栈中释

放掉,所以并不会改变传入变量的值。
就像你用一张新的纸把一张纸上的东西复制一遍,然后在新的纸上写写画画,然后丢掉,并不会影响到原来

的纸上的内容。
5 .传指针(也就是传引用为什么会改变)
因为指针给出了原来变量的地址,使得
* (复引用指针)可以通过这个地址找到这个变量并对它进行修改。

三、指针的const限定
(
1 )指向非常量数据的非常量指针

int  a;
int  b;
int   * aPtr;
aPtr 
=   & a; // OK
aPtr  =   & b; // OK
* aptr  =   3 ; // OK
( 2 )指向常量数据的非常量指针(不能修改指向变量中的数据)

const   int   *  aPtr;
注意:
const  修饰int

int  a;
int  b;
const   int   * aPtr;
aPtr 
=   & a; // OK
aPtr  =   & b; // OK
* aptr  =   3 ; // ERROR 不能修改指向的变量中的数据
( 3 )指向非常量数据的常量指针(不能东指西指)

int   *   const  aPtr;
注意: 
const  修饰指针变量 aptr;
数组名是一个很好的例子。(参见字符串数组中的说明。)

int  a;
int  b;
const   int   * aPtr  =   & a;
aPtr 
=   & b; // ERROR  不能再指向另外一个变量
* aptr  =   3 ; // OK
( 4 )指向常量数据的常量指针(不能修改指向变量中的数据,不能东指西指)
const   int   *   const  aPtr;

int  a;
int  b;
const   int   *   const  aPtr  =   & a;
aPtr 
=   & b; // ERROR  不能再指向另外一个变量
* aptr  =   3 ; // ERROR  不能修改指向的变量中的数据
答案:
1 .实际上 * aPtr相当于a,  &* aPtr就取得a的地址
2 . & aPtr取得aPtr的直至,而 *& aPtr就取得aPtr存放的值,也就是a的地址
3 . &* 会相互抵消,实际上 &* aPtr  ==  aPtr  ==   *& aPtr

转载于:https://www.cnblogs.com/k7_1983/archive/2008/09/25/1298934.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值