前端性能优化--6大角度综合型优化方案
extern "C"的运用方式
能够是单一语句
extern "C" doublesqrt(double);
能够是复合语句, 相当于复合语句中的声明都加了extern "C"
extern "C"
{
double sqrt(double);
int min(int, int);
}
3.能够包含头文件,相当于头文件中的声明都加了extern"C"
extern "C"
{
#include
}
不能够将extern"C" 添加在函数内部
假如函数有多个声明,能够都加extern"C", 也能够只呈现在第一次声明中,后面的声明会承受第一个链接指示符的规则。
除extern"C", 还有extern "FORTRAN" 等。
问题5:sizeof关键字的作用?
答:
sizeof是在编译阶段处置,且不能被编译为机器码。sizeof的结果等于对象或类型所占的内存字节数。sizeof的返回值类型为size_t。
变量:int a;
sizeof(a)为4;
指针:int *p;
sizeof(p)为4;
数组:int b[10];
sizeof(b)为数组的大小,4*10;int c[0];
sizeof(c)等于0
构造体:struct (int a;
char ch;
)s1;
sizeof(s1)为8 与构造体字节对齐有关。
留意:不能对构造体中的位域成员运用sizeof
sizeof(void)等于1
sizeof(void *)等于4
3 构造体
问题1:构造体的赋值?
答:
C言语中对构造体变量的赋值或者在初始化或者在定义后按字段赋值。
方式1:初始化
struct tag
{
chara;
int b;
}x = {‘A’, 1};
/初始化/
或
struct tag
{
char a;
int b;
};
struct tag x = {‘A’,1};
/在定义变量时初始化/
GNU C中可运用另外一种方式:
struct tag
{
char a;
int b;
}x =
{
.a = ‘A’,
.b =1;
};
或
struct tag
{
char a;
int b;
};
struct tag x =
{
.a= ‘A’,
.b=1,
};
方式2:定义变量后按字段赋值
struct tag
{
char a;
int b;
};
struct tag x;
/定义变量/
x.a = ‘A’;
/按字段赋值/
x.b = 1;
/按字段赋值/
而当你运用初始化的方式来赋值时,如x = {‘A’,1};
则出错。
方式3:构造变量间的赋值
struct tag
{
chara;
int b;
};
struct tag x,y;
x.a=’A’;
x.b=1;
y = x;
/构造变量间直接赋值/
问题2:构造体变量如何比拟?
答:固然构造体变量之间能够经过=直接赋值,但不同经过比拟符如==来比拟,由于比拟符只作用于根本数据类型。这个时分,只能经过int memcmp(const void s1, const void s2, size_t n);
来停止内存上的比拟。
问题3:构造体位域
答:
位域是一个或多个位的字段,不同长度的字段(如声明为unsigned int类型)存储于一个或多个其所声明类型的变量中(如整型变量中)。
【前端性能优化--6大角度综合型优化方案】位域的类型:能够是char、short、int,多数运用int,运用时最好带上signed或unsigned
位域的特性:字段能够不命名,如unsignedint :1;
可用来填充;unsigned int :0;
0宽度用来强迫在下一个整型(因而处是unsigned int类型)边境上对齐。
位域的定义:
struct st1
{
unsigned chara:7;
/字段a占用了一个字节的7个bit/
unsigned charb:2;
/字段b占用了2个bit/
unsigned charc:7;
/字段c占用了7个bit/
}s1;
sizeof(s1)等于3。由于一个位域字段必需存储在其位域类型的一个单元所占空间中,不能横跨两个该位域类型的单元。也就是说,当某个位域字段正处于两个该位域类型的单元中间时,只运用第二个单元,第一个单元剩余的bit位置补(pad)0。
于是可知Sizeof(s2)等于3*sizeof(int)即12
struct st2
{
unsigned inta:31;
unsigned intb:2;
/前一个整型变量只剩下1个bit,容不下2个bit,所以只能寄存在下一个整型变量/
unsigned int c:31;
}s2;
位域的益处:
1.有些信息在存储时,并不需求占用一个完好的字节, 而只需占几个或一个二进制位。例如在寄存一个开关量时,只要0和1 两种状态,用一位二进位即可。这样俭省存储空间,而且处置烦琐。这样就能够把几个不同的对象用一个字节的二进制位域来表示。
2.能够很便当的应用位域把一个变量给按位合成。比方只需求4个大小在0到3的随即数,就能够只rand()一次,然后每个位域取2个二进制位即可,省时省空间。
位域的缺陷:
不同系统对位域的处置可能有不同的结果,如位段成员在内存中是从左向右分配的还是从右向左分配的,所以位域的运用不利于程序的可移植性。
问题4:构造体成员数组大小为0
构造体数组成员的大小为0是GNU C的一个特性。益处是能够在构造体中分配不定长的大小。如
typedef struct st
{
inta;
int b;
char c[0];
}st_t;
sizeof(st_t)等于8,即char c[0]的大小为0.
define SIZE 100
st_t s = (st_t )malloc(sizeof(st_t) + SIZE);
4 函数
问题1:函数参数入栈次第
答:
C言语函数参数入栈次第是从右向左的,这是由编译器决议的,更详细的说是函数调用商定决议了参数的入栈次第。C言语采用是函数调用商定是__cdecl的,所以关于函数的声明,完好的方式是:int __cdecl func(int a, int b);
问题2:inline内联函数
答:
inline关键字仅仅是倡议编译器做内联展开处置,即是将函数直接嵌入调用程序的主体,省去了调用/返回指令。
5 内存分配回收
问题1: malloc/free与new/delete的区别
答:
1) malloc与free是C/C++言语的规范库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
2) 关于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的请求。对象在创立的同时要自动执行结构函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不可以把执行结构函数和析构函数的任务强加于malloc/free。因而C++言语需求一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清算与释放内存工作的运算符delete。留意new/delete不是库函数。
我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有结构与析构的过程,对它们而言malloc/free和new/delete是等价的。
3) 既然new/delete的功用完整掩盖了malloc/free,为什么C++不把malloc/free淘汰出局呢?这是由于C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。
假如用free释放“new创立的动态对象”,那么该对象因无法执行析构函数而可能招致程序出错。假如用delete释放“malloc申请的动态内存”,结果也会招致程序出错,但是该程序的可读性很差。所以new/delete必需配对运用,malloc/free也一样。
问题2:malloc(0)返回值
答:假如恳求的长度为0,则规范C言语函数malloc返回一个null指针或不能用于访问对象的非null指针,该指针能被free平安运用。
6 可变参数列表
可变参数列表是经过宏来完成的,这些宏定义在stdarg.h头文件,它是规范库的一局部。这个头文件声明了一个类型va_list和三个宏:va_start、va_arg和va_end。
typedef char *va_list;
define va_start(ap, A) (void)((ap) = (char *)&(A) + _Bnd(A, _AUPBND))
define va_arg(ap, T) (*(T )((ap) += _Bnd(T, _AUPBND)) - _Bnd(T, _ADNBND)))
define va_end(ap) (void)0
int print(char *format, …)
宏va_start的第一个参数是va_list类型的变量,第二个参数是省略号前最后一个有名字的参数,功用是初始化va_list类型的变量,将其值设置为可变参数的第一个变量。
宏va_arg的第一个参数是va_list类型的变量,第二个参数是参数列表的下一个参数的类型。va_arg返回va_list变量的值,并使该变量指向下一个可变参数。
宏va_end是在va_arg访问完最后一个可变参数之后调用的。
问题1:完成printf函数
/*(转载)
A simple printf function. Only support the following format:
Code Format
%c character
%d signed integers
%i signed integers
%s a string of characters
%o octal
%x unsigned hexadecimal
*/
int my_printf( const char* format, ...)
{
va_list arg;
int done = 0;
va_start (arg, format);
while( *format != '\0')
{
if( *format == '%')
{
if( *(format+1) == 'c' )
{
char c = (char)va_arg(arg, int);
putc(c, stdout);
} else if( *(format+1) == 'd' || *(format+1) == 'i')
{
char store[20];
int i = va_arg(arg, int);
char* str = store;
itoa(i, store, 10);
while( *str != '\0') putc(*str++, stdout);
} else if( *(format+1) == 'o')
{
char store[20];
int i = va_arg(arg, int);
char* str = store;
itoa(i, store, 8);
while( *str != '\0') putc(*str++, stdout);
} else if( *(format+1) == 'x')
{
char store[20];
int i = va_arg(arg, int);
char* str = store;
itoa(i, store, 16);
while( *str != '\0') putc(*str++, stdout);
} else if( *(format+1) == 's' )
{
char* str = va_arg(arg, char*);
while( *str != '\0') putc(*str++, stdout);
}// Skip this two characters.format += 2;
} else {
putc(*format++, stdout);
}
}
va_end (arg);
return done;
}
7 其他
问题1:ASSERT()的作用
答:ASSERT()是一个调试程序时经常运用的宏,在程序运转时它计算括号内的表达式,假如表达式为FALSE (0), 程序将报告错误,并终止执行。假如表达式不为0,则继续执行后面的语句。这个宏通常原来判别程序中能否呈现了明显非法的数据,假如呈现了终止程序以免招致严重结果,同时也便于查找错误。例如,变量n在程序中不应该为0,假如为0可能招致错误,你能够这样写程序:
......
ASSERT( n != 0);
k = 10/ n;
.....
ASSERT只要在Debug版本中才有效,假如编译为Release版本则被疏忽。
assert()的功用相似,它是ANSI C规范中规则的函数,它与ASSERT的一个重要区别是能够用在Release版本中。
问题2:system("pause"); 的作用
答:系统的暂停程序,按恣意键继续,屏幕会打印,"按恣意键继续。。。。。"省去了运用getchar();
问题3:请问C++的类和C里面的struct有什么区别?
推荐阅读
- Jsr303做前端数据校验
- 数据库设计与优化
- Improve|Improve Nested Conditionals(优化嵌套的条件语句) 面对大量的if-else语句
- 7、前端--jQuery简介、基本选择器、基本筛选器、属性选择器、表单选择器、筛选器方法、节点操作、绑定事件
- 首屏时间,你说你优化了,那你倒是计算出给给我看啊!
- 前端代码|前端代码 返回顶部 backToTop
- 数据库|SQL行转列方式优化查询性能实践
- 性能测试中QPS和TPS的区别
- #12-UITableView|#12-UITableView 优化方案
- javascript|javascript 性能测试笔记