C语言深度解剖----重点部分笔记

第一章:关键字

auto:所有变量在编译器默认缺省情况下都是auto的
register:请求编译器尽可能的将变量存在CPU内部寄存器而不是通过内存寻址访问以提高效率。尽可能是因为一个CPU的寄存器也就那么几个或几十个,如果定义了很多register变量是不可能全部放入的。
用&符号是去内存中取址,取不到放在编译器中的地址。CPU不直接和内存打交道而是通过寄存器去进行交流。因此&符号不能获得register的值。
static(调试版):

#include<iostream>
using namespace std;

static int j;

void fun1(void)
{   
    static int i = 0;        
    i++;   
}

void fun2(void)
{   
    j = 0;      
    j++;   
}
int main()
{
    for (int k = 0; k < 10; k++)
    {  
        fun1();  
        fun2();         
    }
    system("pause");
}
//结果:
i=1,2,3,4,5,6,7,8,9,10
j=1,1,1,1,1,1,1,1,1,1

其实主要是考察调试的问题,fun1(),fun2()设断点然后F5,再F10,F11的问题。

static(输出版):

#include<iostream>
using namespace std;
static int j;
int* fun1(void)
{
    static int i = 0;
    int *a = &i;//这样做可以获得i的地址,也可以*i获得i的值
    i++;
    return a;
}
int* fun2(void)
{
    j = 0;
    int *a = &j;
    j++;
    return a;
}
int main()
{
    for (int k = 0; k < 10; k++)
    {
        fun1();
        fun2();
        cout << *b << endl;
        cout << *c << endl;
    }
    system("pause");
}

sizeof://是关键字不是函数

int i=0;
sizeof(int)==sizeof(i)==sizeof i==4

double a[100] = {0.0};
double *p=a;
sizeof(a);//值为800
sizeof(p);//值为4
sizeof(a[0])==sizeof(*a)//值为8
sizeof(&a)==sizeof(&a[0])//值为4,有取址符号的都为4,因为地址的sizeof为4

长循环放在内层可以节省效率,减少CPU切换循环层的次数。

符号表是一种用于语言翻译器的数据结构,在符号表中每个标识符都和它的声明或使用信息绑定在一起,比如其数据类型,作用于以及内存地址。const由于没有了存储和读内存的操作,使得它的效率也很高。
0x01<<2+3;//由于+号的优先级大于<<或>>符号,因此结果为0x01左移5位,值为32,一个整形长度位32位,左移或右移总位数不能超过32位。

 

第四章:指针与数组

*p.f=>*(p.f)//因为.的优先级高于*,因此该句的语义为对p取f偏移作为指针,然后指针去解引用。解引用就是取值的意思。
int *ap[]=>int *(ap[])=>(int *)(ap[])//因为[]的优先级高于*,因此ap是一个元素为int指针的数组。
int (*ap)[]//就是指向数组的指针。
int *fp()=>int *(fp())//因为()的优先级高于*,因此fp是一个函数,返回int *类型,也就是返回指针的函数。函数指针指向函数的入口地址。
int (*fp)()//fp为一个指向函数的指针,也就是函数的指针,这里函数参数为空,返回值为int。

++和--的优先级高于*

练习:
1.int (*(*d)[5])(int *);
*d是一个指针,指针指向一个含有5个元素的数组,每一个元素是一个函数指针,函数参数为int*,返回值为int。

2.int (*(*e)(int*))[5];
*e是一个指针,这个指针是一个函数指针,形参为int*,返回一个指向数组的指针,这个指针是整型的。
我们需要改为:
typedef int (*pArr)[5];//这里的这个括号说明这是一个函数指针数组,int为返回值。如果没有括号这是就是别名的意思。
typedef pArr (*func)(int*);

char a[5] = { 'A', 'B', 'C', 'D', 'E' };
char(*p3)[5] = &a;//这里因为左右相等的原则,只能以char(*p3)[5]的形式,其他都不可以,这里的p3是指整个数组,所以*(p3+1)指的是E后面的那个字符,也就是无效空字符。
#include<stdio.h>
int main()
{
    char a[5] = { 'A', 'B', 'C', 'D', 'E' };
    char(*p3)[5] = &a;
    //char(*p4)[5] = a;
    char *p4=*(p3 + 1);
    return 0;
}


int *p=NULL;

int *p;
*p=NULL;//这个可能会不安全,因为p是一个未知地址,比较好的方法是

int i=10;
int *p=&i;
*p=NULL;

如何给一个地址存入值
int *p=(int *)0x12ff7c;//如何判断一个内存是否可访问:int i=0;去到内存中取&i的值即可。但其实这种写法在VS上会报错,最好还是别用这种方法,说是因为调试器会保护要写区域的内存不允许访问。
*p=0x100;//将值100存入0x12ff7c
或者直接:*(int *)0x12ff7c=0x100;

#include <iostream>
using namespace std;

struct Test
{
    int Num;
    char *pcName;
    short sDate;
    char ch[2];
    short str[4];
}*p;//值为20,转为16进制位14

void main()
{
        p = (Test*)0x100000;

        printf("p+0x01  ->  0x%08x\n", p+0x01);//+0x01等价于加了一整个数组结构,值为0x100014
        printf("(unsigned long)p+0x01  ->  0x%08x\n", (unsigned long)p+0x01);//只加一,0x100001
        printf("(unsigned int*)p+0x01  ->  0x%08x\n", (unsigned int*)p+0x01);//加了四,0x100004
    system("pause");
}

大端模式
       a[0]                a[1]              a[2]                   a[3]  
        1                   2                  3                      4
0x00 0x00 0x00 0x01    0x00 0x00 0x00 0x02    0x00 0x00 0x00 0x03    0x00 0x00 0x00 0x04 
大端模式读出来的值是0x00000100,也就是0x100(大端从左往右读)

在32位的x86系统下,是小端模式——认为第一个字节是最低位字节
在内存中存放为:
a[0]                     a[1]
0x01 00 00 00     0x02 00 00 00
所以读取为:0x02000000(小端从右往左读)

二维数组的定义为

a=>&a[0]
a[i]=>&a[0]+i*sizeof(char)*4
a[i][j]=>&a[0]+i*sizeof(char)*4+j*sizeof(char)=>*(*(a+i)+j)
#include<stdio.h>
#include<iostream>
using namespace std;
int main()
{
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };//因为是小括号,所以a的值为a={1,3,5};
    //int a[3][2]={{0,1},{2,3},{4,5}};这样才是正确的取值
    int *p;
    p = a[0];//a[0]的值是{1,3}
    printf("%d", p[0]);//p[0]的值为1
    system("pause");
}

算内存最好的方法是画内存布局图

#include<stdio.h>
int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;/*这里如果没有疾病的话是有问题的...报错在于无法将int(*)[5]类型分配给int(*)[4],除非改为int (*p)[5],但这样就体现不出意义了,编译器为VS2013,可能是编译器的问题。不同的编译器的起始
值不一定为0。后面有提到应该把指针初始定为NULL,就是把它拴在尺子的0mm处,估计是因为没有拴指针导致的问题,看下之后第五章有没有解决办法。*/
    printf("a_ptr=%#p,p_ptr=%#p\n", &a[4][2], &p[4][2]);
    printf("%p,%d", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}


但其实这里最妙的地方在于int(*p)[4]的含义,它是指int[][4],这里的p++是以4个单位一起加的,结果为a[1][0],但如果int *p这里的p++就是一个一个加的,也就是a[0][1]。

#include<stdio.h>
int main()
{
    int a[3][4];
    int(*p)[4];//int *p;p=a;这玩意也跑不了啊,总而言之思想记住就好。
    p = a;//如果这样跑的话这里就ok
    printf("a_ptr=%#p,p_ptr=%#p\n", &a[4][2], &p[4][2]);
    printf("%p,%d", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}

无法向函数传递一个数组:
无法向函数传递指针变量本身,而是指针变量本身的拷贝值
这样问题就来了,当我需要写一个GetMemory的函数,这个函数负责向内存申请所需的空间。

#include<iostream>
using namespace std;
char *GetMemory(char *p, int num)
{
    p = (char*)malloc(num*sizeof(char));
    return p;
}
int main()
{
    char*str = NULL;
    str=GetMemory(str, 10);
/*如果以函数void形式不加return返回值则无效,因为指针本身不会被传递到函数中,而是以_str的拷贝形式传进去的,然后这个_str在函数结束后又释放掉了,因此str还是老样子为NULL,而_str又在堆里自动销毁了。
唯一的用处是以指针指向_str的地址,将其拷贝出来并返回,这样main里才可以查找到这个值。也就是对于要传指针的函数一定要将这个指针传出,否则无法运用到这个指针。*/
    strcpy_s(str,6, "hello");
    cout << str;
    free(str);
    system("pause");
}
#include<iostream>
using namespace std;
char **GetMemory(char **p, int num)
{
    *p = (char*)malloc(num*sizeof(char));
    return p;
}
int main()
{
    char*str = NULL;
    GetMemory(&str, 10);//这里真真正正传的是str的值,而不是通过_str传的
    strcpy_s(str,6, "hello");
    cout << str;
    free(str);
    system("pause");
}

char a[3][4]等效的指针参数为char (*p)[10]
char *a[5]等效的指针参数为char **p
一个中括号可以抵掉一个*号


函数指针

char *fun(char* p1,char* p2){}
main:
char *(*pf)(char* p1,char* p2);
pf=&fun;
*pf("aa","bb");
#include<stdio.h>
void Function()
{
    printf("Call Function!\n");
}
int main()
{
    void (*p)();
    *(int*)&p=(int)Function;//强制将Function从void型转化为int型
    (*p)();//这句话相当于调用了函数Function
    return 0;
}

函数指针的主要作用在于
1.实现面向对象编程中的多态性
ps:很好的代码https://blog.csdn.net/philip_puma/article/details/25973139
2.回调函数

typedef void (*event_handler) (unsigned int para1, unsigned int para2);

struct event {
  unsigned int ev_id;
  event_handler handler;
};
struct event event_queue[MAX_EVENT_SIZE];

这里要搞懂怕是要去看源码了,这种坑不急着开。。。水平还不够。。。
像事件epoll源码里肯定是有的,红黑树那一块会用到。
/*class A{void fun();};
class B{void fun();};
list<EventHandler> _lstEventHandlers;
A a1,a2;B b;
_lstEventHandlers.push_back(a1.fun);
_lstEventHandlers.push_back(a2.fun);
_lstEventHandlers.push_back(b.fun);*/

这个程序是一个事件handle函数,即回调函数,在事件队列中都是用一个函数指针来保存的,程序可以通过扫
描这个事件队列来获取每个事件对应的处理函数,然后调用它。
成员变量这里再加一条:

#include<iostream>
using namespace std;

class A{
public:
    int x;
};

typedef int A::* MemberPointer;

int main(int argc, char *argv[])
{   
    MemberPointer pV;//成员变量指针的定义,等价于int A::* pV;    
    pV = &A::x;
    A a;
    a.*pV = 1;//等价于a.x=1;
    cout << &a->*pV << endl;
//这几种方式都是等价的
    system("pause");
}
#include<stdio.h>
#include<string.h>
char* fun1(char* p)
{
    printf("%s\n",p);
    return p;
}
char* fun2(char* p)
{
    printf("%s\n",p);
    return p;
}
char* fun3(char* p)
{
    printf("%s\n",p);
    return p;
}
int main()
{
    char* (*a[3])(char* p);
    char* (*(*pf[3]))(char* p);
    pf=&a;
    a[0]=fun1;
    a[1]=&fun2;
    a[2]=&fun3;
    pf[0][0]("fun1");//等价于(*pf)[0]("fun1");
    pf[0][1]("fun2");//等价于(*pf)[1]("fun2");
    pf[0][2]("fun3");//等价于(*pf)[2]("fun3");
    return 0;
}

 

 

第五章:内存管理

栈的效率要比堆的效率高,因为栈是编译时分配空间的,而堆是运行时动态分配空间的,且cpu有专门的寄存器(esp,ebp)来操作栈,而堆都是使用间接寻址。栈的存取速度仅次于寄存器,并且栈内可以数据共享。
struct的内存对齐是按照当前结构体中最大的数据的字节对齐的。有double或64位机子上有long,都是按8字节对齐的。
struct结构体只需要对指针进行内存分配,只要结构体内有指针就需要进行内存分配。
举例:

zclReportCmd_t *reportCmd;
typedef struct
{
    uint8 numAttr;
    zclReport_t attrList[];
}zclReportCmd_t;
typedef struct
{
    uint16 attrID;
    uint8 dataType;
    uint8 *attrData;
}zclReport_t;
reportCmd=(zclReportCmd_t *)osal_msg_allocate(sizeof(zclReportCmd_t)+sizeof(zclRepor_t));
reportCmd->attrList[0].attrData=(uint8*)osal_msg_allocate(len);

再来一个:

struct image
{
    struct header *info;
    unsigned char **data;
};
struct image *newimage(int nr,int nc)
{
    struct image *x;
    x=(struct image *)malloc(sizeof(struct image));//image的指针
    x->info=(struct header *)malloc(sizeof(struct header));//info指针
    x->data=(unsigned char **)malloc(sizeof(unsigned char *)*nr);//data的第一层指针
    x->data[0]=(unsigned char *)malloc(nr*nc);//data的第二层指针
    for(i=0;i<nr;i++)
    {
        x->data[i]=(x->data+nr*i);
    }
    return x;
} 


为char*分配指针内存
char *p1="abcdefg";
char *p2=(char*)malloc(sizeof(char)*strlen(p1)+1*sizeof(char));//这里需要考虑到'\0'的内存空间.
//并且字符串常量需要以\0结束,例如char a[7]={'a','b','c','d','e','f','g'};这个就是未结束,需要多加\0。
//不要因为sizeof(char)为1就省略这个写法,这样只会使代码可以执行下降。
strcpy(p2,p1);//但其实strcpy这个函数已经会报错了,需要改为strcpy_s(p2,8,p1);

初始化很重要,不确定的话就设为0或者设为NULL。

内存越界数组加一减一问题,以及内存泄漏的问题。会产生泄漏的内存是堆上的内存(还有资源或句柄等的泄漏情况),也就是由malloc系列函数或者new操作符分配的函数。如果使用完后没有及时free或delete,这块内存就无法释放,直到整个程序终止。
malloc的函数原型是(void*)malloc(int size);由于malloc会有不成功的可能性,因此一定要加入if(NULL!=p)的语句验证。

char *p=(char*)malloc(int size);
free(p);
p=NULL;//一定要将释放的指针设为空,不然就会变成悬垂指针。

 

 

第六章:函数

汇编语言代码往往就是从入口处开始一条一条执行,直到遇到跳转指令比如ARM的B、BL、BX、BLX。
编写strlen函数,用递归的方式解决:
递归1.0

int my_strlen(const char* strDest)
{
    assert(NULL!=strDest);
    if('\0'==*strDest)
    {
        return 0;
    }
    else
    {
        return(1+my_strlen(++strDest));
    }
}

递归2.0

int my_strlen(const char* strDest)
{
    assert(NULL!=strDest);
    return ('\0'!=*strDest)?(1+my_strlen(strDest+1)):0;    
}

递归的效率低是因为每次的函数调用的开销比循环来说大得多,而且递归深度太大可能会出现栈溢出的错误。
 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一章关键字..................................................................................................................................9 1.1,最宽恒大量的关键字----auto..........................................................................................11 1.2,最快的关键字---- register............................................................................................... 11 1.2.1,皇帝身边的小太监----寄存器............................................................................. 11 1.2.2,使用register 修饰符的注意点.............................................................................11 1.3,最名不符实的关键字----static........................................................................................12 1.3.1,修饰变量...............................................................................................................12 1.3.2,修饰函数...............................................................................................................13 1.4,基本数据类型----short、int、long、char、float、double........................................... 13 1.4.1,数据类型与“模子”............................................................................................... 14 1.4.2,变量的命名规则...................................................................................................14 1.5,最冤枉的关键字----sizeof...............................................................................................18 1.5.1,常年被人误认为函数...........................................................................................18 1.5.2,sizeof(int)*p 表示什么意思?........................................................................18 1.4,signed、unsigned 关键字................................................................................................19 1.6,if、else 组合.................................................................................................................... 20 1.6.1,bool 变量与“零值”进行比较...............................................................................20 1.6.2, float 变量与“零值”进行比较.................................................................................21 1.6.3,指针变量与“零值”进行比较...............................................................................21 1.6.4,else 到底与哪个if 配对呢?...............................................................................22 1.6.5,if 语句后面的分号............................................................................................... 23 1.6.6,使用if 语句的其他注意事项.............................................................................. 24 1.7,switch、case 组合........................................................................................................... 24 1.7.1,不要拿青龙偃月刀去削苹果.............................................................................. 24 1.7.2,case 关键字后面的值有什么要求吗?.............................................................. 25 1.7.3,case 语句的排列顺序...........................................................................................25 1.7.4,使用case 语句的其他注意事项..........................................................................27 1.8,do、while、for 关键字................................................................................................... 28 1.8.1,break 与continue 的区别.....................................................................................28 1.8.2,循环语句的注意点...............................................................................................29 1.9,goto 关键字......................................................................................................................30 1.10,void 关键字....................................................................................................................31 1.10.1,void a?............................................................................................................31 1.10,return 关键字................................................................................................................. 34 1.11,const 关键字也许该被替换为readolny....................................................................... 34 1.11.2,节省空间,避免不必要的内存分配,同时提高效率.................................... 35 1.12,最易变的关键字----volatile.......................................................................................... 36 1.13,最会带帽子的关键字----extern.................................................................................... 37 1.14,struct 关键字..................................................................................................................38 1.14.1,空结构体多大?.................................................................................................38 1.14.2,柔性数组.............................................................................................................39 1.14.3,struct 与class 的区别.........................................................................................40 1.15,union 关键字..................................................................................................................40 1.15.1,大小端模式对union 类型数据的影响............................................................. 40 1.15.2,如何用程序确认当前系统的存储模式?........................................................ 41 1.16,enum 关键字..................................................................................................................42 1.16.1, 枚举类型的使用方法..........................................................................................43 1.16.2,枚举与#define 宏的区别....................................................................................43 1.17,伟大的缝纫师----typedef 关键字................................................................................. 44 1.17.1,关于马甲的笑话.................................................................................................44 1.17.2,历史的误会----也许应该是typerename........................................................... 44 1.17.3,typedef 与#define 的区别...................................................................................45 1.17.4,#define a int[10]与typedef int a[10];.............................................................. 46 第二章符号....................................................................................................................................49 2.1,注释符号..........................................................................................................................50 2.1.1,几个似非而是的注释问题...................................................................................50 2.1.2,y = x/*p................................................................................................................. 51 2.1.3,怎样才能写出出色的注释...................................................................................51 2.1.3.1,安息吧,路德维希.凡.贝多芬................................................................. 51 2.1.3.2,windows 大师们用注释讨论天气问题....................................................51 2.1.3.3,出色注释的基本要求............................................................................... 52 2.2,接续符和转义符..............................................................................................................53 2.3,单引号、双引号..............................................................................................................54 2.4,逻辑运算符......................................................................................................................54 2.5,位运算符..........................................................................................................................55 2.5.1,左移和右移...........................................................................................................55 2.5.2,0x01<<2+3 的值为多少?...................................................................................55 2.6,花括号..............................................................................................................................56 2.7,++、--操作符...................................................................................................................56 2.7.1,++i+++i+++i......................................................................................................... 57 2.7.2,贪心法...................................................................................................................57 2.8,2/(-2)的值是多少?.........................................................................................................58 2.9,运算符的优先级..............................................................................................................58 2.9.1, 运算符的优先级表................................................................................................58 2.9.2,一些容易出错的优先级问题.............................................................................. 60 第三章预处理................................................................................................................................61 3.1,宏定义..............................................................................................................................62 3.1.1,数值宏常量...........................................................................................................62 3.1.2,字符串宏常量.......................................................................................................62 3.1.3,用define 宏定义注释符号?.............................................................................. 63 3.1.4,用define 宏定义表达式.......................................................................................63 3.1.5,宏定义中的空格...................................................................................................64 3.1.6,#undef....................................................................................................................64 3.2,条件编译..........................................................................................................................65 3.3,文件包含..........................................................................................................................66 3.4,#error 预处理................................................................................................................... 66 3.5,#line 预处理.....................................................................................................................67 3.6,#pragma 预处理...............................................................................................................67 3.6.8,#pragma pack........................................................................................................ 69 3.6.8.1,为什么会有内存对齐?........................................................................... 70 3.6.8.2,如何避免内存对齐的影响....................................................................... 70 3.7, #运算符..............................................................................................................................72 3.8,##预算符..........................................................................................................................72 第四章指针和数组.........................................................................................................................74 4.1,指针.................................................................................................................................74 4.1.1,指针的内存布局...................................................................................................74 4.1.2,“*”与防盗门的钥匙............................................................................................. 75 4.1.3,int *p = NULL 和*p = NULL 有什么区别?.................................................... 75 4.1.4,如何将数值存储到指定的内存地址.................................................................. 76 4.1.5,编译器的bug?....................................................................................................77 4.1.6,如何达到手中无剑、胸中也无剑的地步.......................................................... 78 4.2,数组.................................................................................................................................78 4.2.1,数组的内存布局...................................................................................................78 4.2.3,数组名a 作为左值和右值的区别.......................................................................79 4.3,指针与数组之间的恩恩怨怨..........................................................................................80 4.3.1,以指针的形式访问和以下标的形式访问.......................................................... 80 4.3.1.1,以指针的形式访问和以下标的形式访问指针....................................... 81 4.3.1.2,以指针的形式访问和以下标的形式访问数组....................................... 81 4.3.2,a 和&a 的区别...................................................................................................... 81 4.3.3,指针和数组的定义与声明...................................................................................83 4.3.3.1,定义为数组,声明为指针....................................................................... 83 4.3.3.2,定义为指针,声明为数组....................................................................... 85 4.3.4,指针和数组的对比...............................................................................................85 4.4,指针数组和数组指针......................................................................................................86 4.4.1,指针数组和数组指针的内存布局...................................................................... 86 4.4.3,再论a 和&a 之间的区别.....................................................................................87 4.4.4,地址的强制转换...................................................................................................88 4.5,多维数组与多级指针......................................................................................................90 4.5.1,二维数组...............................................................................................................91 4.5.1.1,假想中的二维数组布局........................................................................... 91 4.5.1.2,内存与尺子的对比....................................................................................91 4.5.1.3,&p[4][2] - &a[4][2]的值为多少?........................................................... 92 4.5.2,二级指针...............................................................................................................93 4.5.2.1,二级指针的内存布局............................................................................... 93 4.6,数组参数与指针参数......................................................................................................94 4.6.1,一维数组参数.......................................................................................................94 4.6.1.1,能否向函数传递一个数组?................................................................... 94 4.6.1.2,无法向函数传递一个数组....................................................................... 96 4.6.2,一级指针参数.......................................................................................................97 4.6.2.1,能否把指针变量本身传递给一个函数................................................... 97 4.6.2.2,无法把指针变量本身传递给一个函数................................................... 98 4.6.3,二维数组参数与二维指针参数.......................................................................... 99 4.7,函数指针........................................................................................................................100 4.7.1,函数指针的定义.................................................................................................100 4.7.2,函数指针的使用.................................................................................................101 4.7.2.1,函数指针使用的例子............................................................................. 101 4.2.7.2,*(int*)&p ----这是什么?....................................................................... 102 4.7.3,(*(void(*) ())0)()------这是什么?.....................................................................102 4.7.4,函数指针数组.....................................................................................................103 4.7.5,函数指针数组的指针.........................................................................................104 第五章内存管理...........................................................................................................................107 5.1,什么是野指针................................................................................................................107 5.2,栈、堆和静态区............................................................................................................107 5.3,常见的内存错误及对策................................................................................................108 5.3.1,指针没有指向一块合法的内存........................................................................ 108 5.3.1.1,结构体成员指针未初始化..................................................................... 108 5.3.1.2,没有为结构体指针分配足够的内存..................................................... 109 5.3.1.3,函数的入口校验......................................................................................109 5.3.2,为指针分配的内存太小.....................................................................................110 5.3.3,内存分配成功,但并未初始化.........................................................................110 5.3.4,内存越界............................................................................................................. 111 5.3.5,内存泄漏............................................................................................................. 111 5.3.5.1,告老还乡求良田......................................................................................112 5.3.5.2,如何使用malloc 函数.............................................................................112 5.3.5.3,用malloc 函数申请0 字节内存.............................................................113 5.3.5.4,内存释放..................................................................................................113 5.3.5.5,内存释放之后..........................................................................................114 5.3.6,内存已经被释放了,但是继续通过指针来使用............................................ 114 第六章函数.................................................................................................................................. 115 6.1,函数的由来与好处........................................................................................................116 6.2,编码风格........................................................................................................................ 116 6.2,函数设计的一般原则和技巧...........................................................................................121 6.4,函数递归........................................................................................................................123 6.4.1,一个简单但易出错的递归例子........................................................................ 123 6.4.2,不使用任何变量编写strlen 函数......................................................................124 第七章文件结构.........................................................................................................................127 7.1,文件内容的一般规则....................................................................................................127 7.2,文件名命名的规则........................................................................................................130

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值