塞班s60v3吧 关注:5,500贴子:162,964

【编程】关于编程语言的总贴

只看楼主收藏回复

吧主帮忙整理一下版面哈@华为三文鱼


来自手机贴吧1楼2015-01-23 00:46回复
    一,c语言入门必读手册


    来自手机贴吧2楼2015-01-23 00:47
    回复
      教程一,概述


      来自手机贴吧4楼2015-01-23 00:49
      回复


        IP属地:海南来自Android客户端8楼2015-01-23 01:02
        回复
          C语言入门教程 (五) 编写第一个C语言程序 前面几节介绍了常量和变量、 运算符 、 表达式 和语句的概念,对它们的使用有了一个大概的了解。也许刚学 程序 的人会觉得有些枯燥,下面我们就来编写第一个 C语言 程序。 #define PI 3.1416 main() { float Radius,Area; scanf(%f,&Radius); /*输入半径的值*/ Area=PI*Radius*Radius; printf(%f\n,Area); /*输出圆的面积*/ } 1.一个C语言程序,通常由带有#号的编译 预处理 语句开始。关于预处理我们在以后介绍,这里的#define PI 3.1415926相当于PI代表3.1416,下面在程序中遇到PI,我们就用3.1416替代一下。在以后的程序中,在学习预处理之前,我们都将不使 用预处理语句。 2.main() 任何一个完整的程序都需要main(),这是一个 函数 ,具体什么是函数,以后再讲,这儿你就要记住就行。后面有一对{}把所有的语句都括在里面,表明那些语句都属于main()里面。程序运行时从这个左大括号开始。 3.{}里面的4行语句大家应该都能明白,先定义两个变量,一个代表半径,一个代表面积,然后输入半径的值,然后求面积,最后在屏幕上输出面积。程序到 main()的那对{}的右大括号结束。求面积的语句Area=PI*Radius*Radius;相当于 Area=3.1416*Radius*Radius;(完全用3.1416替代PI)。 具体程序从编写到运行得到结果的步骤为: 1.双击tc.exe,进入Turbo C 2.0编译界面 2.ALT+E 进入编辑模式 3.书写程序 4.F2 存储程序(也可进入File菜单,选择save),第一次存储需要写上程序名称(*.C),回车 5.ALT+F9 编译,如果有错误和警告,光标停留在错误行,回车进行修改,修改后,回到4;没有错,下一步 6.CTRL+F9 连接和运行程序 7.用ALT+F5查看程序运行结果,任意键返回程序 如何打开一个已有的C文件: 1.双击tc.exe,进入Turbo C 2.0编译界面 2.F3 进入load状态,找到所要打开 文件 的目录,找到文件,回车;后面都一样。 具体的有哪些快捷键及其它们的作用,请查看第一节概述。 说明: 1.必须在程序的最开始部分定义所有用到的变量,例如这里的Area,Radius。 2.变量的命名要尽量有意义,如用代表该意思的英文单词、或者是汉语拼音,例如这里的Radius,Area,绝对禁止用毫无干系的字母,如a,b,c。 例如下面的程序,虽然意思和上面的一样,但是看上去意思不明朗,时间长了,很可能忘记程序本身的意思。对于仅仅是控制程序运行,不代表实际意思时,可以用 一些简单字母。 main() { float a,b; scanf(%f,&a); b=3.1416*a*a; printf(%f\n,b); } 3.采用层次书写程序的格式,要有合理的缩进,必要的时候要有空行,一行只书写一个语句。所有语句尽量不分行,除非太长(分行时变量、运算符,格式字符等等不能拆开),例如下面两个程序看起来就不好看了,虽然它们的功能和前面是一样的。 main() {float Radius,Area;scanf(%f,&Radius); Area=3.1416*Radius*Radius;printf(%f\n,Area);} main() { float Radius,Area; scanf(%f, %Radius); Area=3.1416*Radius *Radius; printf(%f\n, Area); } 4.程序在适当的地方要用/*……*/注释,它的意思表示在/* */里面的所有字符都不参加编译。因为一个较大的程序,经过一段时间,有些地方可能连编程者都忘记了,增加注释可以帮助恢复记忆,调试程序时,也容易找出错误。注释也可以分行写。 5.在书写{}时要对齐。虽然不对应也不影响程序运行,但对齐后方便以后检查程序,也是为了美观,特别是后面学到流程控制时,{}一定要对齐。 程序设计方法: 1.从问题的全局出发,写出一个概括性的抽象的描述。 2.定义变量,选取函数,确定算法。算法这个东西不好说,遇到的问题多了,自然就会形成自己一整套的算法。 3.按照解决问题的顺序把语句和函数在main()里面 堆 砌起来。 一个好的C程序员应该做到: 1.在运行程序之前存盘 2.所有在程序中用到的常量都用预处理语句在程序开头定义 3.所有在程序中用到的函数都在程序开头声明 4.头文件的#ifndef 5.变量名和函数名使用有意思的英文单词或汉语拼音 6.尽量少用全局变量或不用全局变量 7.采用层次的书写程序格式,对for,while,if_else,do_while,switch_case等控制语句或他们的多重嵌套,采用缩格 结构 8.所有对应的{}都对齐 9.尽量用for,而不用while做记数循环 10.尽量不用goto语句 11.一个函数不宜处理太多的功能,保持函数的小型化,功能单一化 12.一个函数要保持自己的独立性,如同黑匣子一样,单进单出 13.函数的返回类型不要省略 14.用malloc()分配内存空间时,以后一定要用free()释放 15.打开文件后,记住在退出程序前要关闭 16.出错情况的处理 17.写上必要的注释 这里说的是一些基本的,经常遇到的情况,还有其他很多要注意的地方,在实际编程中都会遇到.


          来自手机贴吧13楼2015-01-23 01:09
          回复
            C语言入门教程 (十) 函数的定义和调用 本节介绍C程序的基本单元--函数。 函数 中包含了 程序 的可执行代码。每个C程序的入口和出口都位于函数main()之中。main()函数可以调用其他函 数,这些函数执行完毕后程序的控制又返回到main()函数中,main()函数不能被别的函数所调用。通常我们把这些被调用的函数称为下层 (lower-level)函数。函数调用发生时,立即执行被调用的函数,而调用者则进入等待状态,直到被调用函数执行完毕。函数可以有参数和返回值。 程序员一般把函数当作“黑箱”处理,并不关心它内部的实现细节。当然程序员也可以自己开发函数库。 说 明一点,函数这一节很重要,可以说一个程序的优劣集中体现在函数上。如果函数使用的恰当,可以让程序看起来有条理,容易看懂。如果函数使用的乱七八糟,或 者是没有使用函数,程序就会显得很乱,不仅让别人无法查看,就连自己也容易晕头转向。可以这样说,如果超过100行的程序中没有使用函数,那么这个程序一 定很罗嗦(有些绝对,但也是事实)。 一、函数的 定义 一个函数包括函数头和语句体两部分。 函数头由下列三不分组成: 函数返回值类型 函数名 参数表 一个完整的函数应该是这样的: 函数返回值类型 函数名(参数表) { 语句体; } 函数返回值类型可以是前面说到的某个 数据类型 、或者是某个数据类型的 指针 、指向 结构 的指针、指向 数组 的指针。指针概念到以后再介绍。 函数名在程序中必须是唯一的,它也遵循标识符命名规则。 参数表可以没有也可以有多个,在函数调用的时候,实际参数将被拷贝到这些变量中。语句体包括局部变量的声明和可执行代码。 我们在前面其实已经接触过函数了,如abs(),sqrt(),我们并不知道它的内部是什么,我们只要会使用它即可。 这一节主要讲解无参数无返回值的函数调用。 二、函数的声明和调用 为了调用一个函数,必须事先声明该函数的返回值类型和参数类型,这和使用变量的道理是一样的(有一种可以例外,就是函数的定义在调用之前,下面再讲述)。 看一个简单的例子: void a(); /*函数声明*/ main() { a(); /*函数调用*/ } void a() /*函数定义*/ { int num; scanf(%d,&num); printf(%d\n,num); } 在main()的前面声明了一个函数,函数类型是void型,函数名为a,无参数。然后在main()函数里面调用这个函数,该函数的作用很简单,就是输入一个整数然后再显示它。在调用函数之前声明了该函数其实它和下面这个程序的功能是一样的: main() { int num; scanf(%d,&num); printf(%d\n,num); } 可以看出,实际上就是把a()函数里面的所有内容直接搬到main()函数里面(注意,这句话不是绝对的。) 我们前面已经说了,当定义在调用之前时,可以不声明函数。所以上面的程序和下面这个也是等价的: void a() { int num; scanf(%d,&num); printf(%d\n,num); } main() { a(); } 因为定义在调用之前,所以可以不声明函数,这是因为编译器在编译的时候,已经发现a是一个函数名,是无返回值类型无参数的函数了。 那么很多人也许就会想,那我们何必还要声明这一步呢?我们只要把所有的函数的定义都放在前面不就可以了吗?这种想法是不可取的,一个好的程序员总是在程序的开头声明所有用到的函数和变量,这是为了以后好检查。 前面说了,在调用之前,必须先声明函数,所以下面的做法也是正确的(但在这里我个人并不提倡)。 main() { void a(); a(); } void a() { int num; scanf(%d,&num); printf(%d\n,num); } 一般来说,比较好的程序书写顺序是,先声明函数,然后写主函数,然后再写那些自定义的函数。 既然main()函数可以调用别的函数,那么我们自己定义的函数能不能再调用其他函数呢?答案是可以的。看下面的例子: void a(); void b(); main() { a(); } void a() { b(); } void b() { int num; scanf(%d,&num); printf(%d\n,num); } main()函数先调用a()函数,而a()函数又调用b()函数。在 C语言 里,对调用函数的层数没有严格的限制,我们可以往下调用100层、1000 层,但是在这里我们并不提倡调用的层数太多(除非是递归),因为层数太多,对以后的检查有一些干扰,函数调过来调过去,容易让自己都晕头转向。 某些人可能就不明白了,看上面的例子,好象使用函数后,程序变的更长了,更不让人理解。当然,我举的这个例子的确没有必要用函数来实现,但是对于某些实际问题,如果不使用函数,会让程序变的很乱,这涉及到参数问题,我们下一节再说。


            来自手机贴吧18楼2015-01-23 01:20
            回复
              C语言入门教程 (十二) 变量的作用域和存储类型 一、作用域和生存期 C程序的标识符作用域有三种:局部、全局、 文件 。标识符的作用域决定了 程序 中的哪些语句可以使用它,换句话说,就是标识符在程序其他部分的可见性。通常,标识符的作用域都是通过它在程序中的位置隐式说明的。 1.局部作用域 前面各个例子中的 变量 都是局部作用域,他们都是声明在 函数 内部,无法被其他函数的代码所访问。函数的形式参数的作用域也是局部的,它们的作用范围仅限于函数内部所用的语句块。 void add(int); main() { int num=5; add(num); printf(%d\n,num); /*输出5*/ } void add(int num) { num++; printf(%d\n,num); /*输出6*/ } 上面例子里的两个num变量都是局部变量,只在本身函数里可见。前面我们说了,在两个函数出现同名的变量不会互相干扰,就是这个道理。所以上面的两个输出,在主函数里仍然是5,在add()函数里输出是6。 2.全局作用域 对于具有全局作用域的变量,我们可以在程序的任何位置访问它们。当一个变量是在所有函数的外部声明,也就是在程序的开头声明,那么这个变量就是全局变量。 void add(int); int num; main() { int n=5; add(n); printf(%d\n,num); /*输出6*/ } void add(num) /*形式参数没有指定类型*/ { num++; printf(%d\n,num); /*输出6*/ } 上面的main()和add()里面,并没有声明num,但是在最后输出的时候却要求输出num,这是由于在程序的开始声明了num是全局变量,也就是在 所有函数里都可以使用这个变量。这时候一个函数里改变了变量的值,其他函数里的值也会出现影响。上面的例子输出都是6,因为在add()函数里改变了 num的值,由于num是全局变量,就好象它们两个函数共用一个变量,所以在main()函数里的num也随之改变了。 3.文件作用域 在很多 C语言 书上,都没有说明文件作用域,或者只是略微的提到,其实文件作用域在较大程序中很有作用(在多文件系统中)。文件作用域是指外部标识符仅在声 明它的同一个转换单元内的函数汇总可见。所谓转换单元是指定义这些变量和函数的源代码文件(包括任何通过#include指令包含的源代码文件)。 static存储 类型 修饰符指定了变量具有文件作用域。 static int num; static void add(int); main() { scanf(%d,&num); add(num) printf(%d\n,num); } void add(num) { num++; } 上面的程序中变量num和函数add()在声明是采用了static存储类型修饰符,这使得它们具有文件作用域,仅爱定义它们的文件内可见。 由于我们提到的大多数程序都只有一个编译文件组成,所以这种写法没有实际意义。但是实际工程上的文件有很多,它们不是由一个人写成的,由很多人共同完成, 这些文件都是各自编译的,这难免使得某些人使用了一样的全局变量名,那么为了以后程序中各自的变量和函数不互相干扰,就可以使用static修饰符,这样 在连接到同一个程序的其他代码文件而言就是不可见的。 二、变量存储类型 前面我们说了,声明变量时用如下类似的形式: int num; float total; 它们都没有存储类型修饰符,我们在声明时也可以通过存储类型修饰符来告诉编译器将要处理什么类型的变量。存储类型有以下四种:自动(auto)、静态(static)、外部(extern)、寄存器(regiser)。 1.自动存储类型 自动存储类型修饰符指定了一个局部变量为自动的,这意味着,每次执行到定义该变量的语句块时,都将会为该变量在内存中产生一个新的拷贝,并对其进行初始化。实际上,如果不特别指明,局部变量的存储类型就默认为自动的,因此,加不加auto都可以。 main() { auto int num=5; printf(%d\n,num); } 在这个例子中,不论变量num的声明是否包含关键字auto,代码的执行效果都是一样的。函数的形式参数存储类型默认也是自动的。 2.静态存储变量 前面已经使用了static关键字,但是对于局部变量,静态存储类型的意义是不一样的,这时,它是和自动存储类型相对而言的。静态局部变量的作用域仍然近 局限于声明它的语句块中,但是在语句块执行期间,变量将始终保持它的值。而且,初始化值只在语句块第一次执行是起作用。在随后的运行过程中,变量将保持语 句块上一次执行时的值。看下面两个对应的程序: /*1.C*/ /*2.C*/ int add(); int add(); main() main() { { int result; int result; result=add() result=add(); printf(%d ,result); printf(%d ,result); result=add(); result=add(); printf(%d ,result); printf(%d ,result); result=add(); result=add(); printf(%d,result); printf(%d,result); } } int add() int add() { { int num=50; static int num=50; num++; num++; return num; return num; } } 上面两个源文件,只有函数add()里的变量声明有所不同,一个是自动存储类型,一个是静态存储类型。 对于1.C文件,输出结果为51 51 51;这很好理解,每次初始值都是50,然后加1上来。 对于2.C文件,输出结果为51 52 53;这是由于变量是静态的,只在第一次初始化了50,以后都是使用上次的结果值。当第一次调用add()时,初始化为50,然后加1,输出为51;当第 二次调用时,就不初始化了,这时num的值为上次的51,然后加1,输出52;当第三次调用时,num为52,加1就是53了。 比较就会发现它们的不同之处了。静态变量在下一节要说的递归函数中经常使用到。 当第一次不指明静态变量的初始值时,默认为0。 下面举一个例子,把我们说到的静态变量理解一下。 求1+2+……+100的值 void add(); int result; main() { int i; result=0; for(i=0;i<100;i++) add(); printf(%d\n,result); } void add() { static int num=0; num++; result+=num; } add()函数被调用了100次,num的值从1一直变到100,这样就可以求出它们的和了。如果写成int num=0;那就是求1+1+……+1这100个1的值了。 实际上类似的这类问题我们可以通过递归函数来解决,什么是递归,我们下一节介绍。 3.外部存储类型 外部存储类型声明了程序将要用到的、但尚未定义的外部变量。通常,外部存储类型都是用于声明在另一个转换单元中定义的变量。下面举一个例子,这个例子包括两个文件。 /*1.C*/ void a(); main() { extern int num; a(); printf(%d\n,num); } /*2.C*/ int num; void a() { num=5; } 这两个程序是分别编译的,然后连接成一个执行文件。具体如何操作,可以查看一些手册,这儿我简单说了一下。把上面两个文件都编译好后,再制作一个.prj文件,里面的内容是: 1.c 2.c 只有这两行,这可在编辑状态下写成,存盘,取名为1.prj。 然后选择project选项,选择projectname,填入1.prj文件名,按F9后,即可生成1.exe文件。 main()函数中变量num是在另一个文件中定义的。因此,当编译器编译1.c时,无法确定该变量的地址。这时,外部存储类型声明告诉编译器,把所有对 num的引用当作暂且无法确定的引用,等到所有便宜好的目标代码连接成一个可执行程序模块时,再来处理对变量num的引用。 外部变量的声明既可以在引用它的函数的内部,也可以在外部。如果变量声明在函数外部,那么同一转换单元内的所有函数都可以使用这个外部变量。反之,如果在函数内部,那么只有这一个函数可以使用该变量。 前面说了文件作用域的问题,如果在声明全局变量时,加上static修饰符,那么该变量只在当前文件内可见,而extern又可以引用其它文件里的变量。 所以在一个大型程序中,每个程序员只是完成其中的一小块,为了让自己的变量不让其他程序员使用,保持一定的独立性,经常在全局变量前加static。我们 可以这样来说明一下: 还是上面的两个文件,现在再增加一个文件3.c,内容为: static int num; void a() { num=6; } 把1.prj文件后面加上3.c 这样,我们生成的1.exe文件,执行时输出是5,而不是6。因为3.c文件的num变量增加了文件作用域,在其他文件中是无法使用它的。 4.寄存器存储类型 被声明为寄存器存储类型的变量,除了程序无法得到其地址外,其余都和自动变量一样。至于什么是变量地址,以后说 指针 时会详细介绍。 main() { register int num; num=100; printf(%d,num); } 使用寄存器存储类型的目的是让程序员指定某个局部变量存放在计算机的某个硬件寄存器里而不是内存中,以提高程序的运行速度。不过,这只是反映了程序员的主观意愿,编译器可以忽略寄存器存储类型修饰符。 寄存器变量的地址是无法取得的,因为绝大多数计算机的硬件寄存器都不占用内存地址。而且,即使编译器忽略寄存器类型修饰符把变量放在可设定地址的内存中,我们也无法取地址的限制仍然存在。 要想有效的利用寄存器存储类型,必须象汇编语言程序员那样了解处理器的内部构造,知道可用于存放变量的寄存器的数量和种类,以及他们是如何工作的。但是, 不同计算机在这些细节上未必是一样的,因此对于一个可移植的程序来说,寄存器存储类型的作用不大。特别是现在很多编译器都能提供很好的优化效果,远比程序 员来选择有效的多。不过,寄存器存储类型还是可以为优化器提供重要的参考。


              来自手机贴吧20楼2015-01-23 01:23
              回复
                C语言入门教程 (十五) 指针概念 学习Turbo C语言 ,如果你不能用 指针 编写有效、正确和灵活的 程序 ,可以认为你没有学好C语言。指针、地址、 数组 及其相互关系是C语言中最有特色的部分。规范地使用指 针,可以使程序达到简单明了,因此,我们不但要学会如何正确地使用指针,而且要学会在各种情况下正确地使用指针变量。 一、指针基本 概念 及其指针变量的定义 我们知道变量在计算机内是占有一块存贮区域的,变量的值就存放在这块区域之中, 在计算机内部, 通过访问或修改这块区域的内容来访问或修改相应的变量。TurboC语言中, 对于变量的访问形式之一,就是先求出变量的地址,然后再通过地址对它进行访问,这就是这里所要论述的指针及其指针变量。 所谓变量的指针, 实际上指变量的地址。变量的地址虽然在形式上好象类似于整数, 但在概念上不同于以前介绍过的整数, 它属于一种新的 数据类型 , 即指针类型。Turbo C中, 一般用指针来指明这样一个表达式&x的类型,而用地址作为它的值,也就是说, 若x为一整型变量, 则表达式&x的类型是指向整数的指针,而它的值是变量x的地址。同样, 若double d;则&d的类型是指向以精度数d的指针,而&d的值是双精度变量d的地址。所以, 指针和地址是用来叙述一个对象的两个方面。虽然&x、&d的值分别是整型变量x和双精度变量d的地址, 但&x、&d的类型是不同的, 一个是指向整型变量x的指针, 而另一个则是指向双精度变量d的指针。在习惯上,很多情况下指针和地址这两个术语混用了。 我们可以用下述方法来定义一个指针类型的变量。 int *ip; 首先说明了它是一指针类型的变量,注意在定义中不要漏写符号*,否则它为一般的整型变量了。另外,在定义中的int 表示该指针变量为指向整型数的指针类型的变量, 有时也可称ip为指向整数的指针。ip是一个变量, 它专门存放整型变量的地址。 指针变量的一般定义为: 类型标识符 *标识符; 其中标识符是指针变量的名字, 标识符前加了*号,表示该变量是指针变量, 而最前面的类型标识符表示该指针变量所指向的变量的类型。一个指针变量只能指向同一种类型的变量, 也就是讲, 我们不能定义一个指针变量, 既能指向一整型变量又能指向双精度变量。 指针变量在定义中允许带初始化项。如: int i, *ip=&i; 注意, 这里是用&i对ip初始化, 而不是对*ip初始化。和一般变量一样,对于外部或静态指针变量在定义中若不带初始化项, 指针变量被初始化为NULL, 它的值为0。Turbo C中规定, 当指针值为零时, 指针不指向任何有效数据, 有时也称指针为空指针。因此, 当调用一个要返回指针的 函数 时(以后会讲到), 常使用返回值为NULL来指示函数调用中某些错误情况的发生。 既然在指针变量中只能存放地址,因此,在使用中不要将一个整数赋给一指针变量。下面的赋值是不合法的: int *ip; ip=100; 假设 int i=200, x; int *ip; 我们定义了两个整型变量i,x,还定义了一个指向整型数的指针变量ip。i,x中可存放整数,而ip中只能存放整型变量的地址。我们可以把i的地址赋给ip: ip=&i; 此时指针变量ip指向整型变量i,假设变量i的地址为1800, 这个赋值可形象理解为下图所示的联系。 ip i ________ _______ | | | | | 1800 | ---- | 200 | |________| |_______| 图1. 给指针变量赋值 以后我们便可以通过指针变量ip间接访问变量i,例如: x=*ip; 运算符*访问以ip为地址的存贮区域,而ip中存放的是变量i的地址,因此,*ip访问的是地址为1800的存贮区域(因为是整数, 实际上是从1800开始的两个字节),它就是i所占用的存贮区域,所以上面的赋值 表达式 等价于x=i; 另外,指针变量和一般变量一样,存放在它们之中的值是可以改变的,也就是说可以改变它们的指向, 假设 int i, j, *p1, *p2; i='a'; j='b'; p1=&i; p2=&j; 则建立如下图所示的联系: p1 i ________ _______ | | | | | | ---- | 'a' | |________| |_______| p2 j ________ _______ | | | | | | ---- | 'b' | |________| |_______| 图2. 赋值运算结果 这时赋值表达式: p2=p1; 就使p2与p1指向同一对象i,此时*p2就等价于i,而不是j,图2.就变成图3.所示: p1 i ________ _______ | | ____ | | | | __ | 'a' | |________| | |_______| | p2 | j ________ | _______ | | | | | | | ___| | 'b' | |________| |_______| 图3. p2=p1时的情形 如果执行如下表达式: *p2=*p1; 则表示把p1指向的内容赋给p2所指的区域, 此时图2.就变成图4.所示 p1 i ________ _______ | | | | | | ---- | 'a' | |________| |_______| p2 j ________ _______ | | | | | | ---- | 'a' | |________| |_______| 图4. *p2=*p1时的情形 通过指针访问它所指向的一个变量是以间接访问的形式进行的,所以比直接访问一个变量要费时间,而且不直观,因为通过指针要访问哪一个变量,取决于指针的值(即指向), 例如*p2=*p1;实际上就是j=i;,前者不仅速度慢而且目的不明。但由于指针是变量,我们可以通过改变它们的指向, 以间接访问不同的变量,这给程序员带来灵活性,也使程序代码编写得更为简洁和有效。 指针变量可出现在表达式中, 设 int x, y *px=&x; 指针变量px指向整数x, 则*px可出现在x能出现的任何地方。例如: y=*px+5; /*表示把x的内容加5并赋给y*/ y=++*px; /*px的内容加上1之后赋给y [++*px相当于++(*px)]*/ y=*px++; /*相当于y=*px; px++*/ 二、地址运算 指针允许的运算方式有: (1). 指针在一定条件下,可进行比较,这里所说的一定条件, 是指两个指针指向同一个对象才有意义,例如两个指针变量p, q指向同一数组, 则<, >, >=,<=, ==等关系 运算符 都能正常进行。若p==q为真, 则表示p, q指向数组的同一元素; 若p (2). 指针和整数可进行加、减运算。设p是指向某一数组元素的指针,开始时指向数组的第0号元素, 设n为一整数, 则p+n就表示指向数组的第n号元素(下标为n的元素)。不论指针变量指向何种数据类型, 指针和整数进行加、减运算时,编译程序总根据所指对象的数据长度对n放大, 在一般微机上, char放大因子为1, int、short放大因子为2, long和float放大因子为4, double放大因子为8。对于下面讲述到的 结构 或 联合 , 也仍然遵守这一原则。 (3). 两个指针变量在一定条件下,可进行减法运算。设p, q指向同一数组,则p-q的绝对值表示p所指对象与q所指对象之间的元素个数。其相减的结果遵守对象类型的字节长度进行缩小的规则。 对于初学者而言,指针和地址以及指针和数组之间的关系都是非常让人头疼的概念。我说了上面那么多,可能很多人还是一头雾水。这就需要多看看一些书了。毕竟自己理解的东西永远比别人讲解的要深刻。 下面举一个例子,来看看指针的应用: main() { char c='A'; int i=123; float f=3.45; char *cp; int *ip; float *fp; cp=&c; ip=&i; fp=&f; printf(%c\n,*cp); printf(%d\n,*ip); printf(%f\n,*fp); } 如果你们还对指针有不理解,可以再接着输出cp,ip,fp的值看看,看它们到底是什么。


                来自手机贴吧23楼2015-01-23 01:29
                回复
                  C语言入门教程 (十九) 联合和枚举 联合 (union): 一、联合说明和联合变量定义 联合也是一种新的 数据类型 , 它是一种特殊形式的变量。 联合说明和联合变量定义与 结构 十分相似。其形式为: union 联合名 { 数据类型 成员名; 数据类型 成员名; ... }联合变量名; 联合表示几个变量公用一个内存位置,在不同的时间保存不同的数据类型和不同长度的变量。 下例表示说明一个联合a_bc: union a_bc { int i; char mm; }; 再用已说明的联合可定义联合变量。 例如用上面说明的联合定义一个名为lgc的联合变量,可写成: union a_bc lgc; 在联合变量lgc中, 整型量i和字符mm公用同一内存位置。 当一个联合被说明时, 编译 程序 自动地产生一个变量,其长度为联合中最大的变量长度。 联合访问其成员的方法与结构相同。同样联合变量也可以定义成 数组 或 指针 ,但定义为指针时,也要用->符号, 此时联合访问成员可表示成: 联合名->成员名 另外, 联合既可以出现在结构内, 它的成员也可以是结构。 例如: struct { int age; char *addr; union { int i; char *ch; }x; }y[10]; 若要访问结构变量y[1]中联合x的成员i, 可以写成: y[1].x.i; 若要访问结构变量y[2]中联合x的字符串指针ch的第一个字符可写成: *y[2].x.ch; 若写成y[2].x.*ch;是错误的。 二、结构和联合的区别 1. 结构和联合都是由多个不同的数据类型成员组成,但在任何同一时刻,联合中只存放了一个被选中的成员, 而结构的所有成员都存在。 2. 对于联合的不同成员赋值,将会对其它成员重写,原来成员的值就不存在了,而对于结构的不同成员赋值互不影响的。 下面举一个例了来加深对联合的理解。 main() { union { /*定义一个联合*/ int i; struct { /*在联合中定义一个结构*/ char first; char second; }half; }number; number.i=0x4241; /*联合成员赋值*/ printf(%c%c\n, number.half.first, mumber.half.second); number.half.first='a'; /*联合中结构成员赋值*/ number.half.second='b'; printf(%x\n, number.i); getch(); } 输出结果为: AB 6261 从上例结果可以看出: 当给i赋值后, 其低八位也就是first和second的值;当给first和second赋字符后,这两个字符的ASCII码也将作为i 的低八位和高八位。 简单的说,就是联合里面的所有变量共用一个内存区域,区域大小是所有变量中最大的那个。改动某一个变量的值,其他的值也会随之改变。 枚举 (enum) 枚举是一个被命名的整型常数的集合,枚举在日常生活中很常见。 例如表示星期的SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,就是一个枚举。 枚举的说明与结构和联合相似, 其形式为: enum 枚举名 { 标识符[=整型常数], 标识符[=整型常数], ... 标识符[=整型常数], }枚举变量; 如果枚举没有初始化,即省掉=整型常数时,则从第一个标识符开始,顺次赋给标识符0,1,2, ...。但当枚举中的某个成员赋值后, 其后的成员按依次加1的规则确定其值。 例如下列枚举说明后,x1, x2, x3, x4的值分别为0, 1, 2, 3。 enum string{x1, x2, x3, x4}x; 当定义改变成: enum string { x1, x2=0, x3=50, x4, }x; 则x1=0, x2=0, x3=50, x4=51 注意: 1. 枚举中每个成员(标识符)结束符是,, 不是;, 最后一个成员可省略,。 2. 初始化时可以赋负数, 以后的标识符仍依次加1。 3. 枚举变量只能取枚举说明结构中的某个标识符常量。 例如: enum string { x1=5, x2, x3, x4, }; enum strig x=x3; 此时, 枚举变量x实际上是7。 下面看一个例子: main() { enum colors {red=1,green,blue}col; int cl; printf(1=red,2=green,3=blue. seclect:); scanf(%d,&cl); col=(enum colors) cl; /*强制转换*/ switch(col) { case red: printf(red\n); break; case green: printf(green\n); break; case blue: printf(blue\n); break; defalut: break; } } * **类型说明** * 类型说明的格式为: typedef 类型 定义名; 类型说明只定义了一个数据类型的新名字而不是定义一种新的数据类型这里类型是Turbo C许可的任何一种数据类型定义名表示这个类型的新名字。 例如: 用下面语句定义整型数的新名字: typedef int SIGNED_INT; 使用说明后, SIGNED_INT就成为int的同义词了,此时可以用SIGNED_INT定义整型变量。 例如: SIGNED_INT i, j;(与int i, j等效)。 但 long SIGNED_INT i, j; 是非法的。 typedef同样可用来说明结构、联合以及枚举。 说明一个结构的格式为: typedef struct { 数据类型 成员名; 数据类型 成员名; ... } 结构名; 此时可直接用结构名定义结构变量了。例如: typedef struct { char name[8]; int class; char subclass[6]; float math, phys, chem, engl, biol; }student; student Liuqi; 则Liuqi被定义为结构数组和结构指针。


                  来自手机贴吧27楼2015-01-23 01:34
                  回复
                    2.链数据的插入和删除 对于一个已排序好的链表(假设是生序),现在想插入一个数据进去,可能有三种情况: (1).比首项数据还小,即插入的数据作为首项出现: 这种情况我们的处理方法是:把该数据作为第一项,指针指向原先的首项即可。设原先首项为top,待插入的数据为in,则: in->next=top; 即可让该数据作为链表的头。 (2).比最后一项大,即插入的数据作为最后一项出现: 这也很好办,设原先最后一项为old,则: old->next=in; in->next=NULL; (3).作为中间某一项出现:前面是old,后面是top,则: old->next=in; in->next=top; 如果想删除一个数据,也可能是出现在开头,中间和结尾。 例如想删除in这个数据,它原先的前面是old,后面是top,即原先的链表是这样: old->next=in; in->next=top; 现在删除in,只需把old指向top即可: old->next=top->next; /*删除节点函数*/ void delete(struct address *info,structaddress *old) { if(info) { if(info==start) start=info->next; /*删除的是第一个节点*/ else { old->next=info->next; /*被删除节点前的指针指向下一个节点*/ last=old; /*若节点是链表尾,则该节点前的节点指针指向NULL*/ } free(info); /*释放删除节点占用空间*/ } } /*查找链表中是否有该数据*/ struct address *search(struct address*top,char *n) { while(top) { if(!strcmp(n,top->name)) return top; /*找到要删除的节点指针*/ top=top->next; /*继续找*/ } return NULL; /*没有找到*/ } /*链表的输出*/ void display(struct address *top) { while(top) { printf(top->name); top=top->next; } } 链表问题比较复杂,但又是很重要的概念。上面说的输入,查找,删除,插入等功能一定要理解,可以参考别的一些资料看看。 上面说的单链表,但是单链表有一个缺点,就是无法反向操作,当某一个链因破坏而断裂,则整个链就被破坏而无法恢复。双链表可以弥补这个缺点,所谓双链表是 指每个节点有两个指针项,一个指针指向其前面的节点,而另一个指针指向后面的节点。关于双链表的使用相对要复杂一些,这里就不介绍了,可以找其他一些资料 看看。


                    来自手机贴吧29楼2015-01-23 01:42
                    回复
                      C语言入门教程 (二十一) 位操作 在第一节概述里就说了, C语言 是一种中级语言,能对计算机硬件直接操作,这就涉及到位的概念。 一、位的概念 我们知道,在计算机中,一字节占8位(现在的某些电脑也有占16位的),这样表示的数的范围为0-255,也即00000000-11111111。位就是里面的0和1。 char c=100; 实际上c应该是01100100,正好是64H。其中高位在前,低位在后。 | | 第7位 第0位 二、位逻辑 运算符 符号 描述 & 位逻辑与 | 位逻辑或 ^ 位逻辑异或 ~ 取补 表中除去最后一个运算符是单目运算符,其他都是双目运算符。这些运算符只能用于整型 表达式 。位逻辑运算符通常用于对整型变量进行位的设置、清零、取反、以 及对某些选定的位进行检测。在 程序 中一般被程序员用来作为开关标志。较低层次的硬件设备驱动程序,经常需要对输入输出设备进行位操作。 & 运算的规则是当两个位都为1时,结果为1,否则为0; | 运算的规则是当两个位都为0时,结果为0,否则为1; ^ 运算的规则是当两个位相同时,结果为0,否则为1; ~ 运算的规则是当为1时结果为0,当为0时,结果为1。 设置位:设置某位为1,而其他位保持不变,可以使用位逻辑或运算。 char c; c=c|0x40; 这样不论c原先是多少,和01000000或以后,总能使第6位为1,而其他位不变。 清除位:设置某位为0,而其他位保持不变。可以使用位逻辑与运算。 c=c&0xBF; 这样c和10111111与以后,总能使第6位为0,其他位保持不变。 那如果想让某位为1,其他位都为0怎么办呢? 三、位移运算符 符号 描述 << 左移 >> 右移 位移运算符作用于其左侧的变量,其右侧的表达式的值就是移动的位数,运算结果就是移动后的变量结果。 b=a<<2; 就是a的值左移两位并赋值为b。a本身的值并没有改变。 向左移位就是在低位沙锅补0,向右移位就是在高位上补0。右移时可以保持结果的符号位,也就是右移时,如果最高位为1,是符号位,则补1而不是补0。 程序员常常对右移运算符来实现整数除法运算,对左移运算符来实现整数乘法运算。其中用来实现乘法和除法的因子必须是2的幂次。 举例:输入一个整数,判断这个数中有几个二进制位1?例如输入67,输出结果应该为3。因为67的相应二进制数为00000000 01000011(0043H),有3个1出现。 分析:要判断是不是1,只需要判断该位与1与以后是不是1就可以知道。一个整数,判断16次即可。 main() { int num,k; int count=0; /* 记录1的个数 */ scanf(%d,&num); for(k=0;k<16;k++) { if(num&1==1) count++; /* 判断最低位是不是1 */ num>>=1; /* num右移1位 */ } printf(%d\n,count); } 这样每次都判断最低位是不是1,判断完以后,让前面的右移一位即可。 对位的操作,一般程序中用的不多,但是在对计算机硬件操作时,肯定会涉及到。例如,我们以后要讲到的对串口和声卡操作就要用到一些。


                      来自手机贴吧30楼2015-01-23 01:42
                      回复
                        火钳


                        IP属地:广东来自Android客户端32楼2015-01-23 05:31
                        回复
                          贴吧不支持编辑帖子,加之我也是手机党,更没有办法帮助排版长文了。见谅。不过,想看的人应该看得清楚,当提高阅读识别能力吧。。


                          来自手机贴吧33楼2015-01-23 06:45
                          回复
                            大家觉得此教程如何? @紫星之光者 @0336l4625035 @沛秦 @蝉曦 @东南都_达人1


                            来自手机贴吧34楼2015-01-23 07:17
                            收起回复
                              标题是“关于编程语言的总贴”,意思是本帖要收录楼主见过的多种语言的教程全文?


                              来自手机贴吧35楼2015-01-23 07:23
                              回复