每日一题(六)
9.21数组、字符串的存取效率
在程序中,对数组和字符串的存取,哪个更有效率?
先看一段程序:
#include "stdio.h"
int main() {
char a = 1;
char c[] = "123456789";
char *p = "123456789";
a = c[1];
a = p[1];
return 0;
}
声明了一个数组c和一个字符串p,然后同样读取其中的一个值,对应的汇编代码如下:
10:a=c[1];
004010678A4DF1 movcl,byteptr[ebp-0Fh]
0040106A884DFC movbyteptr[ebp-4],cl
11:a=p[1];
0040106D8B55EC movedx,dwordptr[ebp-14h]
004010708A4201 moval,byteptr[edx+1]
004010738845FC movbyteptr[ebp-4],al
可以看出对于a = c[1]的操作,是直接将数组中字符串的元素读取到c1寄存器中(也就是a)
对于a = p[1]的操作,显示将指针的值edx中,再根据地址读取字符元素
所以数组的读取比字符串的读取要有效率,即在栈上的数组比指针指向的字符串要读取快。
9.22 求一个int数据 二进制中1的个数
#include <iostream>
using namespace std;
int fun (int x) {
int count = 0;
while (x) {
x &= (x-1);
++count;
}
return count;
}
int main() {
int x = 0;
cin>>x;
cout<<"ans is :"<<fun(x)<<endl;
return 0;
}
分析:把一个整数减去1,再和原整数做 & 运算,就会把整数最右边一个1变成0,通过while(x)来计数有多少个1.
9.23 指针与引用的区别
- 引用只是变量的一个别名,内部是依靠只读指针实现的,引用本身不占用内存空间,不能建立数组的引用
- 引用在初始化的时候就要指明赋值;而且指针可以在允许的情况下任意时刻赋值
- 引用不能为NULL;指针可以为NULL
- 引用保存的是被引用变量的地址
sizeof 引用
的大小是被引用变量的大小;sizeof 指针
的大小是指针本身的大小- 引用在源代码级相当于一个普通的变量,但是作为函数参数时,传递的是变量地址
- 指针可以有多级,引用只能一层
- 引用作为函数返回值传递的时候,不能返回局部变量的引用、函数内new的内存的引用
9.24 编写strcpy
**已知strcpy的函数原型:char *strcpy(char strDest, const char strSrc)其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数,请编写函数 strcpy。
#include <stdio.h>
#include <assert.h>
cahr* strcpy (char *strDest, const char *strSrc)
{
assert ((strDest != NULL) && (strSrc != NULL));
char *addr = strDset;
while ((*strDest++ = *strSrc++) != '\0');
return addr;
}
- assert是宏,不是函数,其的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行
- strcpy函数会连‘\0’一起拷贝
- 要用一个临时的变量保存目标字符串的首地址,最后返回这个临时变量
- 返回值为char* 是为了支持链式表达式
9.25引用作为函数参数的的注意
- 不能返回局部变量的引用
- 不能返回函数内部new产生的引用
- 传递引用给函数与传递指针给函数的效果一样,但是指针传递参数在函数中要分配空间的,而且在函数内使用指针变量名进行运算,程序的可读性会比较差
- 使用引用传递进来的参数,在函数运行过程中是没有产生实参的副本,是直接对地址进行操作的,所以当形参传递的数据比较大的时候,引用传递参数效果比较好