旅途

如果想飞得高,就该把地平线忘掉

指针变量的储单元的大小

main()
{
int i;
int *p = &i;
printf("%d",sizeof(p));
}
我32位CPU,
在VC测试: 4
在TC测试: 2
请问,指针变量存储单元的大小与什么有关?
指针大小和当前系统的地址总线位数一样,TC运行在16位模拟器中,所以指针大小是16位即2个字节,vc就是32位的,int类型的大小也和这个一样是变的,其它类型的大小不会变的
TC和VC所支持的语言标准不同,跟16位和32位编程无关。
TC支持纯C语言,纯C语言里的6种int型数据中只有long和unsigned long型长度是4字节,另外4种长度是2字节,而VC里支持的C语言全部6种int型数据长度全部是4字节。我们知道,指针的长度和其相应的数据类型长 度相等,所以int型指针在TC里是2字节,在VC里是4字节。

指针的大小是问:一个指针变量占用多少内存空间?

 

分析:既然指针只是要存储另一个变量的地址,。注意,是存放一变量的地址,而不是存放一个变量本身,所以,不管指针指向什么类型的变量,它的大小总是固定的:只要能放得下一个地址就行!(这是一间只有烟盒大小的“房间”,因为它只需要入一张与着地址的纸条)。

 

存放一个地址需要几个字节?答案是和一个 int 类型的大小相同:4字节。

 

所以,若有:

int* pInt;

char* pChar;

bool* pBool;

float* pFloat;

double* pDouble;

 

:sizeof(pInt)、sizeof(pChar)、sizeof(pBool)、sizeof(pFloat)、sizeof(pDouble)的值全部为:4。

 

(你敢拆电脑吗?拆开电脑,认得硬盘数据线吗?仔细数数那扁宽的数据线由几条细线组成?答案:32条,正是 4 * 8)。





指向数组的指针

 

现在,来说说指针指向一个数组的情况。

 

int arr[] = {1,2,3,4,5}; //一个数组

 

int* parr; //一个指针。

 

parr = arr; //没有&?对啊,对数组就是不用取址符。

 

cout << *parr << endl;  //输出 *parr

 

先猜想一下,输出结果是什么?

 

最“直觉”的想法是:parr 指向一个数组,那么输出时,自然是输出数组中的所有元素了。所以答案应该是:“12345”了?

不过,我想,学过前面的数组,我们就能知道这种想法错误。

 

正确答案是输出数组中的第一个元素: 1 。

 

接下来,如果是这样输出呢?

 

parr = arr;

cout << parr << endl;

 

答案是输出了arr的地址。就等同于输出 arr

cout << arr << endl; 的作用

 

在这里,难点是要记住,数组变量本身就是地址。所以有:

 

1、想让指针变量存储一个数组的地址(想让指针变量指向一个数组)时,不用取址符。

2、解析一个指向数组的指针,得到的是数组的第一个元素



偏移指针


int* parr2;

 

parr2 = parr + 1;

加1后,指针指向了下一个元素。由于这是一个 int 类型的数组,每个元素的大小是4个字节。所以第二个元素的地址是10000014。

 

重点 & 易错点:对指针 进行加1操作,得到的是下一个元素的地址,而不是原有地址值直接加1。

 

知到了如何“加”,也就知道了如何“减”。减以后,得到的是上一个元素的大小。

 

所以,一个类型为 T 的指针的移动,以 sizeof(T) 为移动单位。

所以,一个类型为 T 的指针的移动,以 sizeof(T) 为移动单位。

 

比如:

int* pInt; 移动单位为 sizeof(int) 。即:4。而 char* pChar; 移动单位为 sizeof(char)。即1。



指针的最小移动单位

 

int arr[6] = {101,102,103,104,105,106};

int* pI = arr;

 

cout << "pI 是一个指向整型数组的指针,移动单位:4字节" << endl;

 

for (int i = 0; i < 6; i++)

   cout << "pI + " << i << " ----> " << pI + i << ", *(pI + i) = "  << *(pI + i) << endl;  

 

cout << "------------------------------------" << endl;

 

//接下 来是一个指向char类型数组的指针:

char str[4] = {'a','b','c','d'}

 

char*  pC = str;

 

cout << "pC 是一个指向字符数组的指针,移动单位:1字节" << endl;

for (int i=0; i < 4; i++)

    cout << "pC + " << i << " ----> " << (int)(pC + i) << ", *(pC + i) = "  << *(pC + i) << endl;  

 

system("PAUSE");

 

输出结果:

(指针的最小移动单位)

每一行中,程序先输出指针加上偏移量以后的值(地址),比如:1245024、1245028;然后输出偏移后指针指向的值,比如101,102。

查看移动前后指针存储的地址,我们就可以计算出移动单位。1245028 - 1245024 = 4 (byte)。

 


* (地址解析符)与 ++ 的优先级


指针的前置++与后置++的区别

 

//代码片段一:

int arr[] = {1,2,3,4,5,6,7,8,9,10};

int* parr1 = arr;

 

int A = *parr1++;

int B = *parr1;

 

cout << "A = " << A << endl;

cout << "B = " << B << endl;

 

输出结果:

 

A = 1;

B = 2;

 

代码片段二:

 

int arr[] = {1,2,3,4,5,6,7,8,9,10};

int* parr1 = arr;

 

int A = *++parr1;

int B = *parr1;

 

cout << "A = " << A << endl;

cout << "B = " << B << endl;

 

输出结果:

 

A = 2;

B = 2;

 

 

19.8.7* (地址解析符)与 ++ 的优先级

 

从上例中我们可以看到。当 * (作为地址解析符) ++ 同时作用在指针时,不管是前置还是++,都要比*有更高的优先级。比如代码中的:

 

int A = *parr++;

 

我们来一个反证:假设*的优先级比++高,那么,应先计算:

 

*parr 结果为: 1 (第一个元素)

然后计算  1++ ,结果为:2。

 

但实验发现结果为 1,这个1 又是如何来的呢?有点复杂。

首先,++优先计算,所以应先计算:parr++

结果是parr指向了下一个元素:2。因为这是后置++,所以,它必须返回自己计算之前的值;所以,在改变parr之前,编译程序会生成一个临时变量,计算原先parr的值。我们假设为 old_parr 。下面是第二步操作:

A = *old_parr

由于 old_parr parr 原来的值,指向第一个元素,所以 A 得到值: 1 。

 

可见,后置 ++ 或 后置-- 操作,需要系统生成一个临时变量。

如果这个变量占用的内存空间很小(比如指针类型总是只有4字节),则该操作带来的,对程序速度的负面影响可以不计,如果变量很大,并且多次操作。则应在可能的情况下,尽量使用前置++或前置--操作。

 

你自然会问,前置++就不会产生临时变量吗?我们来试试。

 

int A = *++parr;

 

同样,++优先级大于*,所以先计算:++parr

结果parr 指向下一个元素。因为这是前置++,所以,它只需要返回的,正是自己计算之后的值。下一步是:

A = *parr;

由于 parr 此时已完成++操作,指向下一个元素。所以 A 得到值: 2

 

19.8.8上机实验六:指针的 ++与--操作

 

int arr [] = {1,2,3,4,5};

 

int* parr = arr;

 

//前进 ++

for (int i=0; i < 5; i++) //如果为了优化,你可以写成: ++i :)

{

   cout << *parr << endl;

   parr++;   //如果为了优化,你可以写成:++parr :D

 

   /*

     上面两句你还可以写成一句: 

     cout << *parr++ << endl;  //这里,你可不能为了优化写成: *++parr.

  */

}

 

//后退 --:

for (int i=0; i < 5; i++)

{

   parr--;

   cout << *parr << endl;

}

 

输出结果:

(指针的++与--)

 


posted on 2007-09-06 01:23 旅途 阅读(1378) 评论(0)  编辑 收藏 引用 所属分类: C/C++


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理