C语言博大精深,很多看似简单的却暗含杀机

如果你感到你的C语言学的差不多了,那说明你的C一无所知:

下面就看过的C做一些总结,文中都是以图片的形式给出,也花费了我很多宝贵的时间

之所以用图片就是为了迫使大家自己在编译器上敲一遍代码

由于编译器和系统的差异,可能结果有点不一样,而且很多都没有解释,自己看,如有问题,下面评论留言::

<本文出自www.lfsblack.com>

 

0,

C经典笔记

 

 

1,

C经典笔记

 

2,

C经典笔记

 

3,

C经典笔记

4,

C经典笔记

 

5,

C经典笔记

 

6,

C经典笔记

 

7,

C经典笔记

 

8,

C经典笔记

 

9,

C经典笔记

 

10,

C经典笔记

 

11,

C经典笔记

 

12,

C经典笔记

 

13,

C经典笔记

 

14,

C经典笔记

 

15,

C经典笔记

 

16,

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

 

 

22,

C经典笔记

23,

C经典笔记

 

24,

C经典笔记

 

25,

C经典笔记

 

26,

C经典笔记

 

27,

C经典笔记

 

28,

C经典笔记

 

29,

C经典笔记

 

30,

C经典笔记

 

31,

C经典笔记

 

32,

C经典笔记

 

33,

C经典笔记

 

34,

C经典笔记

 

35,

C经典笔记

 

36,

C经典笔记

 

37,

C经典笔记

 

38,

C经典笔记

 

39,

C经典笔记

 

40,

C经典笔记

 

41,

C经典笔记

 

42,

C经典笔记

 

43,

C经典笔记

 

44,

C经典笔记

 

45,

C经典笔记

 

46,

C经典笔记

 

47,

C经典笔记

 

48,

C经典笔记

 

49,

C经典笔记

 

50,

C经典笔记

 

51,

C经典笔记

 

52,

C经典笔记

 

53,

C经典笔记

 

54,

C经典笔记

55,

C经典笔记

 

56,

C经典笔记

 

57,

C经典笔记

 

58,

C经典笔记

 

59,

C经典笔记

 

60,

C经典笔记

 

61,

C经典笔记

 

62,

C经典笔记

 

63,

C经典笔记

 

64,

C经典笔记

65,

C经典笔记

 

66,

C经典笔记

 

67,

C经典笔记

 

68,

C经典笔记

 

69,

C经典笔记

 

70,

C经典笔记

 

71,

C经典笔记

 

72,

C经典笔记

 

73,

C经典笔记

 

74,

C经典笔记

 

75,

C经典笔记

 

76,

C经典笔记

 

77,

C经典笔记

 

78,

C经典笔记

 

79,在字符串中找出连续最长的数字串,返回长度,最长数字串放在outputstr

C经典笔记

C经典笔记

 

80,

C经典笔记

 

81,

C经典笔记

 

82,

C经典笔记

windows下的结果:

C经典笔记

 

83,

C经典笔记

但是这个地方和系统和编译器有很大关系:在windows下结果如下:我们姑且这样认为(linux下默认4字节对齐)

C经典笔记

 

84,

C经典笔记

windows下的结果:

C经典笔记

 

85,

C经典笔记

windows下结果:

C经典笔记

 

86,

C经典笔记

windows下的结果:

C经典笔记

87,

C经典笔记

windows下结果:

C经典笔记

88,

C经典笔记

 

89,

C经典笔记

 

90,

C经典笔记

 

91,

C经典笔记

 

92,

C经典笔记

 

93,

C经典笔记

 

94,

C经典笔记

 

95,

C经典笔记

 

96,

C经典笔记

 

97,

C经典笔记

 

98,

C++程序中调用被C编译器编译后的函数,为什么要加extern "C"?

  C++语言支持重载,C不支持。函数被C++编译后在库中的名字与C的不同。

  C++提供了C链接交换指定符号extern "C"解决名字匹配问题

 

99,

头文件ifndef/define/endif有什么作用?

  防止该头文件被重复引用

 

100,

编程去掉代码中的注释:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>

void remove_comment(char *buf,size_t size) {
   char *p,*end,c;
   char *sq_start,*dq_start;
   char *lc_start,*bc_start;
   size_t len;
   p = buf;
   end = p + size;
   sq_start = dq_start = lc_start = bc_start = NULL;

   while(p < end) {
      c = *p;
      switch(c) {
      case '\'':
         if(dq_start || lc_start || bc_start) {
            p ++;
            continue;
         }
         if(sq_start == NULL)
            sq_start =  p ++;
         else {
            len = p ++ - sq_start;
            if(len == 2 && *(sq_start+1) == '\\') {
               continue;
             }
            sq_start = NULL;
         }
         break;
      case '\"':
         if(sq_start || lc_start || bc_start ) {
            p ++ ;
            continue;
         }
         if(sq_start == NULL)
            dq_start = p ++;
         else {
            if(*(p ++ -1) == '\\') 
               continue;
            dq_start = NULL;
         }
         break;
      case '/':
         if(sq_start || dq_start || lc_start || bc_start) {
            p ++;
            continue;
         }
         c = *(p+1);
         if(c == '/') {
            lc_start = p;
            p += 2;
         }else if(c == '*') {
            bc_start = p ;
            p += 2;
         } else
            p ++;
         break;
      case '*':
         if(sq_start || dq_start || lc_start || bc_start == NULL) {
              p ++;
              continue;
         }
         if(*(p+1)  != '/') {
            p ++;
            continue;
         }
         p += 2;
         memset(bc_start, ' ',p - bc_start);
         bc_start = NULL;
         break;
      case '\n':
         if(lc_start == NULL) {
            p ++;
            continue;
         }
         c = *(p-1);
         memset(lc_start,' ',(c == '\r' ? (p ++ -1) : p++) - lc_start);
         lc_start = NULL;
         break;
      default:
         p ++;
         break;
      }
   }
   if(lc_start) 
      memset(lc_start,' ' ,p - lc_start);
  }

int main(int argc, char *argv[]) {
   int fd,n;
   char buf[102400];
   fd = open("1.txt",O_RDONLY,0);
   if(fd == -1)
      return -1;
   n = read(fd,buf,sizeof(buf));
   if( n == -1 || n == 0) {
      close(fd);
      return -1;
   }
   remove_comment(buf,n);
   *(buf + n) = '\0';
   printf(buf);
   close(fd);
   return 0;
}

测试文件1.txt:

C经典笔记

 

测试结果:

C经典笔记

 

101,

用一个宏,求一个结构体里某个变量相对于struct的偏移量

  #define FIND(struc,e) (size_t)((struct *)0)->e)

102,

用预处理定义一个常数,用以表明1年中有多少秒

    要考虑有可能溢出,因此用UL 

   #define SECOND_PER_YEAE    (60*60 * 24 * 365)UL

103,

用宏返回两个数中较小的一个

  #define MIN(A,B)   ((A) <= (B) ? (A) : (B))

104,

const在C中有什么用途?

  1,可以定义const常量

  2,const可以修饰函数的参数和返回值,甚至函数的定义体。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性

105,

const和#define区别?

  const常量有数据类型,宏没有。编译器可以对前者进行 类型安全检查,而后者只能进行字符替换,并且替换中还有可能发生意想不到的错误

  有些集成化的调试工具对const常量进行调试,但是不能对宏常量进行调试。在C++中const完全取代了宏常量

106,

  常量引进在早期的C++版本,当时标准C规范正在制定。那时,常量被看做一个好的思想而被包含在C中。但是,C中的const的意思是“一个不能被改变的普通变量”。在C中,它总占用

内存,而且名字的全局符。C编译器不能把const看成一个编译期间的常量。在C中如果写:

C经典笔记

 

但是可以这样写: const bufsize;

而这种写法在C++中是不允许的。C编译器则把它作为一个声明,这个声明指明在别的地方内存分配。因为C默认const是外部连接的,C++默认const是内部连接的,这样,如果C++

中想完成与C中同样的事,必须用extern把内部连接改成外部连接:

      extern const buffer;

107,

C经典笔记

C经典笔记

 

108,

C经典笔记

 

109,

 

C经典笔记

 

110,

C经典笔记

 

111,

#include <iostream>
using namespace std;

class A1 {
public:
   int a;
   static int b;
   A1();
   ~A1();
};


class A2 {
public:
   int a;
   char c;
   A2();
   ~A2();
};
class A3 {
public:
   float a;
   char c;
   A3();
   ~A3();
};
class A4 {
public:
   float a;
   int b;
   char c;
   A4();
   ~A4();
};
class A5 {
public:
   double d;
   float a;
   int b;
   char c;
   A5();
   ~A5();
};

void main() {
   cout << sizeof(A1) << endl << sizeof(A2) << endl << sizeof(A3) 
    << endl << sizeof(A4) << endl << sizeof(A5) << endl;
}

C经典笔记

 

112,

sizeof和strlen的区别?

1>sizeof操作符的结果类型是size_t,它在头文件中的typedef为unsigned int类型。该类型保证能容纳实现所建立的最大对象的字节大小

2>sizeof是运算符,strlen是函数

3>sizeof可用类型做参数,strlen只能用char *做参数,且必须是以'\0'结尾,sizeof还可以用函数做参数

4>数组作为sizeof参数不退化,传递给strlen就退化为指针

5>大部分编译程序编译的时候就把sizeof计算过了,是类型或是变量的长度。这就是sizeof(x)可以用来定义数组的尾数原因

  

C经典笔记

6>strlen的结果要在运行的时候才能计算出来,用来计算字符串的长度,而不是类型占内存的大小

7>sizeof后如果是类型必须加括号,如果是变量名可以不加括号。这是因为sizeof是个操作符而不是个函数

8>当使用一个结构类型或变量时,sizeof返回实际的大小。当使用一静态的空间数组时,sizeof返回全部数组的尺寸。sizeof操作符不能返回动态

分配的数组或外部的数组的尺寸

9>数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址

10>sizeof操作符不能用于函数类型、不完全类型或字段。不完全类型指具有未知存储大小数据的数据类型,如:未知存储大小的数组类型,未知内容的结构或联合类型,void类型

 

113,

sizeof的使用场合:

1>sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信

2>用它可以看看某种类型的对象在内存中所占的单元字节

3>在动态分配一个对象时,可以让系统知道分配多少内存

4>便于一些类型的扩充,在windows中有很多结构类型就有一个专用的字段用来存放该类型的字节大小

5>由于操作数的字节数在实现时可能会出现变化,在涉及操作数字节大小时也用sizeof代替常量计算

6>如果操作数是函数中的数组形参或函数类型的参数,sizeof给出其指针的大小

 

114,

C经典笔记

 

115,

C经典笔记

C经典笔记

 

 

116,

C经典笔记

 

117,

C经典笔记

 

118,

C经典笔记

 

119,

C经典笔记

 

120,

 

C经典笔记

 

121,

交换:

#include <iostream>
using namespace std;

void swap1(int p,int q) {
   int temp ;
   temp = p;
   p = q;
   q = temp ;
}

void swap2(int *p,int *q) {
   int *temp ;
   *temp = *p;
   *p = *q;
   *q = *temp;
}

void swap3(int *p,int *q) {
   int *temp ;
   temp = p;
   p = q;
   q = temp;
}

void swap4(int *p,int *q) {
   int temp;
   temp = *p;
   *p = *q;
   *q = temp;
}

void swap5(int &p,int &q) {
   int temp;
   temp = p;
   p = q;
   q = temp;
}

int main() {
   int a = 1,b = 2;
   swap1(a,b);
   cout << a << '\t' << b << endl;
  // swap2(&a,&b);  //有错误
  // cout << a << '\t' << b << endl;
   swap3(&a,&b);
   cout << a << '\t' << b << endl;
   swap4(&a,&b);
   cout << a << '\t' << b << endl;
   swap5(a,b);
   cout << a << '\t' << b << endl;

   return 0;
}

结果:只有后两个可以实现

C经典笔记

 

122,

C经典笔记

上面程序崩溃。因为GetMemory并不能传递动态申请的内存,str一直都是NULL

C经典笔记

C经典笔记

 

 

123,

C经典笔记

 

124,

C经典笔记

 

125,

 

C经典笔记

 

126,

C经典笔记

 

127,

在main函数中可以不写return语句,因为编译器会隐式返回0

删除一个指针后,把它设置为空指针(0)

 

128,

int (*(*f)(int,int))(int)

f是一个函数指针,指向的函数类型是有两个int参数并且返回一个函数指针的函数,返回的函数指向一个int参数且返回int的函数

 

129,

C经典笔记

 

130,

C经典笔记

 

131,

C经典笔记

 

132,

C经典笔记

 

133,

C经典笔记

 

134,

auto_ptr指针

 

135,

 

C经典笔记

 

136,

 

C经典笔记

 

137,

C经典笔记

 

138,

C经典笔记

 

139,

C经典笔记

 

140,

C经典笔记

 

141,

C经典笔记

 

142,

C经典笔记

 

143,

C经典笔记

 

144,

统计字符串中,各个字符出现的次数:

C经典笔记

C经典笔记

 

145,

C经典笔记

 

146,

C++代码实现,输入n输出nXn矩阵,规定沿45度线递增,形成一个zigzag数组(JPEG编码里取像素数据的排列顺序):

C经典笔记

C经典笔记

 

147,

两个等长数组A、B,所含元素相同,但顺序不同,只能取A数组某值和B数组某值进行比较,比较结果为大于,小于或等于。但是不能取同一数组两个值进行比较,也不能取得某数组中的某个值。写一个匹配算法(即A数组中某值与B数组中某值等值)

C经典笔记

C经典笔记

 

148,

标准模板库是一个基于模板的容器类库

容器是包容其他对象的对象

 

149,

C经典笔记

C经典笔记

从最上面输出结果看,两次调用析构函数

C经典笔记

 

150,

C++的空类默认产生4个函数,默认构造函数,析构函数,拷贝构造汉斯,赋值函数

C++中struct和class默认访问权限是唯一区别,可以有构造和析构函数

类静态成员必须初始化赋初值!!!

151,

C经典笔记

C经典笔记

可见 上面第一个例子之所以错,是因为编译器把Test b();当作一个函数声明了

 

152,

C经典笔记

C经典笔记

C经典笔记

 

153,

C经典笔记

从上例子中我们可以看到析构函数可以是内敛的

 

154,

C经典笔记

 

155,

封装可以隐藏实现细节,使得代码块化

继承可以扩展已存在的代码模块,目的是为了代码重用

多态是为了实现 接口重用

 

156,

C经典笔记

结果:

C经典笔记

 

C经典笔记

结果:

C经典笔记

 

157,

C经典笔记

结果:

C经典笔记

 

 

158,

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

 

159,

如果一个圆角矩形有直边和圆角,那么它也就多重继承了圆形和矩形,而圆形和矩形又都是从shape类里继承。问:当创建一个圆角矩形使,共创建多少shape?

答曰:如果圆形类和矩形类都不是virtual继承shape类,那么生成两个shape,一个为圆形类,一个为矩形类。

如果圆形类和矩形类都是virtual继承shape类,那么生成一个共享的shape

 

160,

C经典笔记

结果:

C经典笔记

 

161,

C经典笔记

C经典笔记

C经典笔记

 

162,

C经典笔记

C经典笔记

C经典笔记

 

163,

虚指针或虚函数指针是带有虚函数的类中,一个对象都有一个虚指针指向该类的虚函数表

C++如果阻止一个类被实例化? 

                                         使用抽象类或者构造函数被声明为private

一般在什么时候构造函数被声明成private?

                                         要阻止编译器生成默认的copy constructor的时候

什么时候编译器会生成默认copy constructor?

                                         只要自己没写,而程序中需要,就会生成

如果已经写了一个构造函数,编译器还会生成copy constructor么?

                                          会

 

164,

虚函数的入口地址和普通函数有什么不同?

每个虚函数都在vtable中占了一个表项,保存着一条跳转到它入口地址的指令(实际上就是保存了它的入口地址)。当一个包含虚函数的对象(不是对象的指针)被创建

的时候,它在头部附加一个指针,指向vtable中相应的位置。调用虚函数的时候,不管你是用什么指针调用的,它先根据vtable找的入口地址再执行,从而实现了“动态联编”

而不像普通函数那样简单的跳转到一个固定的地址

 

165,

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

 

 

166,

C经典笔记

结果:

C经典笔记

 

167,

一个C++程序员想要运行一个static_cast<char *>()。为了能够确保合法性。

应该增加函数   operator char*();

 

168,

C++中,typeid运算符的返回值为:type_info常量对象的引用

C经典笔记

 

169,

C经典笔记

 

170,

C经典笔记

 

171,

C经典笔记

 

 

172,

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

 

 

173,

C经典笔记

C经典笔记

C经典笔记

C经典笔记

 

 

174,

C经典笔记

 

175,

C经典笔记

 

176,

C经典笔记

 

177,

C经典笔记

 

 

178,

C经典笔记

C经典笔记

 

 

179,

int *ptr;

ptr = (int *)0x67a9;

*ptr = 0xaa55;

 

180,

C经典笔记

 

 

181,

C经典笔记

C经典笔记

 

 

182,

C经典笔记

C经典笔记

 

 

183,

求补码:(貌似有问题)

unsigned short get(short x )
{
short y ;
y = x >> 15 ;
return ((x^y)-y)|(y<<15);
}

 

184,

C经典笔记

 

185,

C经典笔记

C经典笔记

 

186,

C经典笔记

C经典笔记

C经典笔记

C经典笔记

C经典笔记

 

187,

全局变量放在                                                                          数据段

函数内部变量static int ncount 放在                                             数据段

函数内部变量char *p = "AAA",p放在                                           堆栈

指向的空间放在                                                                        数据段

函数内变量char *p = new char,p放在                                          堆栈

指向空间放在                                                                           堆

 

188,

C经典笔记

C经典笔记

 

189,

C经典笔记

 

 

190,

C经典笔记

C经典笔记

C经典笔记

C经典笔记

 

191,

 

C经典笔记

相关文章: