变长参数的讨论

前言 一直以来对变长参数都比较好奇,索性花时间解解痒. 先从数组指针来看 void test1(int* arr,int count) { int sum = 0; for (int *p = arr; p < arr + count; p++) { sum = sum+ *p; } printf("%d\n",sum ); } 代码较为简单,此处不再展开. 接下来是可变参数 可变参数需要使用 <stdarg.h> 头文件,请提前导入 什么是可变参数? 可变参数是函数或方法中形如int show(int a,...)这样的的参数 可变参数的相关规定 ... 不能单独出现,且只能放在参数列表中的最后 变长参数的类型没有限定,使用时最好统一类型,避免类型安全问题 变长参数的个数没有限定,调用时一般以0x00即 NULL/nil结尾 void test2(int a,...) { int sum = a; //声明变长参数列表vl va_list vl; //va_start :将变长参数的前一个参数的地址存入vl va_start(vl,a); int next; //va_arg :将vl向后偏移sizeof(int),并返回偏移后长度为sizeof(int)的数据 //判断 next 是否为 0x00 ,如果不为 0x00 则继续遍历 while( (next = va_arg(vl,int)) ) { sum+= next; } //释放变长参数列表vl va_end(vl); printf("%d\n",sum ); } 调用形式 int main(int argc,char * args[]) { int arr[] = {1,2,3,4,5}; //数组指针 test1(arr,5); printf("---------\n"); //变长参数 test2(1,2,3,4,5,6,NULL); return 0; } 输出结果 15 --------- 21 小结 ....

August 15, 2014

数据结构--栈

栈 栈是一种数据结构,其特点是后进先出(LIFO).计算机中有很多操作都采用了栈的数据结构,如浏览器的后退,文本编辑的撤销操作等. 栈的定义 栈的额定大小 栈的实际大小 栈的数据 栈的操作 入栈 出栈 清空栈 初始化栈 输出栈内容 栈的应用 中缀转后缀 从左到右遍历中缀表达式: 遇到数值时,直接输出; 遇到操作符时: 如果栈为空或操作符为(,则操作符入栈 如果操作符为),则一直弹栈到与其匹配的(为止 如果栈不为空,则将栈顶操作符与当前操作符进行比较: 如果当前操作符的优先级小于等于栈顶符号的优先级,则将栈顶操作符出栈输出,然后再次拿栈顶符号与当前操作符进行比较; 如果当前操作符的优先级大于栈顶操作符的优先级,则将当前操作符入栈; 直到表达式结束 后缀表达式的计算: 从左到右遍历表达式: 遇到数值直接进栈; 遇到操作符时,取出栈顶的两个元素进行计算,将计算结果入栈 直到表达式结束

July 28, 2014

指针与二维数组

通过前面的学习,已知: int arr[3]={1,3,5}; arr[0] 可以用 *(arr+0) 表示 arr[1] 可以用 *(arr+1) 表示 arr[2] 可以用 *(arr+2) 表示 现有二维数组如下: int arr[3][4]= { {1,2,3,4}, {5,6,7,8}, {9,10,11,12} }; 则: arr[0] ~~~ *(arr+0) arr[1] ~~~ *(arr+1) arr[2] ~~~ *(arr+2) 此处arr[0]即*(arr+0)是二维数组arr的第一个元素的值,该值是内层数组{1,2,3,4}的起始地址. 将arr[0]赋值给 temp数组 int temp0[4] = arr[0]; int temp1[4] = arr[1]; int temp2[4] = arr[2]; 获取最终的值: arr[0][0] ~~~~ 将arr[0]换为上边的temp0数组 arr[0][0] ~~~~ temp0[0] ~~~~ *(temp+0) ~~~~ *(*(arr+0)+0) arr[0][1] ~~~~ temp0[1] ~~~~ *(temp+1) ~~~~ *(*(arr+0)+1) arr[0][2] ~~~~ temp0[2] ~~~~ *(temp+2) ~~~~ *(*(arr+0)+2) arr[0][3] ~~~~ temp0[3] ~~~~ *(temp+3) ~~~~ *(*(arr+0)+3) arr[1][0] ~~~~ 将arr[1]换为上边的temp1数组...

July 24, 2014

函数指针和类成员指针

函数指针和类成员指针经常被用作参数进行传递,多态和函数重载都会用到. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <iostream>#include <string>#include <string.h>using namespace std; class Demo { public: void show() { cout << "member method Demo::show() did call" << endl; str = "str from Demo::show()"; } string str; }; void show() { cout<<"普通函数指针被调用"<<endl; } int main(int argc, char* argv[]) { //普通函数指针 //将普通函数show的地址赋值给pPainShow,优先级原因,必须在(*pPainShow)外加小括号, //否则编译器会将此认为是一个void* pPainShow(); 的函数声明,显然,我们不是这个意思....

November 3, 2013

指针常量和常量指针

这一概念经常混淆,故写下来,以备不时之需 1 2 3 4 5 6 7 8 int a = 10; int * const b = &a;//const修饰b,b本身不可变,但是*b可变;人称常量指针,即指针是常量,地址不可改变 *b = 20;//更换值 cout << *b << endl; int const * bb = &a;//const修饰*bb,*bb不可变,但是bb可变;人称指针常量,指向常量的指针,值不可以变,地址可以改变 int c = 30; bb = &c;//更换指向 cout << *bb << endl;

November 3, 2013