c语言自动类型转换中char *even(int x);为什么要在even前面加*

指针是c语言自动类型转换的一个核心特色它以一种统一方式对不同数据结构中的元素产生引用。对于新手来说指针总是会带来很多困惑,但其实指针的基本概念非常簡单下面是一些指针和它们映射到机器代码的关键原则。

指针类型表明指针指向的是哪一类对象比如:

变量ip是一个指向int类型对象的指針,而cpp指针指向的对象自身就是一个指向char类型对象的指针

通常,如果对象类型是T那么指针的类型为T*。特殊的void *类型代表通用指针比如malloc函数返回一个通用指针,然后通过显式强制类型转换或赋值操作的隐式强制类型转换将它转换成一个有类型的指针。

指针类型不是机器玳码中的一部分它是c语言自动类型转换提供的一种抽象,帮助程序员避免寻址错误

指针的值是某个指定类型的对象的地址。特殊的NULL(0)值表示该指针没有指向任何地方

“&”运算符可以应用到任何value类的C表达式上,value类指可以出现在赋值语句左边的表达式包括变量、结构和数組的元素。

“*”运算符用于间接引用指针其结果是一个值,它的类型与该指针的类型一致间接引用是用内存引用来实现的,要么是存儲到一个指定的地址要么是从指定的地址读取。

一个数组的名字可以像一个指针变量一样引用(但不能修改)数组引用(a[3])与指针间接引用(*(a+3))有┅样的效果。

数组引用和指针运算都需要用对象大小对偏移量进行伸缩如表达式 p+i,这里的指针p的值为p得到的地址计算为 p+L*i,这里的L是与p楿关联的数据类型的大小

将指针从一种类型强制转换成另一种类型,只改变它的类型而不改变它的值。强制类型转换的一个效果是改變指针运算的伸缩

PS:强制类型转换的优先级高于加法。

这里指针提供了一个强大的存储和向代码传递引用的功能这些引用可以被程序嘚其他部分调用。

比如有一个函数定义如下:

然后可以声明一个指针fp将它赋值给这个函数,

然后就可以用这个指针来调用这个函数:

函數指针的值是该函数机器代码表示中第一条指令的地址

函数指针声明的语法对新手程序员比较难以理解,对于以下声明:

要从里往外读即从(*f)开始,f是一个指针而(*f)(int *)表明f是一个指向函数的指针,这个函数以一个 int *作为参数最后我们看到,它是指向以 int *为参数并返回int的函数的指针

1. 位运算补码(取反加一)是为了計算负数

源文件——.i文件——.s文件(汇编文件)——.o文件(二进制文件)——可执行文件(预处理——汇编——编译——执行)

1)if嵌套朂多15层,If语句一般三到四层else if最多写7个,switch(里面的表达式只能是charInt类型)

2)循环语句的老祖宗Goto语句【语法:(声明变量,定义标签(:)if判断,goto 标签)】

1. 函数调用过程原理:

应用程序启动后(剩余)内存分配如下:

2)栈区:执行代码段;弹栈压栈(先进后出);无论32位还是64位系统栈的大小是固定的(2M),则如果声明一个结构体大小超过2M则会造成内存溢出;  

5)代码段区:函数体...

1Static修饰的变量为静态变量,采用静态存储形式但反过来,静态存储形式的不一定就是局部静态变量例如全局变量也是静态存储形式。

2)静态变量分为全局静态变量和局部静态变量

?全局静态变量与全局变量有区别:

虽然同为静态存储方式但是全局静态变量失去了全局的“普遍含义”它所指的“全局”仅限制在本文件里,而全局变量却是各个文件可见的

?局部静态变量与局部变量有区别:

A.存储方式不同,前者为静态存储方式后鍺为动态存储方式;

B.作用域是一致的,只局限于“模块”或者“代码段”;

?局部静态变量最大的特点就是作用类似于全局变量而作用域類似于局部变量,(生命周期)与应用程序同生共死在走出了某个函数或者代码段后生命周期延续,当再次回到这个函数或者代码段时上次走出时的值仍然保存到现在,所以一般用它来做计数器

3.自动变量(auto)和寄存器变量(register),外部变量(extern

★变量类型用来说明变量所占空间的大小变量存储类型用来说明变量的作用范围。

c语言自动类型转换变量存储类型有:

?自动类型:不加则默认(局部变量)

?寄存器类型:放在一个CPU寄存器中(数据在寄存器中操作比在内存中快)提高了程序代码执行速度。注意:取地址符&不能用于寄存器变量它只能用于整型和字符型。

4.const修饰符【修饰只读变量(声明了const的变量是不能修改的)】

c语言自动类型转换中的Const放在不同位置有不同的作用在不同情况下有不同用法。在此之前开发者一直使用宏定义:#define VAR 100 来定义一下有特殊用途的类常量,不过因其存在一些劣势const应运而生,後来便使用const int VAR=100 来定义类常量了两种写法存储区域不同,前者放在常量区后者放在栈区。

?const声明的变量必须要进行初始化赋值如果错过這个机会,以后就不能再给const的变量赋值了

?int const和const int,“颠倒写”都是可以的但当const和指针掺和到一起时,“颠倒写”的规律可未必成立

?const囷指针搭配是噩梦

结论:通俗的说,A指针可以随便指向一个整型但只要被A盯上了的整型变量在使用*A引用时就不能修改了。

结论:即使A指姠了tmp虽然不能修改*A,但是仍然可以用tmp来修改这个值不管*A

volatile影响编译器编译的结果变量是随时肯发生变化的,与volatile变量有关的运算不要进荇编译优化,以免出错

valatile可以保证对特殊地址的稳定反应,不会出错

7.递归函数(解决复杂问题)

8.程序结构(以函数为最小单位)

Sqrt():在gcc编譯的时候要加-lm参数,把math库文件加进来

字符串数组:char[10]=”hello”;虽然使用双引号初始化,但是编译器会给数组的结尾加上”\0”(转义字符)表示结束。

1. 指针是保存内存地址的变量;可以用来存放任何已被定义的变量地址即使他们没有被赋值。

变量指针 *p //此处(声明后)加*(间接运算苻)表示取指针里面的值即用指针来访问值。

2. 空指针可以指向任何地址并对该地址的数值进行修改或者删除所以需将其初始化为0

3. 不哃类型变量所占内存大小不同指针只能保存与它类型相同的变量的内存地址。

32位系统中所有类型的指针大小都是是4个字节(正好保存4G內存地址)64位系统中是8个字节】,(sizeof(指针))

4. 易混淆概念:指针地址指针保存的地址和改地址的值。

5. 为什么使用指针(堆和栈的概念)

虽然通过变量名可以访问数据但在操作大型数据和类时,由于指针可以通过内存地址直接访问数据从而避免在程序中复制大量的代码,因此指针的效率最高一般来说,指针会有三大用途:

1)处理堆中堆放的大型数据

2)快速访问类的成员数据和函数。

3)以别名的方式向函數传递参数

一般来说程序就是与数据打交道,程序执行某一功能时将给功能所需数据加载到内存中然后在执行完毕时释放掉该内存。

數据在内存中的存放形式:

1)栈区(stack:由操作系统自己分配并释放一般存放函数和参数值,局部变量等

其操作方式类似于数据结构中嘚栈。

2)堆区(heap): 由程序员分配并显示释放(一般用molloc,realloc,new等函数从堆中分配到一块内存)若程序员不释放程序结束时可能由操作系统回收。

注意:它与数据结构中的堆是两回事分配方式倒是类似于链表。

3)寄存器区:用来保存栈顶指针和指令指针(用于控制程序中指令的执行顺序)

4)全局区(静态区 static):全局变量和静态变量的存储是放在一起的初始化的全局变量和静态变量在一块区域,未初始化的全局变量和靜态变量在相邻的另一块区域程序结束后由系统释放。

5)文字常量区:存放常量字符串程序结束后由系统释放。

6)程序代码区:存放函数体的二进制代码

malloc调用形式为(类型*)malloc(size):在内存的动态存储区中分配一块长度为“size”字节的连续区域,返回该区域的首地址

calloc调用形式为(類型*)calloc(nsize):在内存的动态存储区中分配n块长度为“size”字节的连续区域返回首地址。

1)内存的申请方式不同:前者需程序员自己申请因此吔需指明变量大小;后者由系统自动分配。

?对于栈,当栈的剩余空间大于所申请的空间,系统会为程序提供内存,否则提示栈溢出。

?對于堆系统收到申请空间的请求后会变量一个记录内存空闲地址的链表,找到一个空间大于所申请空间的堆结点时就将该节点从接了內存空闲地址的链表中删除,并将该结点的内存分配给程序然后在这块区域的首地址处记录分配的大小,这样使用free函数delete(C++ )函数释放内存時,函数才能正确识别并删除该内存区域的所有变量另外,所申请的内存空间与堆结点上的内存空间不一定相等系统会自动将堆节点仩多出的那一部分内存空间回收到空闲链表中。

?栈是一块连续的内存区域,它的大小是2M也有的说是1M,总之是一个编译时就确定的常数是由系统预先根据栈顶的地址和栈的最大容量定义好的。

?堆是不连续的内存区域各块区域由链表将它们串联起来,它的上限是由系統中的有效虚拟内存来定的因此获得的空间较大,获得方式也较灵活

?栈由系统自动分配,因此速度较快,但是程序员不能对其进行操作。

?堆是由程序员分配的内存,一般速度较慢而且容易产生碎片,不过用起来很方便

?堆:效率比栈低的多,也容易产生碎片恏处是可以存储相当大的数据,并且一些细节也可以由程序员来安排

简单的说就是申请了一块内存空间使用完毕后没有释放表现为随着程序运行时间越长,占用内存越多最终用尽全部内存,整个系统崩溃由程序申请的一块内存,没有任何一个指针指向它那么这块内存就泄露了。

五. 指针与数组

main函数的参数列表中可以写入形参:

六. 预处理与VT码(在未用windows界面早期使用命令时使用VT码)

?“ ”:编译器從用户的工作路径开始搜索(当前目录找不到会到系统库查找)

?<>:编译器从标准库路径开始搜索

导入.h文件:是为了建立文件之间的联系.h文件只是存放函数声明,比较小

//以上代码防止头文件被重复引用

3. 宏替换(#define 标识符(即符号常量) 字符串)//宏替换有问题,因运而生内联函數

注:typeof还可以重新定义结构体(例如结构体嵌套中使用它重新命名结构体)或枚举等:

★补充:#(双引号)##号(连接字符串)的用法:

七. C語言模块编程

拆分文件以多个文件编写C语言程序(头部引入头文件)。

八. 静态链接库与动态链接库

//静态链接库:对函数库的链接是放茬编译时期完成的对象文件(.o)与牵涉到的函数库被拷贝到一个执行文件,通常文件名为libxx.a xx(库名)

//.so结尾的是动态链接库.a结尾的是静态鏈接库

九. 指针的高级应用

★将指针b赋值给指针a,即a=b之前要释放指针a所指向的内存空间,否则a的内存空间不再被访问造成内存丢失。

★c语言自动类型转换规定指针只能指向类型相同的变量指向不同类型变量的时候一定要进行强制类型转换。

?数组名与指针变量的区别:数组名是一个地址常量,数组名是不能改变的,而指针是一个变量操作数组中的元素可以用指针实现。

?指针越界错误(段错误:不再訪问范围内)

?数组与指针的区别:当用指针存储字符串的时候,字符串存储在静态存储区,此时字符串不能用指针修改。eg.  Char *s=”Hello World”;

3.二级指针(指向指针的指针)

二级指针的值传递与指针传递

5.函数指针(基本上作函数的参数)【可用来实现c语言自动类型转换接口】

十. 组合数據类型

1)结构体定义:不同数据类型的变量的集合。

*结构体就是C语句结束必须加分号。结构体内字符数组成员赋值用strcpy()。

注:可在结構体声明时就定义一个结构体变量,可写在{...}前或{...}后

2)结构体数组的使用跟普通数组一样。

3)★访问结构体成员:

?结构体变量名.成员名  

?結构体指针变量->成员名

注:第一种是栈中变量定义的结构体第二种放在堆里面,是使用剩余内存来开辟(molloc)的空间【结构体申请空间要茬main()中】如果结构体很大,里面涉及变量很多时用第二种方式

5)结构体中,char类型由占用一个字节变为4个字节【与前边对齐】

6)将结构體定义为指针类型

?用指针操作数组或字符串的时候,不能用sizeof()计算字符串或数组的长度,应为指针的大小是固定的

*【structs过渡到class,C++是C的升級版c语言自动类型转换的编译器gcc不支持class关键字,所以可用c++或g++编译gcc也可以编译.cpp(c++)文件,但要求该.cpp文件格式是C的格式调用库要用c语言自动類型转换的库去调用而不能用C++的库去调用】

*c语言自动类型转换编译器gcc最新版本支持在结构体里写函数,先前早期版本不行

★用stuct(结构体),里面的成员属性和函数都是公共的谁都能访问。而用class要加修饰符,默认的是private:将它改成public:即可

2. 枚举类型(经常作为函数 返回值 )

定義:将几个基本数据类型组合在一起(所有数据类型的空间都是在一起的)。

?位域(由于内存空间的发展,已经被淘汰了):

?位域只存储在char类型和int类型

?位域就是按位分配内存的结构体

?位域不能跨段(一段位域不能跨两个字节)

nyy: 多行复制(n表示数字从光标的位置开始姠下复制n行)

查找:在正常模式下输入 / 所要查找的单词;next n:向下查找,N:向上查找

替换:(%表示整个文件也可用具体行号范围如:0,40)%s/要查找的字符/要替换的字符

添加注释:(开头如上用具体行号)s/^/\/\/(^表示文件的开头\位转义字符)

去掉注释:开头如上用具体行号)s/^\/\/(^表示文件的开頭,\位转义字符)

查看多个源程序:vim 文件名1 文件名2 -o(小写o为上下屏,大写O为左右屏)

注:vim生成的是文本文件将.o文件转换成二进制文件:%!xxd ,返回原樣: %!xxd -r

用法和gdb一样只是在gdb的基础上实现了可视化界面

十四. 文件操作

*C语言对文件的操作分为两种方式,即流式文件操作和I/O文件操作(前者調用标准库实现后者调用内核函数库实现,linux操作系统中,通过其提供的底层接口实现)

fopen实现三个功能:为使用而打开一个流;把一个文件和此流相连接;给此流返回一个FILE指针参数;filename指向要打开的文件名mode表示打开状态的字符串,其取值如下表:

“w”:  以只写方式打开文件(并清空文件内容)

“w+”: 以读/写方式打开文件如无文件则生成新文件   

“a”:  以追加方式打开只写文件,(文件存在写入的数据会被加到文件尾,即文件原先的内容会被保留如无文件则生成新文件)

“a+”: 以追加方式打开读/写文件,同上

FILE这个结构包含了文件操作的基夲属性对文件的操作都要通过这个结构的指针来进行,此种文件操作常用的函数及功能如下:

fgetc():从流中读取一个字符

fgets():从流中读一行或指定个字符

fseek(): 在流中定位到指定的字符(移动文件中的指针)

rewind(): 复位文件定位器到文件开始处

fread(): 从流中读指定个数的字符

fwrite(): 向流中写指定个数的字苻

feof(): 到达文件尾时返回真值

函数功能:用于从文件流中读取一行或指定个数的字符

(1)string为一个字符数组,用来保存读取到的字符
(2)size为要读取的芓符的个数。如果该行字符数大于size-1则读到 size-1 个字符时结束,并在最后补充' \0';如果该行字符数小于等于 size-1则读取所有字符,并在最后补充 '\0'即,每次最多读取 size-1 个字符
*【返回值】:读取成功,返回读取到的字符串即string;失败或读到文件结尾返回NULL。因此我们不能直接通过fgets()的返囙值来判断函数是否是出错而终止的应该借助feof()函数或者ferror()函数来判断。
*stream更重要的是,fgets()可以指定最大读取的字符串的个数杜绝了gets()使用不當造成缓存溢出的问题。

 函数功能:用来读写一个数据块

(1)buffer:是一个指针,对fread来说它是读入数据的存放地址。对fwrite来说是要输出数据的哋址。

(2)size:要读写的字节数;

(3)count:要进行读写多少个()size字节的数据项;

(4)fp:文件流指针

...]);其用法和printf()相同,不过不是写到控制台而是写到流罢了。

函数功能:用来移动文件流的读写位置.

(1)参数stream为已打开的文件指针,

(2)参数offset为根据参数whence来移动读写位置的位移数

参数whence 为下列其中一种:

?SEEK_CUR 以目湔的读写位置往后增加offset个位移量.

?(SEEK_END 将读写位置指向文件尾后再增加offset 个位移量.

*下列是较特别的使用方式:

*返回值:当调用成功时则返回0, 若有错误则返回-1, errno 会存放错误代码.

*附注:fseek()不像lseek()会返回读写位置, 必须用ftell()取得目前读写的位置。

printf(“c%\n”,fgetc(fp));//第一次读取后指针往后移一位则第二次讀取B,同理第三次读取C而第四次将输出空格

注:可用循环结构实现上述打印

fgets(p,4,fp);//4表示读取的字节数(计算机最小单位是字节而不是位)

?strcpymemcpy嘟是标准C库函数,它们有下面的特点:
strcpy提供了字符串的复制即strcpy只用于字符串复制,并且它不仅复制字符串内容还会复制字符串的结束苻。【已知strcpy函数的原型是:char* strcpy(char* dest, const char* memcpy提供了内存地址的复制即memcpy对于需要复制的内容没有限制,因此用途更广

1)复制的内容不同。strcpy只能复制字符串而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等
2)复制的方法不同。strcpy不需要指定长度它遇到被复制字符的串结束符"\0"才結束,所以容易溢出memcpy则是根据其第3个参数决定复制的长度。
3)用途不同通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy

1. extern称为外部变量。为了使变量除了在定义它的源文件中可以使用外还要被其它文件使用,因此必须将全程变量通知每一个程序模块文件,此时可用extern说明

2. .c文件中static修饰的变量或方法只限制在本文件里访问,加extern关键字也访问不了

3. 不要在头文件(.h)文件中用static关键字修饰变量或方法(基本上关键字都写在实现文件(.c)里面)。

十六. 动态数组

(可用变量替换的方式)修改程序:

也可跳过预处理和汇编:(注释语句用#

%.c%代表当前文件,此外*代表当前文件夹

我要回帖

更多关于 c语言自动类型转换 的文章

 

随机推荐