今天在做项目的过程中遇到了一些关于strlen与sizeof的问题,特地的查证了一下,比较了他们的区别
看了很多人的博客,发现他们大都从这两个关键词的使用情景来考察,而本文将会从他们的源码角度,对这两个关键词进行分析。
strlen的源码来自于Lib/string.c中,是一个函数
size_t strlen(const char *s)
{
const char *sc;
for (sc = s; sc != '\0'; s++);
return sc - s;
}
而sizeof是编译器由定义的一个操作符,主要是由编译器识别出sizeof括号内的符号是表达式(变量),数组,结构体/对象,还是类型,并分别得这些符号在内存中占用内存的值。
举例来说,对于类型
#define mysizeof(type) ((char *)((type *)(1) + 1) - (char *)((type *)(1)))
对于变量
#define mysizeof(var) ((char *)(&(var) + 1) - (char *)&(var))
对于结构体,还要进行padding,具体的伪代码见
从上面的两个关键词的来源可以看到
strlen以字符为单位,依次寻找指针指向内存中的'\0',直到找到为止,并计算出不包含'\0’的字符个数
sizeof是编译器识别出符号的类型后,进行求内存大小的操作。
以下面的代码为例,介绍sizeof与strlen容易混淆的地方。
下面的代码在Ubuntu 10.10上进行了测试
- #include <stdio.h>
- #include <string.h>
- int main()
- {
- int a[10];
- char buf[10] = "hello";
- char *c = "hello";
- char d[] = "hello";
- a[0] = 0xf0f0f0f0f;
- a[1] = 0xf0f0f0f0f;
- a[2] = '\0';
- printf("sizeof a[10] is %d\n", sizeof(a));
- printf("sizeof buf[10] is %d\n", sizeof(buf));
- printf("sizeof c is %d\n", sizeof(c));
- printf("sizeof d[] is %d\n", sizeof(d));
- printf("strlen a[10] is %d\n", strlen(a));
- a[0] = 'b';
- printf("strlen a[10] is %d\n", strlen(a));
- printf("strlen buf[10] is %d\n", strlen(buf));
- printf("strlen c is %d\n", strlen(c));
- printf("strlen d[] is %d\n", strlen(d));
- return 0;
- }
得到结果如下:
- sizeof a[10] is 40
- sizeof buf[10] is 10
- sizeof c is 4
- sizeof d[] is 6
- strlen a[10] is 8
- strlen a[10] is 1
- strlen buf[10] is 5
- strlen c is 5
- strlen d[] is 5
结果解释:
先讨论sizeof:
对于数组,sizeof会自动识别他们的类型,得出数组以char为单位的长度值
对于通过buffer[10]和char *c表示的字符串,他们sizeof后的值是不一样的,因为他们代表不用的意义,sizeof(buffer)表示求buffer[10]数组的长度;sizeof(c)表示求指针c的长度。
而char d[] = "hello"中d是一个数组,它有6个元素,最后一个元素是'\0',所以sizeof的结果是6。
再讨论strlen, 对于整数数组,他们仍然是以字符为单位搜索内存中的'\0'字符,考虑到int a[10]数组在内存中的值:
当strlen搜索到第9个字符时,遇到'\0'字符,停止索索,故strlen(a)为8。
当a[0]='b'时,内存中的值为:
由于X86系统是小端模式,即高位存储在高地址处,那么strlen(a)时会首先搜索到一个ascii码为0x62的值,然后发现字符'\0',停止搜索,得到strlen(a)=1的结果。
下面要注意的是strlen("hello")的结果是5,即不会包含'\0'字符。
阅读(334) | 评论(0) | 转发(0) |