在ANSI C中,如果要声明空参数表,则必须使用关键字void进行显式声明;
CPU,16位地址总线,能够访问2^16也就是64KB的内存;20位地址总线,可以访问2^20也就是1MB的内存;32位地址总线,能够访问2^32=2^2*2^30=4GB的内存;
1KB=2^10B;1MB=2^20B;1GB=2^30B;
liunx中如何查看系统中的页面大小?
释放或改写仍在使用的内存,称为"内存损坏";
未释放不再使用的内存,称为"内存泄漏";
对齐(alignment)的意思就是数据项只能存储在地址是数据项大小的整数倍的内存位置上。
访问一个8字节的double数据时,地址只允许是8的整数倍;
char p[i];表示从p所指的地址开始,前进i步,每步都是一个字符;
 
在ANSI C中,初始化指针时所创建的字符串常量被定义为只读。如果试图通过指针修改这个字符串的值,程序就会出现未定义的行为。
char *p = "beautiful";
数组也可以用字符串常量进行初始化;
char a[] = "gooseberry";
与指针相反,由字符串常量初始化的数组是可以修改的;其中的单个字符在以后可以改变,如:
strncpy(a,"black",5);//就将数组的值修改为"blackberry"
我们可以在结构的定义后跟一些变量名,表示这些变量的类型是这个结构,例如:
struct {内容...} plum,pear;
可以在struct关键字后面加一个可选的"结构标签":
struct fruit_tag {内容...} plum,pear;
这样,我们可以在将来的声明中用struct fruit_tag作为struct {内容...}的简写形式了。
因此,结构的通常形式是:
struct 结构标签(可选)
{
    类型1 标识符1;
    类型2 标识符2;
    ...
    类型N 标识符N;
}变量定义(可选);
所以,在下面的声明中:
struct data_tag {short dd,mm,yy;} my_birthday,xmas;
struct data_tag easter,groundhog_day;
变量my_birthday,xmas,easter和groundhog_day属于相同的数据类型。
char * const *(*next) ();
next是一个指针,它指向一个函数,该函数返回另一个指针,该指针指向一个类型为char的常量指针;
char *(*c[10])(int **p);
c是一个数组[0..9],它的元素类型是函数指针,其所指向的函数的返回值是一个指向char的指针;注意:在数组中被函数指针所指向的所有函数都把一个指向指针的指针作为它们的惟一参数;
事实上,typedef的格式与变量声明完全一样,只是多了这个关键字,向你提醒它的实质;
typedef unsigned char Uint8;
typedef unsigned int  Uint32;
typedef关键字并不创建一个变量,而是宣称"这个名字是指定类型的同义词";
typedef为数据类型创建别名,而不是创建新的数据类型;
signal()是一种系统调用,用于通知运行时系统,当某种特定的"软件中断"发生时调用特定的程序。它的真正名称应该是"Call_that_routine_when_this_interrupt_comes_in(当该中断发生时调用那个程序)"。调用signal()时,通过参数传递告诉它中断的类型以及用于处理中断的程序
typedef struct my_tag {int i;} my_type;
    struct my_tag variable_1;
my_type variable_2;
这个typedef声明引入了my_type这个名字作为"struct my_tag{ int i;}"的简写形式。但它同时也引入了结构标签my_tag,在它的前面加个关键字struct可以表示同样的意思;
my_tag为结构标签,my_type为由typedef声明的结构类型;
应该始终在结构的定义中使用结构标签,即使它并非必须。这种做法可以使代码更为清晰;
如果函数库的一份拷贝是可执行文件的物理组成部分,那么我们称之为静态链接;
如果可执行文件只是包含了文件名,让载入器在运行时能够寻找程序所需要的函数库,那么我们称之为动态链接;
系统调用mmap()把文件映射到进程的地址空间中。这样,文件的内容可以通过读取连续的内存地址来获得。mmap()就是一种把文件映射到内存的机制;
始终将-l函数库选项放在编译命令行的最右边;
通过把函数或变量声明为static,使它在其所在的文件之外不可见;
#define BlockScreenUsesRGB   //??
记住,C语言并不强迫对数组进行初始化时为每个元素提供初始值;
如何发现你的系统中堆栈的大致位置:方法是声明位于这些段的变量,并打印它们的地址。
#include <stdio.h>
int main(void)
{
    int i;
    printf("The stack top is near %p\n",&i);
    return 0;
}
不能从函数中返回一个指向该函数局部自动变量的指针,例如:
char *favorite_fuit()
{
    char delicious[] = "apple";
    return delicious;
}
当进入该函数时,自动变量delicious在堆栈中分配。当函数结束时,变量不复存在,它所占用的堆栈空间被回收,可能在任何时候被覆盖。这样,指针就失去了有效性(引用不存在的东西);
如果想返回一个指向在函数内部定义的变量的指针时,要把那个变量声明为static。
这样就能保证该变量被保存在数据段中而不是堆栈中。该变量的生命期就和程序一样长,当定义该变量的函数退出时,该变量的值依然能保持。当函数下一次进入时,该值依然有效。
auto关键字几乎没有什么用处,因为它只能用于函数内部。
但是在函数内部声明的数据缺省值就是auto;
 
在使用setjmp和longjmp的任何源文件中,必须包含头文件<setjmp.h>
volatile关键字??
可以把汇编代码嵌入到C代码中;
可以在汇编代码前冠以关键字"_asm",也可以只使用该关键字一次,把所有的汇编代码放入一对花括号内,如下:
_asm {
    mov ah,2
    mov dl,43h
    int 21h
     }
无论在什么时候,如果遇见了这样一条语句malloc(strlen(str));,几乎可以断定它是错误的,而malloc(strlen(str)+1)才是正确的;
一个'L'的NUL用于结束一个ACSII字符串,
两个'L'的NULL用于表示什么也不指向(空指针)。
break语句事实上跳出的是最近的那层循环语句或switch语句;
定义C函数时,在缺省情况下函数的名字是全局可见的。可以在函数的名字前加个冗余的extern关键字,也可以不加,效果是一样的。这个函数对于链接到它所在的目标文件的任何东西都是可见的。如果想限制对这个函数的访问,就必须加个static关键字。
function apple() {}        /*在任何地方均可见*/
extern funciton pear {}     /*在任何地方均可见*/
static function banana {}    /*在这个文件之外不可见*/
 
static,在函数内部,表示该变量的值在各个调用间一直保持延续性;
    在函数这一级,表示该函数只对本文件可见;
extern,用于函数定义,表示全局可见(属于冗余的);
    用于变量,表示它在其它地方定义;
void,作为函数的返回类型,表示不返回任何值;
    在指针声明中,表示通用指针的类型;
       位于参数列表中,表示没有参数;
sizeof的操作数是个类型名时,两边必须加上括号(这常常使人误以为它是个函数),但操作数如果是变量则不必加括号;
如:sizeof(int);
    sizeof*p;/*sizeof操作符把指针p所指向的东西(即*p)作为操作数*/
[]优先级高于*
int *ap[];/*ap是个元素为int指针的数组,int *(ap[])          */
函数()高于*
int *fp();/*fp是个函数,返回int*,int *(fp())                */
算数运算高于移位运算符
msb << 4 + lsb             <==>       msb << (4 + lsb)
所有的赋值运算符都具有右结合性:a=b=c;
在C语言的官方手册中,强烈建议用fgets()彻底取代gets()。
fgets()函数对读入的字符数设置了一个限制,这样就不会超出缓冲区范围;
内存泄漏:不再使用的内存未回收;
C专家编程P56!!
程序中属于热门(经常被使用)的变量可以放在寄存器中;
遵循标准的编译器必须提供库函数;
ANSI C中最重要的新特性就是"原型",这种特性取自C++。原型是函数声明的扩展,这样不仅函数名和返回类型已知,所有的形参类型也是已知的。这样允许编译器在参数的使用和声明之间检查一致性。
原型的目的是当我们对函数作向前声明(forward declaration)时,在形参类型中增加一些信息(而不仅仅是函数名和返回类型)。这样,编译器就能够在编译时对函数调用中的实参和函数声明中的形参之间进行一致性检查。
可以省略参数名称,只保留参数类型,但最好不要省略形参名。尽管编译器并不理睬形参的名称,但它们经常能向程序员们传递一些有用的信息。
每次编写新函数时都应该使用原型,并确保它在每次调用时都可见。
P29 const C专家编程
关键字const并不能把变量变成常量!在一个符号前加一个const限定符只是表示这个符号不能被赋值。也就是它的值对于这个符号来说是只读的。const应理解为read only!!
const最有用之处就是用它来限定函数的形参,这样该函数将不会修改实参指针所指向的数据,这也许就是C和C++中const最一般的用法;
const int *limitp = &limit;
int i = 27;
limitp = &i;
//表示limitp是指向常量整形的指针,这个指针不能用来修改这个整形数,但是在任何时候,这个指针本身的值却可以改变。这样它就指向了不同的地址,对它进行解引用操作时就会得到一个不同的值!
在制定ANSI C标准时,引入了pragma指示符,这个指示符来源于Ada。#pragma用于向编译器提示一些信息,诸如希望把某个特定函数扩展为内联函数,或者取消边界的检查。
在ANSI C标准中,#pragma指令会产生一个由编译器定义的任意效果。#pagama指示符的行为是由编译器定义的。
printf(" %d ", sizeof'A');
结果是4(或者是你机器上int的长度);
字符常量的类型是int,根据提升规则,它由char转换为int;
在表达式中,每个char都被转换为int,注意所有位于表达式中的float都被转换为double。(以上都不是绝对的P181)由于函数参数也是一个表达式,所以当参数传递给函数时也会发生类型转换。具体地说,char和short转换为int,而float转换为double。
如果使用了函数原型,缺省参数提升就不会发生。如果参数声明为char,则实际所传递的也是char。
在实际编程中,我们通过把函数原型放置在头文件中,而函数的定义则放置在另一个包含了该头文件的源文件中来防止函数的原型与对应的定义不匹配。因为编译器能同时发现它们,如有不匹配就能检测到。
long long格式化限定符%ld;
C函数库使用一个称作kbhit()的函数,如果一个字符正在等待被读取,它就会发出提示;khhit()类似于轮询,就好像你不断地询问设备的状态,看看它是否有字符要传给你。
printf("enter 'q' to quit \n");
for(; c != 'q'; i++)
{
    if( kbhit())
        {
            c = getchar();
        }
    printf("\n got %c, on interaction %d", c, i);
}
每次在使用系统调用(如ioctl())之后,检查一下全局变量errno是一种好的做法,它隶属于ANSI C标准,当知道确有错误发生时,库函数perror()可以打印出错误信息。
curses函数库是一个屏幕管理调用函数库,在所有流行的平台上均得到实现;
#include <curses.h>
用cc foo.c -lcurses命令进行编译;
一个函数指针数组可以像下面这样声明:
void (*state[MAX_STATES]) ();
如果知道了函数名,就可以像下面这样对数组进行初始化:
extern int a(),b(),c(),d();
int (*state[]) () = {a,b,c,d};
可以通过数组中的指针来调用函数:
(*state[i]) ();
所有的函数必须接受同样的参数,并返回同种类型的返回值(除非你把数组元素做成一个联合)。注意,我们甚至可以去掉指针形式,把上面的调用写成:
state[i] ();
编码的过程总结为:"brain,pain,gain(思考、痛苦、收获)"
有时候,花点时间把编程问题分解成几个部分往往是解决它的最佳方法。
强制类型转换(cast),既用于"类型转换",也用于"消除类型歧义"。如:
(float) 3     //是一个类型转换,而且数据的实际二进制位发生了改变
(float) 3.0    //用于消除类型歧义
复杂的类型转换P196 C专家编程
记住,定义是声明的一种特殊情况,它分配内存空间,并可能提供一个初始值;
P209 C专家编程 数组和指针
int,long:4个字节;double:8个字节;
形参(parameter),又称"形式参数(formal parameter)";
实参(argument),又称"实际参数(actual parameter)";
把作为形参的数组和指针等同起来是出于效率原因的考虑。
在C语言中,所有非数组形式的数据实参均以传值形式调用,即对实参作一份拷贝并传递给调用的函数,函数不能修改作为实参的实际变量的值,而只能修改传递给它的那份拷贝。
然而,如果要拷贝整个数组,无论在时间上还是在内存空间上的开销都可能是非常大的。而且在绝大部分情况下,你其实并不需要整个数组的拷贝,你只想告诉函数在那一时刻对哪个特定的数组感兴趣。
事实上,取地址操作符的主要用途就是实现传址调用;
我们倾向于始终把参数定义为指针,因为这是编译器内部所使用的形式;
注意,有一样操作只能在指针里进行而无法在数组中进行,那就是修改它的值。
数组名是不可修改的左值,它的值是不能改变的。
不能把一个数组赋值给另一个数组,因为数组作为一个整体不能成为赋值的对象。
可以把数组名赋值给一个指针,就是因为这个"在表达式中的数组名被编译器当作一个指针"的规则。
只能够在数组声明时对它进行整体的初始化。
多维数组可以通过嵌套的花括号进行初始化:
short a[2][5] = {
    {10,12,3,4,-5},
    {3,22,6,0,-5},
};
 
int b[][3] = {{0,0,0},{1,1,1},};
注意,可以在最后一个初始化值的后面加一个逗号,也可以省略。
同时,也可以省略最左边下标的长度(也只能是最左边的下标),编译器会根据初始化值的个数推断出它的长度。
初始化二维字符串数组的方法:
char vegetables[][9] = { "beet",
             "barley",
             "basil",
             "broccoli",
             "beans" };
一种有用的方法是建立指针数组。字符串常量可以用作数组初始化值,编译器会正确地把各个字符存储于数组中的地址。因此:
char *vegetables[] = { "carrot",
            "celery",
            "corn",
            "cilantro",
            "crispy fried patatoes"}; /*没问题*/
注意它的初始化部分与字符"数组的数组"初始化部分是一样的。只有字符串常量才可以初始化指针数组。指针数组不能由非字符串的类型直接初始化:
int *weight[] = {        /*无法成功编译*/
         {1,2,3,4,5},
         {6,7},
         {8,9,10}
        };      /*无法成功编译*/
C语言中最常见最重要的数据结构:指向字符串的一维指针数组,声明如下:char *a[4];
注意,char *turnip[23]把"turnip"声明为一个具有23个元素的数组,每个元素的类型是一个指向字符的指针(或者一个字符串————单纯从声明中无法区分两者)。可以假想它两边加上了括号————(char *)tunip[23]。
数组指针就是一个指针,指向的是数组,如char (*c) [64];
又如,int (*my_array)[20],一个指向20个元素的int数组的指针;
指针数组是一个数组,里面的每个元素都是指针,如char *c[15];
P233 数组和指针参数是如何被编译器修改的  C专家编程
argv是个指针数组,即char *argv[],这个表达式被编译器改写为指向数组第一个元素的指针,也就是一个指向指针的指针,如char **argv;
形参被改写为指向数组第一个元素的指针;
P238 使用指针从函数返回一个数组  C专家编程
记住,声明必须在使用之前;
int (*paf()) [20];
paf是一个函数,它返回一个指向包含20个int元素的数组的指针。
int (*paf()) [20]
{
    int (*pear)[20]; /*声明一个指向包含20个int元素的数组的指针*/
    pear = calloc(20,sizeof(int));
    if(!pear) longjmp(error,1);
    return pear;
}
用下面这样的方法来调用函数:
int (*result)[20]; /*声明一个指向包含20个int元素的数组的指针*/
...
result = paf();    /*调用函数*/
(*result)[3] = 12; /*访问结果数组*/
 
const int limit = 10;
char plum[limit];  /*error*/
Usenet网络的C语言论坛;
 
标准库malloc函数包含在stdlib.h里
exit()包含在stdlib.h里
 
初始化数组
  char msg[10];
  memcpy(msg,0,sizeof(msg));
 
要注意的是,memset是对字节进行操作,
  所以上述程序如果改为
  int array[5] = {1,4,3,5,2};
  for(int i = 0; i < 5; i++)
  cout<<array[i]<<" ";
  cout<<endl;
  memset(array,1,5*sizeof(int));// 注意 这里与上面的程序不同
  for(int k = 0; k < 5; k++)
  cout<<array[k]<<" ";
  cout<<endl;
  输出的结果就是:
  1 4 3 5 2
  16843009 16843009 16843009 16843009 16843009
  为什么呢?
  因为memset是以字节为单位就是对array指向的内存的5个字节进行赋值,每个都用 ASCII为1的字符去填充,转为二进制后,1就是00000001,占一个字节。
    一个INT元素是4字节,合一起就是 00000001000000010000000100000001,就等于16843009,就完成了对一个INT元素的赋值了。
  所以用memset对非字符型数组赋初值是不可取的!
  例如有一个结构体Some x,可以这样清零:
  memset( &x, 0, sizeof(Some) );
  如果是一个结构体的数组Some x[10],可以这样:
  memset( x, 0, sizeof(Some)*10 );
 
例子
  main(){
  char *s="Golden Global View";
  clrscr();
  memset(s,'G',6);//这里有问题// 单步运行到这里会提示内存访问冲突
  printf("%s",s);
  getchar();
  return 0;
  } 
  【以上例子出现内存访问冲突应该是因为s被当做常量放入程序存储空间,如果修改为char s[]="Golden Global View";则没有问题了。】
 
 #pragma pack(n)和#pragma pack()
  struct sample
  {
  char a;
  double b;
  };
  当sample结构没有加#pragma pack(n)的时候,sample按最大的成员那个对齐;
  (所谓的对齐是指对齐数为n时,对每个成员进行对齐,既如果成员a的大小小于n则将a扩大到n个大小;
  如果a的大小大于n则使用a的大小;)所以上面那个结构的大小为16字节.
  当sample结构加#pragma pack(1)的时候,sizeof(sample)=9字节;无空字节。
  (另注:当n大于sample结构的最大成员的大小时,n取最大成员的大小。
  所以当n越大时,结构的速度越快,大小越大;反之则)
  #pragma pack()就是取消#pragma pack(n)的意思了,也就是说接下来的结构不用#pragma pack(n)
 
应用实例:
在网络协议编程中,经常会处理不同协议的数据报文。一种方法是通过指针偏移的
  方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来
  也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这
  一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,
  不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,
  其它程序无需修改,省时省力。下面以TCP协议首部为例,说明如何定义协议结构。
  其协议结构定义如下:
  #pragma pack(1) // 按照1字节方式进行对齐
  struct TCPHEADER
  {
  short SrcPort; // 16位源端口号
  short DstPort; // 16位目的端口号
  int SerialNo; // 32位序列号
  int AckNo; // 32位确认号
  unsigned char HaderLen : 4; // 4位首部长度
  unsigned char Reserved1 : 4; // 保留6位中的4位
  unsigned char Reserved2 : 2; // 保留6位中的2位
  unsigned char URG : 1;
  unsigned char ACK : 1;
  unsigned char PSH : 1;
  unsigned char RST : 1;
  unsigned char SYN : 1;
  unsigned char FIN : 1;
  short WindowSize; // 16位窗口大小
  short TcpChkSum; // 16位TCP检验和
  short UrgentPointer; // 16位紧急指针
  };
  #pragma pack() // 取消1字节对齐方式 #pragma pack规定的对齐长度,实际使用的规则是: 结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。 也就是说,当#pragma pack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。 而结构整体的对齐,则按照结构体中最大的数据成员 和 #pragma pack指定值 之间,较小的那个进行。
  指定连接要使用的库比如我们连接的时候用到了 WSock32.lib,你当然可以不辞辛苦地把它加入到你的工程中。但是我觉得更方便的方法是使用 #pragma 指示符,指定要连接的库:#pragma comment(lib, "WSock32.lib")
 
%d:输出带符号十进制整数(正号不输出);
%f:以小数形式输出,隐含输出6位小数;
%u:输出无符号十进制整数;
m:要输出的数据宽度为m位,不足m位,左端补空格凑齐,大于m位,则按实际位数输出;
0m:与m类似,不同之处是在左端补0;
%m.n:m为输出数据的总宽度,n对实数而言为输出数据的小数位数,对字符串而言为所截取的字符个数;
*:输出的数据宽度由紧随其后的常量(变量)值确定;
-:输出的数据靠左对齐;
main()
{
    int i=65;
    float x=3.14159;
    printf("%5d\n",i);
    printf("%05d\n",i);
    printf("*d\n",5,i);
    printf("%7.5f,%7.4f\n",x,x);
    printf("%3s,%6.2s,%.3s","this","this","this");
    printf("%6d%-6d\n",i,i);
    //输出百分号%
    printf("%f%%\n",1.0/3);
}
输出:
_ _ _65
0 0 065
_ _ _65
3.14159,_3.1416      
this,_ _ _ _th,thi
_ _ _ _65,65 _ _ _ _
0.333333%
 
字符输出函数putchar:
需#include <stdio.h>
可输出转义字符,如换行:putchar('\n');
eg:
#include <stdio.h>
int main()
{
    char c;
    c=getchar();
    putchar(c);
    //或者直接putchar(getchar());
    //抑或printf("%c",getchar());
}
 
fscanf()函数和fprintf()函数的读写对象不是键盘和显示器,而是磁盘文件;
fscanf()函数的作用是:从文件中按照指定的格式输入;
fseek()函数一般用于二进制文件,在文本文件中由于要进行转换,故往往计算的位置会出现错误。
cprintf():送格式化输出至文本窗口屏幕中
 
vc中利用"ConsoleOut.lib"静态库文件,调用其中相应函数,进行界面制作。其"ConsoleOut.lib"库中各函数使用方法,通过"ConsoleOut.h"头文件引入,进行查看及使用。
#include "ConsoleOut.h"
#pragma comment(lib,"ConsoleOut.lib")
 
表头文件: #include <string.h>
定义函数: void *memcpy(void *dest, const void *src, size_t n)
函数说明: memcpy()用来拷贝src所指的内存内容前n个字节到dest所指的内存地址上。与strcpy()不同的是,memcpy()会完整的复制n个字节,不会因为遇到字符串结束'\0'而结束
返回值:   返回指向dest的指针
附加说明: 指针src和dest所指的内存区域不可重叠
 
-------------------------------------------------------
#include <string.h>
#include <stdio.h>
 
int main()
{
    char a[30] = "string (a)";
    char b[30] = "hi\0zengxiaolong";
    int i;
 
    strcpy(a, b);             //a[30] = "hi\0ing (a)"
    printf("strcpy():");
    for(i = 0; i < 30; i++)
        printf("%c", a[i]);   //hi ing (a)
 
 
    memcpy(a, b, 30);         //a[30] = "hi\0zengxiaolong"
    printf("\nmemcpy():");
    for(i = 0; i < 30; i++)
        printf("%c", a[i]);   //hi zengxiaolong
    printf("\n i = %d\n", i); //30
 
}
 
fputs()与puts()不同之处在于:
1.fputs()并不会为输出自动添加换行符;
2.fputs()需要两个参数;
 
#include <stdio.h>
 
int main(int argc, char *argv[])
{
    char *str = "Hiview!";
 
    puts(str);
    fputs(str,stdout);
 
    return 0;
}
 
编程习惯:
在其它文件中定义的变量和函数,要在本文件中使用,都使用extern进行声明;
如果函数只是调用,而没有进行函数指针的赋值,或者函数地址的打印,可以不用extern(这样做是有隐患的);

C专家编程 读书笔记相关推荐

  1. C专家编程-读书笔记(书本顺序)

    C语言设计哲学:   一切工作程序员自己负责.   语言中的所有特性都不需要隐式的运行时支持.   程序员所做的都是对的.   程序员应该知道自己在干什么,并保证自己的所作所为是正确的. ====== ...

  2. C专家编程--读书笔记九 再论数组

    第九章 一.知识点 1.所有作为函数参数的数组名总是可以通过编译器转换成指针. 然而,数组和指针在编译器处理时是不同的,在运行时的表示形式也是不一样的,并可能产生不同的代码.对编译器而言,一个数组就是 ...

  3. C专家编程--读书笔记十 再论指针

    第十章 一.知识点 1.C标准规定%s说明符的参数必须是一个指向字符数组的指针.所以如: char *p = NULL; printf("%s", p); 这是不正确的.NULL是 ...

  4. C专家编程--读书笔记六 运行时数据结构

    第六章 一.知识点 1.代码和数据的区别也可以认为是编译时和运行时的分界线.编译器的绝大部分工作都跟翻译代码有关:必要的数据存储管理的绝大部分都在运行时进行.(P121) 2."a.out& ...

  5. c专家编程 读书笔记

    c诡异离奇,缺陷重重,却获得了巨大的成功 编译器设计者的金科玉律:效率=一切 c预处理器:1.字符串替换 2.头文件包含 3.通用代码模板的扩展 预处理一定要使用强制类型转换!!!明确数据类型 每一个 ...

  6. C专家编程读书笔记一:C语言晦涩难懂的声明

    理解C语言声明的优先级规则: 声明从它的名字开始读取,然后按照优先级顺序依次读取 优先级从高到低依次是: B1     声明中被括号括起来的那部分 B2     后缀操作符:括号()表示是一个函数,二 ...

  7. 《程序员修炼之道–从小工到专家》读书笔记

    <程序员修炼之道–从小工到专家>的读书笔记 <程序员修炼之道–从小工到专家>[美]Andrew Hunt / David Thomas 著 马维达 译 看这本书主要使用了检视阅 ...

  8. UNIX网络编程--读书笔记

    会集中这段时间写UNIX网络编程这本书的读书笔记,准备读三本,这一系类的文章会不断更新,一直会持续一个月多,每篇的前半部分是书中讲述的内容,每篇文章的后半部分是自己的心得体会,文章中的红色内容是很重要 ...

  9. mozart-oz中有限域编程读书笔记

    mozart-oz自带文档: <Finite Domain Constraint Programming in Oz. A Tutorial.>读书笔记 http://www.mozart ...

最新文章

  1. microsoft公式3.0_用了20年的word,居然不知道公式还可以这样输入
  2. oracle主目录自动检测,ORACLE ADDM数据库自动诊断测试
  3. nginx 301重定向带www的https链接配置方法
  4. C/Cpp / STL / map 和 set 的不同点和相同点。
  5. 探索 OpenStack 之(10):深入镜像服务Glance
  6. java 带点的字符串处理,关于android:java中字符串上带点的分割函数
  7. Java Arraylist 如何使用 Comparator排序
  8. React Native - FlexBox弹性盒模型
  9. 内核电源管理器已启动关机转换_电气器件-菲尼克斯UPS(不间断电源)使用
  10. dumpbin.exe
  11. 安装Ubuntu18
  12. 三星android se,安卓小钢炮小米8 SE初体验!华为三星靠边站
  13. mybatis查询出现索引越界异常
  14. java html模板转图片、动态绑定数据
  15. awl多线程SYN***
  16. 微博服务器瘫痪容易修复吗,微博服务器九次瘫痪,还有一个竟然连崩四回,程序员:放过我吧!...
  17. 基于OpenCV的音频频谱优化(仿酷狗频谱)
  18. matlab电力电子技术仿真错误,Matlab在电力电子技术仿真中的应用
  19. 删除单号中的符号并查询快递物流信息
  20. 【转载】成本中心费用分配与分摊的区别

热门文章

  1. Linux命令之重启命令
  2. css引入自定义字体/特殊字体/ttf格式语言包
  3. 今天真TMD闹心 哎呦我去了!!
  4. 以服务为驱动 自上而下创建私有云
  5. restTemplate文件上传与下载
  6. 静态方法:无法在静态上下文中引用非静态
  7. 微信小程序中尺寸单位rpx及样式的用法
  8. 容器安全03:NIST.SP.800-190容器安全指南
  9. 大数据才是未来,Oracle、SQL Server成昨日黄花?
  10. Spring(8):构造方法注入与示例