【C语言】sizeof与strlen

目录

0.阅读引用

1.sizeof

1.1 sizeof是运算符

1.2 数据类型

1.3 变量 

1.4 表达式

1.5 sizeof可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用

2.strlen

2.1 strlen测量的是字符的实际长度,不包含'\0'

2.2 ‘sizeof’ on array function parameter ‘str’ will return size of ‘char*’

2.3 字符数组的初始化注意点

3.sizeof与strlen的比较


0.阅读引用

引用阅读1

引用阅读2

zu

注意移植性和通用性

1.sizeof

1.1 sizeof是运算符

sizeof的操作数可以是数据类型、函数、变量.

1.2 数据类型

例如我们要计算一个int型数据的存储空间可以用:sizeof(int),需要注意的是sizeof的操作数是数据类型
时要加括号,其数值大小为该数据类型所占的存储空间的字节数.

1.3 变量 

sizeof(变量名)
如果定义 int a ,可以使用sizeof(a)计算a变量占据的存储空间,具体大小与a的类型有关.

注意:由于sizeof是操作符sizeof a(注意:sizeof和a之间有一个空格)或sizeof(a)都可以,可以不使用括
号),如果操作数是数组名则给出数组所占用内存的字节数. 如果数组名做函数的参数传递时退化为指针.

1.4 表达式

sizeof(表达式)
sizeof可以对一个表达式求值,编译器根据表达式的最终结果类型来确定大小,一般不会对表达式进行计
算.例如:sizeof(1+1.5).


#include <stdio.h>
int main(){
   int a;
   printf("sizeof a is %d .\n",sizeof a); 
   printf("sizeof(1+1.5) is %d\n",sizeof(1+1.5)); // 64位上是8
}

1.5 sizeof可以对一个函数调用求值,其结果是函数返回类型的大小,函数并不会被调用

#include <stdio.h>
int myprint()
{
   printf("hello world\n");
   return 0;
}

int main()
{
    printf("sizeof(myprint())is %d \n",sizeof(myprint()));
    printf("sizeof(myprint)is %d \n",sizeof(myprint));
    return 0;
}


结果只打印函数返回类型的sizeof值,并没有打印hello world说明函数myprint并没有调用.
C99标准规定,函数、不能确定类型的表达式以及位域(bit-field)成员不能被计算sizeof值,即下面这些写法都是错误的,
如:
(1)sizeof(myprint)---这个现在好像是可以的了.
(2)sizeof一个void返回类型的函数如:
void foo () { }
sizeof(foo());---这个现在好像也是可以的了.
(3)位域,这个还是不能通过的;
struct S
{
   unsigned int f1:1;
   unsigned int f2:5;
   unsigned int f3:12;
};
sizeof( S.f1 );


测试代码:
#include <stdio.h>
struct S
{
unsigned int f1:1;
unsigned int f2:5;
unsigned int f3:12;
};
int myprint()
{
   printf("hello world\n");
   return 0;
}
void foo(){}

int main()
{
    printf("sizeof(myprint())is %d \n",sizeof(myprint()));
    printf("sizeof(foo())is %d \n",sizeof(foo()));
    printf("sizeof(myprint)is %d \n",sizeof(myprint));
    //printf("sizeof(S.f1)is %d \n",sizeof(S.f1));
    return 0;
}


注意:
我这里有些C99禁止的规则可以在我的gcc编译器下编译通过且可以执行,为了保证移植可靠性,我们
要注意各个编译器和平台下的移植性,这里还需要多多测试.

2.strlen

2.1 strlen测量的是字符的实际长度,不包含'\0'


strlen的结果运行的时候才出来(不是编译期求值),是计算字符串长度的,其参数必须是字符型指针
(char*),头文件为#include<string.h>.

strlen 测量的是字符的实际长度,以'\0' 结束( 不包含'\0' ). 而sizeof 测量的是字符的分配大小,
如果未分配大小,则遇到'\0' 结束(包含'\0' ,也就是strlen测量的长度加1),如果已经分配内存大
小,返回的就是分配的内存大小.


测试代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int main(){
        char str[] = "Hello World";
        char str1[100] = "Hello World";
        const char *str2 = "Hello World";
        cout << strlen(str) << endl;  // 11
        cout << strlen(str1) << endl; // 11
        cout << strlen(str2) << endl; // 11
        cout << sizeof(str) << endl;  // 12
        cout << sizeof(str1) << endl; // 100
        cout << sizeof(str2) << endl; // 32位的机器上是4,64位的机器上是8
        return 0;
}

2.2 ‘sizeof’ on array function parameter ‘str’ will return size of ‘char*’

/*
在子函数中,sizeof会把从主函数中传进来的字符数组当作是指针来处理,指针的大小由机器来决定.
这种情况下在编译的时候会有警告,编程的时候要注意这一点,不要犯错.
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
void RightUpperCase( char str[] )    
{
        cout << "strlen(str) is " << strlen(str) << endl;
        for( size_t i=0; i<strlen(str); ++i )
                if( 'a'<=str[i] && str[i]<='z' )
                        str[i] -= ('a'-'A' );
}
void WrongUpperCase( char str[] )    
{
        cout << "被调用函数中sizeof(str)/sizeof(str[0]) is " << sizeof(str)/sizeof(str[0]) << endl;/*这句话编译的时候会有警告*/
        for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
                if( 'a'<=str[i] && str[i]<='z' )
                        str[i] -= ('a'-'A' );
}
int main(){
        char str[] = "aBcDeyyyyyyy";
        char str1[] = "aBcDeyyyyyyy";
        cout << "调用函数中sizeof(str)/sizeof(str[0]) " << sizeof(str)/sizeof(str[0]) << endl;
        RightUpperCase( str );
        cout << str << endl;
        WrongUpperCase( str1 );
        cout << str1 << endl;
}

2.3 字符数组的初始化注意点

#include <stdio.h>
#include <string.h>
 
int main()
{
    char str1[] = "hello";// 不定长的时候编译器会自动优化长度
    char str2[] = {'h', 'e', 'l', 'l', 'o', '\0'};// OK
    char str3[5] = {'h', 'e', 'l', 'l', 'o'}; // NOT OK,打印出的字符串与上下文有关,要注意用'\0'来标志字符串的结束,这里会产生内存溢出,如果这里写str3[6]暂时没有发现问题,但是是不严谨的,
    char str4[6] = "hello\0"; // OK,初始化字定长符数组的情况下要将'\0'考虑进去
    
    printf("str1:%s\n",str1);
    printf("str2:%s\n",str2);
    printf("str3:%s\n",str3);
    printf("str4:%s\n",str4);
    
    printf("sizeof(str1):%d\n", sizeof(str1));
    printf("sizeof(str2):%d\n", sizeof(str2));
    printf("sizeof(str3):%d\n", sizeof(str3));
    printf("sizeof(str4):%d\n", sizeof(str4));
    
    printf("strlen(str1):%d\n", strlen(str1));
    printf("strlen(str2):%d\n", strlen(str2));
    printf("strlen(str3):%d\n", strlen(str3));
    printf("sizeof(str4):%d\n", strlen(str4));
 
    return 0;
}

/*
运行结果如下图:
我们知道字符串是以 '\0' 为结束标志的,所以char str1[ ] = "hello" 等效于char str2[ ] = 
{'h' , 'e' , 'l' , 'l' , 'o' , '\0'} 。strlen函数求的是字符串的实际长度,它求得方法是从
开始到遇到第一个'\0',如果你只定义没有给它赋初值,这个结果是不定的,它会从首地址一直找下
去,直到遇到'\0'停止。而如果不在字符数组初始化的时候加上\0,那么strlen 得到的值就不是正确
的数值,打印出来的结果也不是想要的结果。因此我们要避免这种情况,在初始化的时候要记得加上 
\0,或者一次性赋初值。
*/

 

3.sizeof与strlen的比较

(1)strlen的结果要在运行的时候才能计算出来,是用来计算字符串的长度,不是类型占内存的大小,
而大部分编译程序在编译的时候就把sizeof计算过了是类型或是变量的长度.
(2)sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以'\0'结尾的.

 

 

 

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值