Chinaunix首页 | 论坛 | 博客
  • 博客访问: 857296
  • 博文数量: 254
  • 博客积分: 5350
  • 博客等级: 大校
  • 技术积分: 2045
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 13:27
文章分类

全部博文(254)

文章存档

2015年(1)

2014年(9)

2013年(17)

2012年(30)

2011年(150)

2010年(17)

2009年(28)

2008年(2)

分类: C/C++

2011-09-10 11:34:37

sizeof和strlen 比较延伸开来
看一个小程序输出:
#include
int main(void){
char * str1="abcde";
char str2[]="abcde";
char str3[8]={'a',};
char ss[]="0123456789";
printf("sizeof(str1)=%ld ",sizeof(str1));
printf("sizeof(str2)=%d ",sizeof(str2));
printf("sizeof(str3)=%d ",sizeof(str3));
printf("sizeof(ss)=%d\n",sizeof(ss));
return 0;

}

sizeof(str1)=8 sizeof(str2)=6 sizeof(str3)=8 sizeof(ss)=11
[root@ethanTest cstudy]# uname -a
Linux ethanTest 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux
百度有最佳答案
首先说明一点,char类型占一个字节,所以sizeof(char)是1,这点要理解 str1是一个指针,只是指向了字符串"absde"而已。所以sizeof(str1)不是字符串占的空间也不是字符数组占的空间,而是一个字符型指针占的空间。
所以sizeof(str1)=sizeof(char*)=4,在C/C++中一个指针占4个字节 str2是一个字符型数组。C/C++规定,对于一个数组,返回这个数组占的总空间,所以sizeof(str2)取得的是字符串"absde"占的总空间。
"absde"中,共有a b s d e \0六个字符,
所以str2数组的长度是6,所以sizeof(str2)=6*sizeof(char)=6 str3已经定义成了长度是8的数组,所以sizeof(str3)为8 str4和str2类似,'0' '1' ... '9'加上'\0'共11个字符,所以ss占的空间是8 总之,对于指针,sizeof操作符返回这个指针占的空间,一般是4个字节(32位系统);而对于一个数组,
sizeof返回这个数组所有元素占的总空间。char*与char[]容易混淆,一定要分清
,而且char*="aaa"的写法现在不被提倡,应予以避免 而strlen不区分是数组还是指针,就读到\0为止返回长度。而且strlen是不把\0计入字符串的长度的

这里前面都对的,但对于64位系统,这个指针是占8个字节。

将这个程序再改改比较下;
#include
int main(void){
char * str1="abcde";
char str2[]="abcde";
char str3[8]={'a',};
char ss[]="0123456789";
printf("sizeof(str1)=%ld ",sizeof(str1));
printf("sizeof(str2)=%ld ",sizeof(str2));
printf("sizeof(str3)=%ld ",sizeof(str3));
printf("sizeof(ss)=%ld\n",sizeof(ss));
printf("strlen(str1)=%d,strlen(str2)=%d,strlen(str3)=%d,strlen(ss)=%d\n",
strlen(str1), strlen(str2), strlen(str3), strlen(ss));
return 0;

}

sizeof(str1)=8 sizeof(str2)=6 sizeof(str3)=8 sizeof(ss)=11
strlen(str1)=5,strlen(str2)=5,strlen(str3)=1,strlen(ss)=10

还有点需要特别提醒,字符串在初始化时尽量不要指定大小,或者在指定时要考虑'\0'这个NULL结束符
所占的一个空间
,否则可能读取时超出界限,引出异常。如将上面的ss再改动下;
#include
int main(void){
char * str1="abcde";
char str2[]="abcde";
char str3[8]={'a',};
char ss[10]="0123456789";
printf("sizeof(str1)=%ld ",sizeof(str1));
printf("sizeof(str2)=%ld ",sizeof(str2));
printf("sizeof(str3)=%ld ",sizeof(str3));
printf("sizeof(ss)=%ld\n",sizeof(ss));
printf("strlen(str1)=%d,strlen(str2)=%d,strlen(str3)=%d,strlen(ss)=%d\n",
strlen(str1), strlen(str2), strlen(str3), strlen(ss));
return 0;

}
sizeof(str1)=8 sizeof(str2)=6 sizeof(str3)=8 sizeof(ss)=10
strlen(str1)=5,strlen(str2)=5,strlen(str3)=1,strlen(ss)=11

这结果刚好反了,如果在不同的机器,不同时间这个strlen可能又有不同。。。

有了上面的认识再来看一个程序,是linux环境下c编程书上的一个例子。本意是解决
内存溢出的实例:

#include
#include
void upcase(char *inputstring,char *newstring);
int main(void)
{
    char str1[4];
    upcase("Hello",str1);
    printf("str1=%s\n",str1);
    return 0;
}
void upcase(char *inputstring,char *newstring)
{
    int counter;
    strncpy(newstring,inputstring,sizeof(newstring)-1);
    for(counter=0;counter    {
        if(newstring[counter]>=97 && newstring[counter]<=122)
            newstring[counter]-=32;
    }
    *(newstring+strlen(newstring)) = 0x00;
    return newstring;
}

这个例子在32位系统上跑起来应该没有问题,初看起来也很正确;但你稍稍变化下str1初始大小比如12,改动下字符串如。hello,world之类的,就会发现结果完全不对。。

这里关键是sizeof(newstring),这里实际是对指针变量取sizeof,在我64位机上结果会永远为8,32位为4;这样明显偏离了原意。。还有最后的 *(newstring+strlen(newstring)) = 0x00;strcpy函数在目的空间足够情况下会将空闲空间填为'\0', 可用man 3 strcpy查看下帮助,了解;实际这步在前面已经减1情况下是多余的操作。。。解决方案,自己思考下吧。。~+~
阅读(712) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~