c语言精髓之编译过程,C语言精髓知识点

1.字节数:

Char:1个字节

Unsigned:1个字节

Short:2/4个字节

Int:2/4个字节

Unsigned

int:2/4个字节

编译器在32位一下:

Long:4个字节

Unsigned long:8个字节

Float :4个字节

Double:8个字节

《**:不存在无符号的float和double类型

3.补码规则:

正数的补码就为其本身

负数的补码为按位取反加1

4.大端,小端的存储

小端

0x0016F9c0

78

0x0016F9c1

56

0x0016f9c2

34

总结:低地址放低位数据

高地址放高位数据。

大端

0x0016F9c0

34

0x0016F9c1

56

0x0016f9c2

78

总结:低地址放高位数据

高地址放低位数据。

一般存储采用小端存储

Eg:

Int i = 0x12345678;

//首先要转化成占一个字节的类型

If(*(char*)&i=0x12;//

低地址如果存放的是高数据则说明

它是大端否则是小端(栈的生长方向右高地址到低地址)

{

Return

true;

}

Else

{

Return

false;

}

intget_current_sysmode()

{

unionS

{

chara;

intb;

};

unionS

g;

g.b = 0x12345678;

if(g.a

== 0x78)

{

return-1;

}

else

{

return1;

}

}

判断大小端调用实现方法

法2

intmain()

{

inti

= 0x12345678;

if(*(char*)&i==

0x78)

{

return1;

}

else

{

return0;

}

}

5.标识符:不能以数字开头。下划线,字母可开头《一般下划线不合

理,底层程序一般用下划线开头》

关键字不能用做标识符,大小写较敏感,windows大小写不敏感

Const

int n=10;  “const”为常变量,定义时必须赋值

并且不能改变,C++语法。

6.int

i; i=1;

devc++

vc

Printf(“%d”,i++)

1

1

Printf(“%d”,i++)

2

2

Printf(“%d”,++i)

4

4

Printf(“%d”,--i)

3

3

Int b=(i++)+(++i)+(++i)+(i++);

Printf(“%d”,b);

B=20;

7.拓展

Ctrl+F

查找

Ctrl+H

替换

Ctrl+G

跳转

Ctrl+F8

对齐

Ctrl+Z

结束

Ctrl+C

中断

8.*p在32位的计算机中为4个字符,在64位的计算机中8个字符。

Int/long/short所代表的指针均为4/8个字符。

9.Int

arr【a】;

Int a=10;

不能编译,a应该为常量,在int前加const或定义常熟宏则可以编译(C++语法中const int

a=10,a为常量,C语言中a为常变量)

10.堆是从低地址向高地址申请。

11.若a【10】={1,2,3,4},未被初始化列表指定的数组剩余元素,系统会自动把整形常量初始化为0,字符型初始化为“\0”,指针型初始化为null。

12.#include

#include

int main()

{

char arr[]="afkhjfk";

printf("%d",strlen(arr));

printf("%d",sizeof(arr));

return 0;

}

第一个等于7,第二个等于8;

原因:strlen求字符串长度,sizeof求字符串所占空间的大小。

Char

arr[4]={“a”,”b”,”c”,”d”};

Char brr[]=”abcd”

Printf(“%d”,sizeof(arr));

Printf(“%d”,sizeof(brr));

第一个为4,第二个为5;

Char arr[4]={“a”,”b”,”c”,”d”};只定义了4个字符数组,系统会自动加\0,则打印出来的为abcd+乱码;

若改为char arr[5]={“a”,”b”,”c”,”d”};系统会自动为字符数组赋值\0,则打印为abcd.

13.strset:设置字符串内容为某字符(如:*)

Strchr:指的是若传入字符串中无字母,则输入NULL.

若有此字母,则输入该字母的地址。

Assert(str[]!=0)若不满足()内的就会中断该程序

14.不能做switch()的参数类型是(float,double).

15.不使用其他变量交换a,b的值

a=a+b;b=a-b;a=a-b;

A

= a ^ b;

B

= a ^ b;

A

= a ^ b;

16.解释堆和栈的区别

(1)堆是通过malloc/relloc申请动态空间,

栈:局部变量保存在栈内。

(2)堆:从低地址向高地址生成

栈:与堆相反,从高地址向低地址生成

(3)堆:内存中不连续

栈:内存中连续。

17.在微型计算机中(pc),RAM叫(随机读写存储器)

理论上,64位寻址能力是32位寻址能力的2^(64-1)/

2^(32-1)=2^(32-1)

*********12*34=452是多少进制的算法???

1*6^1+2*6^0=8

3*6^1+4*6^0=22

22*8=176

452=4*6^2+5*6^1+2*6^0=176

18

#define

foo(x)  x*3-2

Int

main()

{

Int

a=2;int b=3;

Printf(“%d”,foo(a+b));

Return

0;

}

2+3*3-2=9;

19:函数

(1)全局函数:定义在函数体外部(若不给初值,系统会自动

分0)。

生命周期:从定义开始到全部函数程序结束,一般写在程

序的开始,不写在任意函数体内

(2)局部变量:定义在函数体内部(普通局部变量若不给初始化值,系统会自动分0或者不符合程序要求)

生命周期:从定义开始到所定义的函数结束。

Static存在于全局/静态变量区

20.程序局部变量存在于栈中(stack)

静态变量存在于

数据段/全局变量区/静态变量区

全局变量存在于全局变量区

21.Extern

外部变量声明

22.函数调用与宏之间的优缺点?

函数调用浪费系统资源,可以展开调试。

宏比较节省系统资源,代码较为简单,较易修改,但不容易读,无法展开调用。

22.共用体是构造数据类型,也叫联合体

它使几个不同类型的变量共占一段内存(相互覆

盖),每次只有一个能使用.

结构体则不然, 每个成员都会有存储空间的,可以一起用.

23.数据存放在局部变量,也就是栈中,执行完就会释放,而指针存放在全局变量中,一直到整个程序结束

24. typedef int *p;与 #define int *p;的区别以及它的用法

#define是在预编译时处理的,它只能做简单的字符串替换,而

Typedef是在编译阶段处理的

Eg1:  p i,j;

用typedef int *p;相当于

int *i;  int *j;

用#define int*p;相当于p=int *

Int *i,j;

//而这个j没有定义会出现错误

Eg2:

Typedef

struct

(STU)

{

Int

num;

Float

score;

}stu;

声明一个结构体,typedef的作用使用stu来代替struct(STU),这个STU(一个名字)可要可不要,这里的stu为结构体类型不是变量名。

***如果没有名字:指定了一个无名的结构体类型,再不能以此结构类型去定义其他的变量

Struct STU

{

Int

num;

Float

score;

}stu;

声明一个叫做STU(类型)的结构体,stu是结构体变量名;

Union 共用体类型

Eg 1:

Union data

{

Int

i;

Char

ch;

Float

f;

}a = { 1 ‘a’,1.5};错误!!!!

不能初始化3个成员,

它们占用同一段存储单元

Union data a = {16};  正确,对第一个成员初始化

Union data a = { . Ch =’j’};

c99允许对指定的一个成员

初始化。。

Eg 2;

a.ch = ‘a’;

a.f

= 1.5;

A.i

= 40;

完成以上3个赋值运算后,变量存储单元存放的是最后存入的40,原来的‘a’和1.5都被覆盖。

Printf

(“%d”,a.i)

40

Printf(“%f”,a.f)

未知

Printf

(“%c”,a.ch)‘c’

25.#include

Int

main()

{

Short

i;

Scanf(“%d”,&i);

//

Printf(“%d”,i)应该用%hd.

Return 0;

}

26.有符号整形的表示法(如下图1)

blog_e017ce840102w9y4.html

答案是255,碰到0时结束

0

blog_e017ce840102w9y4.html

-128

无符号整形(如下图2)

blog_e017ce840102w9y4.html

27.其它进制转十进制

Eg:11001.118=1*2^4+1*2^3+1*2^0+1*2^-1

1*2^-2+8*2^-3

28. 十进制转其它进制

整数部分倒置求余(从下往上),小数部分乘权值(从上往

下)。

函数名

调用形式

功能

返回值

fgetc

Fgetc(fp)

从fp指向的文件中读入一个字符

读成功,带回所读的字符,失败则返回文件结束标志EOF(-1)

fputc

Fputc(fp)

把字符ch写到文件指针变量fp所指向的文件中。

输出成功,返回值就是输出的字符,输出失败,则返回EOF(-1)

fgets

Fgets(str,n,fp))

从fp指向的文件读入一个长度为(n-1)字符串,存放到字符数组中str中。

读成功,返回地址str,失败则返回NULL

gputs

Fputs(str,fp)

把str所指向的字符串写到文件指针变量所指向的文件中。

输出成功,返回0;否则返回非0值;

Fread(一般用于二进制)

Fread(buffer,size,count,fp)

从文件fp中读取size*count个字节数放入buffer中)

Fwrite(一般用于二进制)

Fwrite(buffer,size,count,fp)

把buffer所指向的空间区域的size*count个字节放入到fp所指向的文件中。

29.**************

Int

main()

{

Int i=10;

Int j=20;

Const int *p=&i;

*p=100;

//因为int*为常变量,*p=100;不能通过,但是p=&j可以通过

P=&j;

*p=200;

}

//

若int* const p=&i;

则*p=100;通过

P=&j;

不通过;

Eg:  1.  int const *p;

可以修改指针的值,但是不能修改它所指向的值

2  int *const

p

可以修改指针所指向的值,但不能修改指针的值

3.  Int const

*const p;

指针和指针所指的变量的值都不能改变

30.memset;将已开辟的空间S的n个值设为c,它的作用一般用于内存空间初始化。

Memmove:用于从src拷贝count个字符到dest,如果目标区域和源区域优重叠的话,memmove能够保证在被覆盖之前将重叠区域的字节拷贝到目标区域中。但复制后src内容会被更改。但是目标区域和源区域诶有重叠则和memcpy函数功能相同。

Fseek:改变文件的位置标记

Ftell:测定文件位置标记的当前位置。

31.误区

Eg:

#include

Intmain()

{

Printf(“%d”,printf(“%d”,printf(“%d”,43)));

Return0;

}

输出是4321,因为:printf输出43后把它作为返回值给了下一个printf输出的仅仅是它 的个数,所以43

2

1.

32.数组指针

int[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};

在C语言中专门用来指向二维数组

Int(*p)[4];

一般用来指向数组(指向包含4个元素的一位数组)

P =

&a;表示指向数组的首地址

P =

a,表示p的值是&a【0】(指向首元素的首地址);

Eg:

int a[4] = {1,3,5,7};

int (*p)[4] ;

printf("%d\n",**p);

指针数组(指针数组是多个指针变量,以数组形式存在内存中

,占有多个指针的空间

以下的例子,,name是个不可知的表示,分别指向name[0],name[1],name[2]

Char *name[n]={“abcde”,””ghijk”,”lmnop”}

Char **p=name;

Printf(“%p”,name);打印的只是指针的地址。系统给它分配的地址。

Eg:

错误的做法

blog_e017ce840102w9y4.html

指针数组:一般用来指向字符串;

可以用指向一位数组指针来做

Eg:

int (*p) [3]  数组指针sizeof(p) = 4  ,sizeof(*p) =

12

int *p [3]  指针数组,  sizeof(p) = 12 ,sizeof(*p) =

4

char p[2][10] = {"hello","word"};

cout<

char (*str)[10];

cout<

;表示一个二维数组的地址

char *p[2] = {"hello","word"};

cout<

33.static保存在数据段中(影响变量只能在本文件中访问)

extern

(引入外部变量或函数)

34.不用其他的变量数值的交换

Eg:

a和b交换

a = a +

b;

b = a -

b;

a =a -

b;

用位来处理

a =

a^b;

b =

a^b;

a =

a^b;

35 误区

Int i=10;

Double dou =10,10;

(此处分子是浮点型==3.6)

Printf(“%lf”,i+dou+9/5-1.2*3)===17.5

(此处分子是整形=1;)

36.多重if和else的处理

If{ if

}

else

if

If{

elseif

}

每一层都会判断

只要有有一个条件合格则直接跳出

37

Eg: int str(char str[200])

Printf(“%d”,sizeof(str));======4;

首地址会退化成指针,所以返回4.

38.有关地址相减的问题

假定s和p之间有连个元素

Printf(“%d”,p-s);两个指针地址相减得到他们之间的个数

Printf(“%d”,(int)p-(int)s);

它的值为8;

39,误区

char

str[20]={'a','b','c','d','e'};

printf("%d",sizeof(str));==20;

Str中它是按字符来算的,没有在末尾补“\0”,但是字符串不同,字符串会在末尾补”\0”

40.知识点

printf("%p\r\n", (pAry + 1*sizeof(int[5])));1*sizeof(int[5])=====sizeof(int)*5=20;

#include

int main()

{

int arr[5] = {1,2,3,4,5};

printf("%d\n",sizeof(arr));

打印20;算的是整个数组长

所占的空间大小。

//printf(“%d\n”,sizeof(arr[5]));==sizeof(int);

打印4;只是算的一个数所占空间大小,并不是全部

printf("%d\n",&arr);

printf("%d\n",&arr+1);

两个地址相减得到是16

!!&arr+1是越过了这一行(地址不会发生溢出,但它的解引用会发生溢出),所以&arr和&arr+1之间相差了16个字节。

return 0;

}

41.eg:

Char

*pathname=”temp”;

Char

buff[]=”hello”

不能对指针赋值,它保存在全局变量中,可以对数组赋值,它保存在局部变量中。

42.auto和malloc的优缺点

Auto的优点:

1.

不用手动管理

2.

空间占用略小

3.

速度/效率略高

4.

不会产生内存泄漏

Malloc的缺点:

1.

手动释放内存

2.

空间占有略大

3.

速度/效率略慢

4.

不释放会产生内存泄漏

43.

内存所在区域

声明周期

可见范围

作用域

局部变量

栈中

函数内部

函数内部

函数内部

全局变量

数据段/

静态变量区/全局变量区

进程建立起开始,进程结束时中止

整个文件

文件作用域

静态变量

数据段/

全局变量区/静态变量区

进程建立起开始,进程结束时中止

静态局部变量,静态全局变量

外部变量

数据段/

全局变量区/静态变量区

进程建立起开始,进程结束时中止。

通过extern关键字引入的文件,在引入的整个文件可见

44.宏定义(宏不能做递归)

常用的宏有:sprinf,__VA_ARGS__,assert;(已在错误总结中记录)

#include

#include

#define debug_output(format,...)

\

char

out_buf[512];

\

sprintf(out_buf,format,__VA_ARGS__);

\

fprintf("%s",out_buf)

int main()

{

printf("%s", debug_output("%s,%d","hello",10));

return 0;

}

在宏定义的使用中,易出错的点

#define max( a, b)  ((a)>(b))

? (a) : (b)) 从右至左。

X =5;

Y = 8;

Z= max(x++,y++);

Prinf(“x

= %d,y = %d,z = %d\n”,x,y,z)

这块应该值得注意,如果按照正常的函数调用的话,打印z=8;

但是如果采用宏定义中的max则打印x = 6,y = 10,z

= 9;第一个表达式是一个条件表达式,用于确定另两个表达式中的哪一个,剩余的那个表达式将不会执行。宏定义只是简单的进行替换,并不会去

判断,第一个表达式是以一个条件表达式,

#define Inc(x) ++x

int main()

{

int arr[5] = {1,2,3,4,5};

int i = 0;

arr[Inc(i)] = arr[Inc(i)]+10;

for(int j = 0; j < 5; j++)

{

printf("%d ",arr[j]);

}

return 0;

}

这块打印1,2,12,4,5

注意#define只是进行简单的宏替换

也就是i++了两次

宏定义中

Eg:

#define

str(x)

#x

这个定义x讲打印出来的是一个字符串,在x前面加一个‘#’。

#define str(s1,s2)

s1##s2

这个定义的意思是把s2连接到s1的后面,形如s1s2.

45.易出错点

Int i =10 ;

Printf(“%d”,sizeof(i++));

此处打印4

Printf(”%d”,i);

此处打印10

Sizeof测内存空间所占的大小,在编译的阶段只是把4push并没有++,也就是说直接忽视了i++,仅仅测它所占的大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值