zoukankan      html  css  js  c++  java
  • C经典笔记

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

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

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

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

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

    <本文出自www.lfsblack.com>

    0,

    1,

    2,

    3,

    4,

    5,

    6,

    7,

    8,

    9,

    10,

    11,

    12,

    13,

    14,

    15,

    16,

    22,

    23,

    24,

    25,

    26,

    27,

    28,

    29,

    30,

    31,

    32,

    33,

    34,

    35,

    36,

    37,

    38,

    39,

    40,

    41,

    42,

    43,

    44,

    45,

    46,

    47,

    48,

    49,

    50,

    51,

    52,

    53,

    54,

    55,

    56,

    57,

    58,

    59,

    60,

    61,

    62,

    63,

    64,

    65,

    66,

    67,

    68,

    69,

    70,

    71,

    72,

    73,

    74,

    75,

    76,

    77,

    78,

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

    80,

    81,

    82,

    windows下的结果:

    83,

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

    84,

    windows下的结果:

    85,

    windows下结果:

    86,

    windows下的结果:

    87,

    windows下结果:

    88,

    89,

    90,

    91,

    92,

    93,

    94,

    95,

    96,

    97,

    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:

    测试结果:

    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中如果写:

    但是可以这样写: const bufsize;

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

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

          extern const buffer;

    107,

    108,

    109,

    110,

    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;
    }

    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)可以用来定义数组的尾数原因

      

    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,

    115,

    116,

    117,

    118,

    119,

    120,

    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;
    }

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

    122,

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

    123,

    124,

    125,

    126,

    127,

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

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

    128,

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

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

    129,

    130,

    131,

    132,

    133,

    134,

    auto_ptr指针

    135,

    136,

    137,

    138,

    139,

    140,

    141,

    142,

    143,

    144,

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

    145,

    146,

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

    147,

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

    148,

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

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

    149,

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

    150,

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

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

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

    151,

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

    152,

    153,

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

    154,

    155,

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

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

    多态是为了实现 接口重用

    156,

    结果:

    结果:

    157,

    结果:

    158,

    159,

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

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

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

    160,

    结果:

    161,

    162,

    163,

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

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

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

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

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

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

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

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

                                              会

    164,

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

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

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

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

    165,

    166,

    结果:

    167,

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

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

    168,

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

    169,

    170,

    171,

    172,

    173,

    174,

    175,

    176,

    177,

    178,

    179,

    int *ptr;

    ptr = (int *)0x67a9;

    *ptr = 0xaa55;

    180,

    181,

    182,

    183,

    求补码:(貌似有问题)

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

    184,

    185,

    186,

    187,

    全局变量放在                                                                          数据段

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

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

    指向的空间放在                                                                        数据段

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

    指向空间放在                                                                           堆

    188,

    189,

    190,

    191,

  • 相关阅读:
    四十八.监控概述 、 Zabbix基础 、 Zabbix监控服务
    123D
    bzoj3879
    bzoj1699
    LA6878
    uoj#149
    687C
    codeforces round #424 div2
    803E
    713C
  • 原文地址:https://www.cnblogs.com/lfsblack/p/2710329.html
Copyright © 2011-2022 走看看