c语言

来源:互联网 发布:傻瓜p图软件 编辑:程序博客网 时间:2024/05/01 22:03

1、宏定义和展开(必须精通)

简单宏定义:#define N 100 
类型重命名: #define BOOL int 
控制条件编译: #define DEBUG 
预定义宏: 
LINE 被编译的文件的行数 
FILE 被编译的文件的名字 
DATE 编译的日期(格式”Mmm dd yyyy”) 
TIME 编译的时间(格式”hh:mm:ss”) 
STDC 如果编译器接受标准C,那么值为1

使用带参数的宏替代实际的函数的优点: 
1) 、 程序可能会稍微快些。一个函数调用在执行时通常会有些额外开销——存储上下文信息、复制参数的值等。而一个宏的调用则没有这些运行开销。 
2) 、 宏会更“通用”。与函数的参数不同,宏的参数没有类型。因此,只要预处理后的程序依然是合法的,宏可以接受任何类型的参数。例如,我们可以使用MAX宏从两个数中选出较大的一个,数的类型可以是int,long int,float,double等等。 
带参数的宏的一些缺点: 
1) 、 编译后的代码通常会变大。每一处宏调用都会导致插入宏的替换列表,由此导致程序的源代码增加(因此编译后的代码变大)。 
2) 、宏参数没有类型检查。当一个函数被调用时,编译器会检查每一个参数来确认它们是否是正确的类型。如果不是,或者将参数转换成正确的类型,或者由编译器产生一个出错信息。预处理器不会检查宏参数的类型,也不会进行类型转换。 
3) 、无法用一个指针来指向一个宏。如在17.7节中将看到的,C语言允许指针指向函数。这一概念在特定的编程条件下非常有用。宏会在预处理过程中被删除,所以不存在类似的“指向宏的指针”。因此,宏不能用于处理这些情况。 
4) 、宏可能会不止一次地计算它的参数。函数对它的参数只会计算一次,而宏可能会计算两次甚至更多次。如果参数有副作用,多次计算参数的值可能会产生意外的结果。

#运算符 
将一个宏的参数转换为字符串字面量(字符串字面量(string literal)是指双引号引住的一系列字符,双引号中可以没有字符,可以只有一个字符,也可以有很多个字符) 
【实例】

<code class="hljs scss has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-id" style="box-sizing: border-box;">#define</span> <span class="hljs-function" style="box-sizing: border-box;">PRINT_INT(x)</span> <span class="hljs-function" style="box-sizing: border-box;">printf(#x <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" = %d\n"</span>, x)</span>  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//x之前的#运算符通知预处理器根据PRINT_INT的参数创建一个字符串字面量。因此,调用</span><span class="hljs-function" style="box-sizing: border-box;">PRINT_INT(i/j)</span>;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//会变为  </span><span class="hljs-function" style="box-sizing: border-box;">printf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"i/j"</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" = %d\n"</span>, i/j)</span>;  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//在C语言中相邻的字符串字面量会被合并,因此上边的语句等价于:</span><span class="hljs-function" style="box-sizing: border-box;">printf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"i/j = %d\n"</span>, i/j)</span>;  </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#<span class="hljs-keyword" style="box-sizing: border-box;">define</span> STR(x) #x  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>** argv)  {      printf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%s\n"</span>, STR(It<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'s a long string)); //注意:并没有双引号,输出 It'</span>s a <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> str      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;  }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

##运算符 
“##”被称为 连接符(concatenator),它是一种预处理运算符, 用来把两个语言符号(Token)组合成单个语言符号 
【实例】

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#<span class="hljs-keyword" style="box-sizing: border-box;">define</span> MK_ID(n) i##n  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> MK_ID(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>), MK_ID(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>), MK_ID(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//预处理后声明变为:  </span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i1, i2, i3;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#<span class="hljs-keyword" style="box-sizing: border-box;">define</span> GENERIC_MAX (type)           \  </span>type type<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">##_max(type x,  type y)     \  </span>{                                    \      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> x > y ? x :y;             \  }  GENERIC_MAX(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span>)  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//展开为</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> float_max(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> x, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> y) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> x > y ? x :y; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

宏的通用属性: 
1) 、宏的替换列表可以包含对另一个宏的调用。 
2) 、预处理器只会替换完整的记号,而不会替换记号的片断。因此,预处理器会忽略嵌在标识符名、字符常量、字符串字面量之中的宏名。 
3) 、一个宏定义的作用范围通常到出现这个宏的文件末尾。由于宏是由预处理器处理的,他们不遵从通常的范围规则。一个定义在函数中的宏并不是仅在函数内起作用,而是作用到文件末尾。 
4) 、宏不可以被定义两遍,除非新的定义与旧的定义是一样的。小的间隔上的差异是允许的,但是宏的替换列表(和参数,如果有的话)中的记号都必须一致。 
5) 、宏可以使用#undef指令“取消定义”。#undef指令有如下形式: 
#undef N 
会删除宏N当前的定义。(如果N没有被定义成一个宏,#undef指令没有任何作用。)#undef指令的一个用途是取消一个宏的现有定义,以便于重新给出新的定义。 
参考:C语言中的宏定义

2、位操作(必须精通) 
参考:C 位运算符 及有用位运算 
3、指针操作和计算(必须精通) 
4、内存分配(必须精通)

5、字节对齐

满足以下两点个: 
1) 结构体每个成员相对于结构体首地址的偏移量都是本成员大小的整数倍,如不满足则加上填充字节; 
2) 结构体的总大小为结构体最宽的基本类型成员大小的整数倍,如不满足则在最后加上填充字;

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span> A {      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a;      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> b;      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">short</span> c;  };  </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

分析sizeof(A): 
首先第一个 int 为 4 。---- 
其次 char 为 1,char 成员相对于首地址的偏移量为4, 4是char 本身大小 1 的整数倍,所以可以接着安置。----- 
然后 short 为2,short 成员相对于首地址的偏移量为5,5不是short 本身大小 2 的整数倍,所以在填充到6。-----X-- 
最后计算总大小,int 4 char 1 填充 1 short 2 = 8,8是最宽int 4 的整数倍。所以后面不再填充。 
参考:字节对齐

6、sizeof必考

  1. sizeof 计算字符串长度
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> str1[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">20</span>] = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"0123456789"</span>;      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> str2[] = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"0123456789"</span>;      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> a = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(str1); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//20  计算str1所占的内存空间,以字节为单位</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> b = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(str2); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//11, 注意要还要加上 '\0'  </span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> c = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">strlen</span>(str1); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//10, 注意 strlen 参数只能是char*, 且必须以'\0'结尾</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> d = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">strlen</span>(str2); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//10</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

2、8、类空间大小 
空类:1字节 
基类对象的存储空间大小为: 
非static数据成员的大小 + 4 个字节(虚函数的存储空间) 
派生类对象的存储空间大小为: 
基类存储空间 + 派生类特有的非static数据成员的存储空间 
虚继承的情况下,派生类对象的存储空间大小为: 
基类的存储空间 + 派生类特有的非static数据成员的存储空间 + 4字节(每一个类的虚函数存储空间。) 
3、sizeof 计算联合体大小(同样需要字节对齐)

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">uniton u2  {      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> a[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13</span>];      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> b;  };    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(u2) == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//最大成员为13,但要按int的对齐方式(也就是要能整除sizeof(int) = 4,b必须放到离首地址偏移量为16的地方)   </span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

7、各类库函数必须非常熟练的实现 
8、哪些库函数属于高危函数,为什么?(strcpy等等) 
gets 最危险 使用 fgets(buf, size, stdin)。这几乎总是一个大问题! 
strcpy 很危险 改为使用 strncpy。

参考:C语言中不安全的函数以及解决方案

0 0
原创粉丝点击