x210-2021-09-12

1、sprintf(strbuf, "%d",  x)这个形式不好理解,可以先以sprintf(strbuf, "hello world!")和printf("%d",x)的理解入手,首先是sprintf(strbuf, "hello world!"),一般来说,"hello world!"通常都是被打印到屏幕上进行显示,屏幕实际上也是一片内存(即显存),但是sprintf并没有将其打印到显存进行显示,而是用了一个strbuf数组来保存了起来,理解了这个,然后再看printf("%d",x),这个最普遍的作用就是将一个东西打印到屏幕上显示,假设这里x=10,那么printf("%d",x)就是先将x=10放到"%d"里头得到字符串"10",然后再打印到显存进行显示,现在sprintf(strbuf, "%d",  x)将两者结合了起来,其含义就是先将变量x放到"%d"得到字符串,然后字符串不再是直接打印到显存中,而是用一个strbuf数组单独存放起来。

2、字符空间如char 、const char (典型代表就是字符串)的结束标志为'\0',所以传参时一般写为int func(char *p)、int func(const char *p),而非字符空间(也就是除了以上举例的这两种之外的)因为不存在'\0'结束标志,所以需要在传参时传入长度作为指示告诉子函数该空间到底什么时候才结束,但是又因为非字符空间对应着如int、float、struct等多种数据类型,那么传参时不可能为了一一适配而根据不同数据类型单独创建一个子函数,因此非字符空间会使用void *,也就是int func(void *p, int len)来适配各种不同的数据类型形参。

3、int func(int *p)可以传入一个int a = 10的地址,如int func(&a),但又可以传入一个int buf[10],如int func(buf),但这两者一个是变量另一个是连续空间,所以func在声明时写成这样就会产生歧义性,因此为了做区别,声明时要用void *来指示说明是对连续空间进行操作,也就是int func(void *p),而针对单一变量做操作时才声明为int *。

4、假设地址0x0f103407中存储的值为10,注意,如果想要取出指针变量中的内容并操作,需要加*来解引用,如果*前还有变量类型,说明变量还处于声明和初始化阶段,不能当做解引用来理解:

void func(int *p);       void func(int *p);

int *p = 0x0f103407;      int a = 10;

&p = 0x08010004;      &a = 0x08010008;

0x08010004[0x0f103407];    0x08010008[10];

0x0f103407[10];

======================================

func(&p);           func(&a);

func(0x08010004);      func(0x08010008);

======================================

func(p);            无

func(0x0f103407);

======================================

{             {

 *0x0f103407 = 20;     *0x08010008 = 20;

}             }

======================================

p = 0x0f103407;      a = 20;

0x0f103407[20];      0x08010008[20];

======================================

通过上面的对比可以看到,如果直接将指针变量p不取地址然后直接传入形参要求为指针的func中时,是可行的,因为指针变量p存储的本来就是一个地址值,虽然在func(0x0f103407)内部进行了一顿操作,但实际上并没有对指针变量p造成一点伤害,它还是存储着那个地址值0x0f103407,那如果想要触动p应该怎么办呢?从上面对比也可以知道,应该使用func(&p),也就是func(0x08010004),但是会发现func(0x08010004)并不符合int func(int *p),因为在int func(int *p)中形参p指向一个int,但是这里0x08010004指向的是一个地址,所以,为了使用func(&p),就需要改写原声明为void func(int **p),即使用二级指针才能匹配上。

5、宏定义中如果宏体是一个乘除法表达式,那么编译阶段之后就会被算出结果,而不会在运行时再展开做运算,所以不需要担心会影响效率而放弃在宏体中使用。

posted @ 2021-09-18 00:19  migui  阅读(40)  评论(0编辑  收藏  举报