自己看2

1.宏的副作用(精髓在于直接替换)

#define mulitiply(a, b)   a*b    //带参数的宏定义

multiply(1+2,2);   直接替换后为: 1+2  *  2   实际想要的效果是(1+2)*2

#define multiply(a, b)   ((a)*(b))     //理想的写法,避免上面的错误


#define hash(str, sz, rst)    do{unsigned int n=0; n=xxx; rst=n%sz;} while(0)

hash("hello",7,n);   //这个n和unsigned int n=0冲突,小作用域的起作用

宏定义内部使用不同的命名风格


#define max(a,b)  ((a)>(b)?(a):(b))

int  c=max(a,b++);      //不要用++,--来使用宏定义

#define max(a,b) ({int _x=(a),_y=(b); _x>_y?_x:_y})    //保证传入宏的实参在内部只执行一次,限定了int,不通用

宏定义中定义临时变量时候要用大括号括起来

宏定义要返回值的话,最外层还要再用小括号括起来


内联函数其实就是宏定义的一种取代,避免了宏定义的副作用。内联函数不能单独声明,声明和实现写在一起。

*********膜拜大牛:https://onevcat.com/2014/01/black-magic-in-macro/****************

#define NSlog(format, ...)  do{

fprintf(stderr,"<%s : %d> %s\n",

[[[NSString stringWithUTF8Sting:_FILE_] lastPathComponent] UTF8String],

_LINE_, _func_);

(NSlog)((format), ##_VA_ARGS_);

fprintf(stderr, "-----\n");

} while(0)

分析:

函数宏,参数:...  (可变参数),第一个format被单独处理,剩下的参数作为整体处理。

do-while(0)  只执行一次,何不去掉?出现问题:

if(err)

NSlog(@"Oops,error happened");    展开:连缩进都保持一样


if(err)

fprintf((stderr,"<%s:%d>%s\n",[[[NSSTring stringWithUTF8String:_FILE_]lastPathComponent]UTF8String]   //输出

(NSlog)((format), ##_VA_ARGS_);

fprintf(stderr,"----\n");        

if后的单条执行语句不加大括号也没问题,这是错误的认识。宏展开后,一个整体因为if语句而被分割开了。


因为没有大括号,那加上大括号:

#define NSlog(format, ...) {    }

调用的时候:

if(err)

NSLog(@"Oops,error happened");   展开是这样:    {    };   最后会多个分号, 单个可以编译通过,但是如果

if(err)

NSLog(@"Oops,error happened");

else

dosomething     就会出错,展开是      if()   {   }; else   dosomething  肯定出错,else前面多了分号。

所以用do while(0);  吃掉了那个分号,像这样

if(err)

do{

}while(0);

else

something;


[[[NSString stringWithUTF8Sting:_FILE_] lastPathComponent] UTF8String],_LINE_, _func_对应于fprintf的

%s,%d,%s.  _FILE_, _LINE_, _func_是预定义宏,编译器指定的。


(NSlog)((format), ##_VA_ARGS_); 前后双下杠一般都是预定义宏,_VA_ARGS_表示...中剩余的参数。

##意思是前后两项合并,将前面的格式化字符串和后面的参数列表合并。

#define NSLogRect(rect) NSLog(@"%s x:%.4f, y:%.4f, w:%.4f, h:%.4f", #rect, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)
#define NSLogSize(size) NSLog(@"%s w:%.4f, h:%.4f", #size, size.width, size.height)
#define NSLogPoint(point) NSLog(@"%s x:%.4f, y:%.4f", #point, point.x, point.y)
******************************************************

第一次见这种用法,编译器不会报错。。。。

char* fun()

{return "nihao";}

******************************************************

c语言4区模型:

1栈区(stack):编译器自动分配释放,局部变量,形参等

2堆区(heap):程序员分配释放

3数据区:静态区(全局变量,静态变量)+常量区(常量值)

4代码区:存放函数代码的二进制

c++中类的存储:

成员变量(静态)-静态数据区

成员变量(一般)-存储于对象中,字节对齐

成员函数-代码区

******************************************************

d_storage=(T*)adsCalloc(memsize*sizeof(T)+LVEC_EXTRAL_SIZE_FOR_SIZE,1);

d_storage=(T*)(char*)d_storage+LVEC_EXTRAL_SIZE_FOR_SIZE;

思维僵化:

adsCalloc只是分配了一段内存,而且memsize*sizeof(T)+LVEC_EXTRAL_SIZE_FOR_SIZE只是表示多少个字节

并不是说LVEC_EXTRAL_SIZE_FOR_SIZE一定放在最后面|TTTTT|LVEC_EXTRAL_SIZE_FOR_SIZE|

也可以|LVEC_EXTRAL_SIZE_FOR_SIZE|TTTT|,总之这块内存的长度是不变的,LVEC_EXTRAL_SIZE_FOR_SIZE可以用来存储比如后面T的个数之类的冗余信息。

*******************************************************

循环中让某一个函数只执行一次

bool forone=false;

while(1){

if(forone){      

fun();

forone=true;

}

}

*********************************************************

函数指针(指针):int (*func)(int,int);       指针函数(函数):int* func(int,int);       |*|<|()|  优先级

函数指针作为指针函数的返回值:int (*func(int))(int,int)

func(int)-函数  *func(int)-函数返回值为指针   也就是int (*)(int,int)是一个指向函数的指针       *-----*func(int)   

typedef int (*pf)(int,int);       pf func(int);

int *p; //这种写法比较好,p带有*则表示p是一个指针

int (*p)(int);   //p前面有*,所以是指针,又后面是(int)表示是个函数,所以p表示指向函数的指针

int func(int);---------int (*p)(int);       func----*p      func是函数,p是指针       p是指向函数的指针

int (*p)[100]; //p指向一个数组,该数组含有100个整型

int arr[100];------int (*p)[100];        arr是数组,p是指针,p是指向数组的指针


文件处理程序,菜单按钮选择相应的操作(打开文件,读文件,写文件,关闭文件,函数形式相同)

void open(); void read(); void write(); void close();

定义函数指针,把上面4中操作放入一个数组中:typedef void (*PF)();

PF file_options[]={&open, &read, &write, &close};

int *(* (*fp)(int))[10]  解析:

*fp-fp是指针, (*fp)(int)-fp是函数指针,等价temp=(*fp)(int)    >>>>碰到函数指针后,再外层就是该函数返回值<<<<

int *(* temp)[10] 解析:

*temp-temp是指针,(*temp)[10]-temp指向一个数组,数组元素是int*

总体:fp是指向函数的指针,该函数返回的是一个指向数组的指针,数组有10个int*的元素。

************************感谢csdn博主porscheyin大神********************

int*  ptr, ptr2;   //定义了ptr指针,ptr2是int,避免歧义,推荐int  *ptr, ptr2;

1.NULL,空指针常量,int *p=NULL; char *p=0;

2.取变量地址,int i=3; int *ip=&i;

3.>>指针常量,long *p=(long)0xffff ffff ffff fff0;  (64位,long是8字节)

4.数组名,char arr[]={"sdsasd"}; char *cp=arr;

5.>>另一个指针的地址,int t=3; int *tp=&t; int *tpp=&tp;

6.>>字符串常量,char *cp="nihao";

void* 可以接收其他任意指针赋值(函数指针只能接受函数地址,不接受void*); 

void *all=NULL; int *ip=NULL; all=ip;

反过来:ip=(int*)all;

*************************感谢csdn博主porscheyin大神********************

T型指针与一个整数n相加,在内存上移动字节数为sizeof(T)*n.

数组名是一个常量指针,指针自身的值不可以改变,如arr++(实质是arr=arr+1),arr+=3;都是违法的

sizeof一个数组名返回的是:整个数组的大小,元素个数*元素大小

int arr[10];  sizeof(arr)=10*4=40字节,但是

int *arrp=arr; sizeof(arrp)=4字节,一个指针的大小

假若要访问二维数组matrix中第1行第1(注意数组下标从0开始)的元素可以有以下的几种方式(iint型变量)

通过数组名引用         通过指针p的引用         通过指针column_p的引用

i = matrix [0][0];          i = *(*(p+0)+0);           column_p = matrix[0];

i = *(matrix [0]+0);        i = *(p[0] + 0);             i = *(column_p+0);

i = *(*(matrix+0)+0);      i = (*(p + 0))[0];            i = column_p[0];

0可以省略。

printf("%p\n", &matrix);     对应的指针操作:无

printf("%p\n", matrix);       对应的指针操作:printf("%p\n", p);

printf("%p\n",&matrix[0]);   对应的指针操作:printf("%p\n", p);

printf("%p\n",matrix[0]);     对应的指针操作:printf("%p\n", column_p);

printf("%p\n",&matrix[0][0]); 对应的指针操作:printf("%p\n", column_p);

输出的结果是一样的,但是类型不一样

&matrix: 对二维数组名取地址,返回一个指向二维数组的指针;

matrix:  二维数组名会被转换为指向第一行(第一个数组)的指针,与&matrix[0]等价;

&matrix[0]:对第一个一维数组的数组名取地址,返回一个指向一维数组的指针;

matrix[0]:  二维数组中第一个一维数组的数组名,与&matrix[0][0]是等价的;

&matrix[0][0]:对第一行第一列元素取地址,返回一个指向整型元素的指针。

******************************************************************************************************

字符串常量除了

1.作为 &操作符的操作数;

2.作为sizeof操作符的操作数;

3.作为字符数组的初始化值

会被默认转化成由一个指针所指向的字符数组。比如一个字符串“abcdefg”.

printf("%c\n",*"abcdefg");       //输出a

printf("%c\n", *("abcdefg"+ 1));     //输出b

printf("%c\n","abcdefg"[5]);    //输出f

char arr[]="abcd";   //初始化一个字符数组的元素,arr是一个字符数组,把字符串常量赋值到数组中,arr[0]='q';是对的,实质是一个字符数组,而不是字符串常量。char arr2[]="abcd";arr和arr2的地址是不同的

char* p="abcd";    //p是一个字符串常量,不可以通过p改变字符串常量,p[0]='e';是错的,实质是字符串常量。char* p2="abcd";p和p2的地址是相同的,用两个指针同时指向一个字符常量。








 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值