sizeof与strlen()、递归优化题解

sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数。

与strlen的区别:

一、sizeof

是运算符,确切的说是一个编译时运算符,参数可以是数组、指针、类型、对象、函数等。用于统计类型或者变量所占的内存字节数由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小。

二、strlen()

是C标准库中的字符串函数,要在运行时才能计算参数必须是字符型指针(char*), 且必须是以'\0'结尾的。它的功能是:返回字符串的长度。该字符串可能是自己定义的,也可能是内存中随机的,该函数实际完成的功能是从代表该字符串的第一个地址开始遍历,直到遇到结束符'\0'。返回的长度大小不包括'\0'。

三、实例

1、char *str = "hello";

      strlen(str); //它的值是5,因为hello这个字符串有5个字符
             sizeof(str); //它的值是4,因为char *是一个指针类型,它占4个字节。
             sizeof("hello"); //它的值是5,是因为hello有5个字符,每一个字符占1个字节。
     2、int a[2] = {0};
            sizeof(a); //它的值是8,因为a中有2个int型变量,每个int型占4个字节,所以8字节
   strlen(a) //a相当于一个指针,但是strlen只能接受char*类型,所以编译时出错

3、char arr[10] = "Hello";
              int len_one = strlen(arr);
              int len_two = sizeof(arr); 
              cout << len_one << " and " << len_two << endl; 
    输出结果为:5 and 10
 
strlen只关心存储的数据内容,不关心空间的大小和类型。    
        sizeof返回定义arr数组时,编译器为其分配的数组空间大小,不关心里面存了多少数据(10x1)。     
   4、char * parr = new char[10];
              int len_one = strlen(parr);
              int len_two = sizeof(parr);
              int len_three = sizeof(*parr);
              cout << len_one << " and " << len_two << " and " << len_three << endl;
    输出结果:3 and 4 and 1
      第一个输出结果3实际上每次运行可能不一样,这取决于parr里面存了什么(从parr[0]开始直到遇到第一个'\0'结束);
      第二个结果实际上本意是想计算parr所指向的动态内存空间的大小,但是事与愿违,sizeof认为parr是个字符指针,因此返回的是该指针所占的空间(指针的存储用的是长整型,所以为4)
     第三个结果,由于*parr所代表的是parr所指的地址空间存放的字符,所以长度为1。

 
 
面试题:定义一个空的数据类型,里面没有任何成员变量和成员函数,对该类型求sizeof,得到的结果是多少?
答案:是1,为什么不是0?空类型的实例中不包含任何信息,本来求sizeof应该是0,但是当我们声明该类型的实例时,它必须在内存中占有一定的空间,否则无法使用这些实例(也就不能求sizeof了),至于占用多少内存,由编译器决定,Visual Studio中每个空类型的实例占用1字节的空间。
扩展1:如果在该类型中添加一个构造函数和析构函数,再求sizeof,得到的结果是多少?
答案:还是1。调用构造函数和析构函数只需要知道函数的地址即可,而这些地址只与类型相关,而与类型的实例无关,编译器也不会因为这两个函数而在实例内添加任何额外的信息
注:不管添加的是构造函数还是析构函数还是其它任何类型的函数,都是这个结果。
扩展2:那如果把析构函数标记为虚函数呢?
答案:C++的编译器一旦发现一个类型中有虚函数,就会为该类型生成虚函数表,并在该类型的每一个实例中添加一个指向虚函数表的指针,在32位机器上,一个指针占4字节空间,因此求sizeof得到4;如果是64位则为8。测试用例:
#include <stdio.h>

struct nullType { };

struct type1 
{
	type1() {}
	~type1() {}
	int print() { printf("Alexia"); return 0; }
};

struct type2 
{
	type2() {}
	virtual ~type2() {}
};

int main() 
{
	printf("sizeof(nullType) = %d\n", sizeof(nullType));
	printf("sizeof(type1) = %d\n", sizeof(type1));
	printf("sizeof(type2) = %d\n", sizeof(type2));

	return 0;
}

原题

代码的优化,给出下一段代码,请做出最好的优化

int f(int n) {
    if(n<=4)
        return n*n;
    else {
        return f(n-4)*f(n-1) -f(n-2)*f(n-2);
    }
}

解答

无非是将递归转化为循环,防止重复计算中间值,跟斐波那契数列f(n)=f(n-1)+f(n-2)一样,解决方式也一样,就是利用几个临时变量保存中间值,然后每次循环都更新临时变量即可。过程没啥好说的,直接给出代码即可。

int f2(int n) {
    int first = 1;
    int second = 4;
    int third = 9;
    int fourth = 16;

    if(n<=4)
        return n*n;

    for(int i = 5; i <= n; ++i) {
        int tmp = fourth * first - third * third;
        first = second;
        second = third;
        third = fourth;
        fourth = tmp;
    }

    return fourth;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值