Chinaunix首页 | 论坛 | 博客
  • 博客访问: 281229
  • 博文数量: 42
  • 博客积分: 590
  • 博客等级: 中士
  • 技术积分: 447
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-04 01:15
个人简介

健康快乐 虚怀若谷 淡定从容

文章分类

全部博文(42)

分类: C/C++

2011-08-21 02:31:03

/***************************************************

操作系统:WIN7

CPU : Intel i3

编译环境: C-FREE 5.0

编译器: C89

******************************************************/

#include

#include

char string[2000];
int main()

int index;
int *p;
p=string;

 for(index=0;index<500;index++)  
{
  p[index] = -1 - index;
 } 
   printf("strlen(string) = %d\n",strlen(string)); 
return 1;

}

运行结果:

    一开始,我看到这段代码的时候,就认为运行结果为2000. 当实际运行之后,嘿嘿,竟然是上图所示,很意外。跟网友讨论了一番,才明白其来龙去脉以及此段代码考察的知识点,当然,也发现自身的基础不是一般的差,需要多充电去复习那些最原始的东东。

    废话就不多说了,下面就分析一下这段代码:

    char string[2000];    //定义了一个长度为2000的字符型数组string,且默认情况下,其每个元素的                           //初值均为0x00.  

     int index;         //定义32位整型数据index
     int *p;            //定义指向32位整型数据的指针P;
     p=string;          //把string的初始地址赋给p,即p和string均指向相同的地址

    for(index=0;index<500;index++)    //循环500次,给p指向的500个整数赋值,地址从p 至 p+499
    {
        p[index] = -1 - index;
    }  

      printf("strlen(string) = %d\n",strlen(string));  //计算并输出string中第一次出现0x00之前                                                        //的数据个数。  

    如果对strlen()的特点和用法非常熟悉,那么这段代码对你来说已经懂了一半,抓着string中什么时候出现0x00这个点不放,去查找string中的元素。根据上面的for循环,可以得知代码通过给p中的元素赋值来间接地对string中的元素赋值,p中的一个元素就相当于string在内存中对应地址的的连续四个字节,由于intel的CPU支持的是小端模式,所以p[0] = -1在内存中的存放形式为 0xff 0xff 0xff 0xff(内存地址由低到高排列),p[1] = -2   在内存中的存放形式为 0xfe 0xff 0xff 0xff  ,。。。。,p[127] = -128 在内存中的存放形式为0x10 0xff 0xff 0xff ,  p[128] = -129 在内存中的存放形式为 0x7f 0xff 0xff 0xff, 。。。, p[255] = -256 在内存中的存放形式为 0x00 0xff 0xff 0xff, 到此,出现了一个0x00,所以当执行strlen时,在string中的第(255*4+1)个元素处停止,因此,输出为255*4 = 1020。为了更直观的看到前面所述的情况特在代码中添加了打印信息,如下所示:

int main()
{
char dd = 128;
int index;
int *p;
p=string;
for(index=0;index<500;index++)
{
p[index] = -1-500;
}
 printf("string[0*4] = %d\n",string[0*4]);//index = 0时,p[0]的低字节
 printf("string[127*4] = %d\n",string[127*4]);//index=127,p[127]的低字节
printf("string[128*4] = %d\n",string[128*4]);
//index=128,p[128]的低字节
printf("string[129*4] = %d\n",string[129*4]);
//index=129,p[129]的低字节
printf("string[254*4] = %d\n",string[254*4]);
//index=254,p[254]的低字节
printf("string[255*4] = %d\n",string[255*4]);
//index=255,p[255]的低字节
printf("strlen(string) = %d\n",strlen(string));
return 1;
}

运行结果如下:



总结了一下,这段简短的代码大概包含了下面四个知识点:

(1)不同数据类型的长度以及取值范围;

(2)数据在内存中的存放形式;

(3)不同CPU平台的数据存放模式;

(4)函数strlen()的特点。


思考一下:

当CPU支持大端模式时,那么输出会是多少呢?

当p的元素值为正值时,假如从按照1+index的形式进行变化,输出结果又是多少?


下面再给两个有点变化的代码:

(1)

#include
#include
char string[2001];
int main()
{
char dd = 128;
int index;
int *p;
p=string;
for(index=0;index<500;index++)
{
p[index] = -1;
}
/*
printf("string[0*4] = %d\n",string[0*4]);
printf("string[127*4] = %d\n",string[127*4]);
printf("string[128*4] = %d\n",string[128*4]);
printf("string[129*4] = %d\n",string[129*4]);
printf("string[254*4] = %d\n",string[254*4]);
 printf("string[255*4] = %d\n",string[255*4]); */

printf("strlen(string) = %d\n",strlen(string)); 
return 1;
}

(2)

#include
#include
char string[2000];
int main()
{
char dd = 128;
int index;
int *p;
p=string;
for(index=0;index<500;index++)
{
p[index] = -1;
}

/*
printf("string[0*4] = %d\n",string[0*4]);
printf("string[127*4] = %d\n",string[127*4]);
printf("string[128*4] = %d\n",string[128*4]);
printf("string[129*4] = %d\n",string[129*4]);
printf("string[254*4] = %d\n",string[254*4]);
 printf("string[255*4] = %d\n",string[255*4]); */

printf("strlen(string) = %d\n",strlen(string)); 

return 1;
}

二者的运行结果相同么?为什么?

很显然,不一定相同,第一种情况输出肯定为2000,第二种的不确定,因为超出数组string的边界了,边界外的数值不确定是多少,因为不确定何时停止。

阅读(4281) | 评论(9) | 转发(3) |
给主人留下些什么吧!~~

林生20102011-09-14 11:06:40

amarant: 不对吧。。
char str[2000]其分配的内存是栈,如果没有初始化的话,其值是随机的!.....
嗯,如果没有初始化,可能是随机的,因为这个跟编译器有关。在这里,我使用的是C-Free,编译器为C89,已经给string的元素分配了初值0x00,这点是肯定的。

amarant2011-09-13 20:59:44

不对吧。。
char str[2000]其分配的内存是栈,如果没有初始化的话,其值是随机的!

zhanglistar2011-08-25 14:26:06

林生2010: 对的,补码才是数据在内存中的存放形式,掌握补码与原码的转换关系,对理解这段代码很重要。 而strlen,就是要求对这个函数的用法比较熟悉。.....
恩~glibc下对strlen的实现也是比较高效的。

vivieu2011-08-23 12:53:20

似乎简单的问题复杂化了~

GFree_Wind2011-08-23 11:59:33

其实挺简单的。。。因为0即为'\0',strlen就会截止。。。。如果没有'\0',就会一直向后查找这个结束符,就会根据当时的内存的随机值,长度不一。