C 语言基础

来源:互联网 发布:编制软件 编辑:程序博客网 时间:2024/05/16 08:17

前言

C语言写的程序,无处不在,大到计算机操作系统,windows,Unix,linux,各种嵌入式设备等等,小到计算器;C语言作为在各种设备上大量运行的程序的编程语言,在设计之初就大放异彩,并被很多大学作为计算机科学与技术专业甚至是一些非计算机专业,做为计算机编程基础课程;C语言由于其设计的灵活、靠近硬件,能 解决很多基础问题,被程序员们所喜爱。在Android 开发中,ndk开发作为一种让程序员更好控制硬件和计算资源,在google在Android开发的早期阶段都已经支持,市面上很多Android 应用,处于某些考虑,均大量有使用这种开发模式。C语言作为ndk开发的语言,学习好C,自然是必要的了;

知识预备

1.ASCII码

这里写图片描述
2.各种进制
.二进制,八进制,十进制,十六进制及转化
计算机系统使用的基本上是二进制系统。数字以 ,二进制表示,
比如 9;其二进制,就是 111 ;
计算方法:
9/2=4 余数:1
4/2=2 余数:0
2/2=1 余数 :0
1/2 =0 余数:1;
直到商为0,将余数逆向排列,即得到 其二进制;
得到 9的二进制 1001;
将小数转化成二进制

十进制小数转换成二进制小数采用"乘2取整,顺序排列"法。具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,此时01为二进制的最后一位。或者达到所要求的精度为止。比如:0.5 其二进制,就是:(0.1)B0.5*2=1,取出整数1;比如:0.25 其二进制 ,就是:(0.01)B0.25 *2=0.5;取出整数  00.5*2=1; 取出整数 1

3.源码、反码、补码的概念及相关

整数的补码是其二进制,比如:+9,的补码0000 1001;(前面的 0000,是符号位)0.3.2负数的补码将其对应正数二进制表示所有位取反(包括符号位,0110)后加1;比如:-9,源码:0000 0111,->反码:1111 1000,->补码:1111 1001;比如:-5,源码:0000 0101,->反码:1111  1010,->补码:11111 1011;0.3.3已知一个补码,求其源码;已知一个数的补码,求原码的操作其实就是对该补码再求补码:如果补码的符号位为“0”,表示是一个正数,其原码就是补码。如果补码的符号位为“1”,表示是一个负数,那么求给定的这个补码的补码就是要求的原码。比如,已知补码:1111 1001。求其源码:知其符号位为"1",为负数 ,求其补码:0000 0110  再加10000 0111,知道为数字 9,带上符号为:-9;在比如,已知补码:11111 1011。求其源码;知道符号位为“1”,负数, 0000 0100 在加10000  0101 知道为数字 5,带上符号 :-5

基本语法

数据类型

基本类型1.正型  short  ,int long2.浮点型 float  double3.字符型 char4.void5.指针型 **6.结构体和联合1.1.正型根绝修饰符的不同,可是分为有符号和无符号的一下类型(短整型和长整形);signed  short int  ;//可以简单的写成:short 或  int ;取值范围为:-32768~2767;十六位两个字节signed  long  int ;//可以简单的 :long  ;取值范围为:-2147483648~2147483647;三十二位四个字节unsigned  short int ;// unsigned int;  取值范围0~65535 十六位两个字节unsigned  long  int ;// unsigned  long  ; 取值范围:0~4294967295  十六位两个字节2.1浮点型,根据精度分为:单精度浮点型和双精度浮点型;float  324个字节,数值的取值范围是:3.4x10-38E~3.4x10+38E;double  648个字节,数值的取值范围是:1.7x10-308E~1.7x10+308E;单精度浮点数的精度为:6位;双精度浮点数的精度为:7位计算的时候,单精度有精度损失,一般采用,双精度,但是双精度,计算的时候,因为位数比较长,比较消耗计算资源;3.1字符型8位,一个字节,根据有无符号,分为:  signed  char  ,unsigned  char;取值范围分别为:-128~1270~255;4.1 void5.1指针类型  根据实际类型,可分为:      int *;      float  *;      char  *;      struct *;结构体指针;      union * 联合体指针;

变量的类型

根据变量的定义位置分为:
全局变量:定义在main函数外,如果没有初始化,数字类型变量默认值为:0,字符型和指针型默认为:NULL;
局部变量:定义在函数内部,如何没有初始化,默认为随机赋值;
参数变变量:定义在函数参数列表;
三,函数的定义
在c语言中定义一个函数,一般是写在main函数之前;在函数使用之前,需要在全局声明

关键字与标识符定义

关键字:auto double int struct break elselong switch case enum register typedefchar extern return union const floatshort unsigned continue for signed voiddefault goto sizeof volatile do ifwhile static表示含义:auto :声明自动变量break:跳出当前循环case:开关语句分支char :声明字符型变量或函数返回值类型const :声明只读变量continue:结束当前循环,开始下一轮循环default:开关语句中的“其它”分支do :循环语句的循环体double :声明双精度浮点型变量或函数返回值类型else :条件语句否定分支(与 if 连用)enum :声明枚举类型extern:声明变量或函数是在其它文件或本文件的其他位置定义float:声明浮点型变量或函数返回值类型for:一种循环语句goto:无条件跳转语句if:条件语句int: 声明整型变量或函数long :声明长整型变量或函数返回值类型register:声明寄存器变量return :子程序返回语句(可以带参数,也可不带参数)short :声明短整型变量或函数signed:声明有符号类型变量或函数sizeof:计算数据类型或变量长度(即所占字节数)static :声明静态变量struct:声明结构体类型switch :用于开关语句typedef:用以给数据类型取别名unsigned:声明无符号类型变量或函数union:声明共用体类型void :声明函数无返回值或无参数,声明无类型指针volatile:说明变量在程序执行中可被隐含地改变while :循环语句的循环条件

标识符定义规则:

和Java一样,C 的标识符定义也是这样的规则:
1标识符的开头必须是以字母、下划线,不能使用特殊字符和数字开头;
2标识符有大小写字母和数字组成区分大小写
3标识符只有钱32位有效
4标识符不能使用关键字;

基本语句

for 循环whlie 循环do  whlie 循环gotobread;continue;case;default;switch;

注意:和java 不一样的,循环变量的初始化放在循环体外面;

指针

指针的概念:所谓变量的指针,实际上指变量的地址。指针变量:向这要定义一个指向变量地址的一个变量,叫做指针变量;1指针变量的地址;比如,我们定义一个变量 :int  a ,b,*a1=&a;a=10;b=*p;那么我们打印一下a1=?  b?其意义是这样的:定义变量,a,和指针变量a1,将a的地址赋值给指针变量a1;打印出来的结果是一个地址,可以知道,指针变量是保存的一个地址,而不是数值,所以:a1=20;这样的赋值给 a1,是会报错的;在看打印出来  b=?打印结果:b=20;我们可以得出结论:1.1可以将指针变量复制给普通变量,表示将该指针指向的数字赋值给该普通变量;1.2.将普通变量复制给指针变量 ,会标错,进一步明确,指针变量,这能赋值给指针变量;2地址运算:2.1指针的比较满足两个指针变量可比较的条件是,他们指向同一个变量;比如:int  a,*a1,*a2;a1=&a;a2=&a; int res=(a1==a2?1;0);测试结果:1;2.2指针的算符运算前面我们已经测试,知道,指针指向一个变量,可用指针来和普通变量混合参与运算。下面我们写一个函数来测试结论;

数组

1.C 语言中数组的定义: int  arr[10]; char  arr1[15]; long arr3[15]; float arr4[20]; double arr5[15]; int * arr6[10];注意:  int (*p)[5];这个是数组指针,不是指针数组;2数组的使用;2.1一维数组的初始化;    这样:int  arr[5]={1,2,,3,4,5};or  like this:int  arr[]={1,2,3};2.2多为数组:多维数组的定义使用和一维数组没有什么区别;2.3数组与指针:可以说,任何一个数组都可是都可以用指针来表示,但是他们绝对不是一个概念;设想一下:一般我们定义了一个数组变量,那么,计算机就在,内存给我们分配一块连续的区域;指针也代表了一段内存位置中的一个节点,so,如果我们将这个节点指向数组的头节点,然后依次移动指针,就可以获得数组中的元素;这样说还是有些抽象,下面我们来下个代码测试;2.4一些概念的区别:指针数组和数组指针?区别老大了;

结构体和联合体

8.1结构体
结构体的定义:使用关键字 struct做形似如下的代码块,我们称之为结构体,类似于java中的类;

struct 结构名{类型 变量名;类型 变量名;...} 结构变量;比如:struct Person{char[] *name;int sex;double grade;}struct Person  yang,li,zhang,wang;

这里有两种声明方式:
8.1.1声明结构体的同时,指定变量名称;
形如:

struct Person{char[] *name;int sex;double grade;} li;

8.1.2单单只声明结构体,然后在使用时再 分别指定变量名称;
形如:

struct Person{char name;int sex;double grade;}struct  Person  yang,li,zhang;

8.2结构体变量的使用
下面我们来写代码测试结构体的使用;
8.2.1结构体内部变量的访问
例如:

yang.name='y';yang.sex=1;yang.grade=100;

8.3结构数组和结构指针
结构体数组和普通数组一样,只时类型是结构体类型的了;
我们来重点说说,结构体指针
8.3.1结构体指针
定义:结构指针是指向结构的指针。
形如:

struct Person{char name[10];int  gender;int age}* person

结构体指针的赋值:
原本写法:

strcp((*person).name,"yangliang");(*person).age=18;

简写:

strcp(person->name,"yangliang");//注意这个数组赋值函数;person->age=18;

8.3.2位结构

typeDef  struct{int a;....}  oBject;

8.4联合体与枚举

8.4.1和结构体的区别是
1:联合体所有变量保存在一段内存地址中.
2:这段内存内存地址的 长度 是由联合中占用内存最大的变量类型决定的;
3.修改联合体中的变量的某一个,则其他的变量值会被擦除;
8.4.2枚举

enum string{x1,x2=0,x3=50,x4,}x;则x1=0, x2=0, x3=50, x4=51

注意:
1.枚举中每个成员(标识符)结束符是”,”,不是”;”,最后一个成员可省略”,”。
2.初始化时可以赋负数,以后的标识符仍依次加1。
3.枚举变量只能取枚举说明结构中的某个标识符常量。
这样就可以直接定义结构数组和指针数组oBject;

预处理命令

由ANSI的标准规定,预处理指令主要包括:

#define#error#if#else#elif#endif#ifdef#ifndef#undef#line#pragma

define 是宏定义指令;
它的定义范式是这样的: #define 要替换的数值 替换成的数值
注意:宏定义的定义语句,结构是没有“;”

函数

输出和输入语句printf("请输入一个整数");输出数据的格式化printf("name=%s,age=%d,grade=%f,levele=%c");输出:字符串,整数,小数,字符;scantf("a=%d",&a);

基础代码测试代码

#include <stdio.h>#include <stdlib.h>#include <string.h>int com_num;long com_num2;float  com_fnum;double com_fnum2;char   com_c;char   *c0;int  testFunction(int,int );void testBaseFunction(int );void  testGotoKeyWords(void);void  testPoint(void );void  testPointBj(void);void   testPointArithmeticOperation(void);void    testArraCommonUse(void);void    testArrayInnite(void);void    testArrayAndPointer(void);void   testPointMove(void);void   testStructDef(void);void   testStructVarUse(void);void  testStructUse(void);void    testUnionDef(void); void   testUnionPointer(void); void    testEnum(void);#define  MyMax(a,b) (a>b? a:b) //测试宏定义 void  testDefine(){     int  result=MyMax(7,1);     printf("TEST  DEFINE USE");     printf("result=%d",result); }enum   week{    Monday=0,    Teusday=1,    Wensday=2,    Thursday=3,    Friday=4,    };    int  testAdd(int a,int  b){//  a,b分别是下面函数内部,的a和b;是外部的变量,传递到函数内部的通道;如果参数列表不写,就意思是:没有参数要传递到函数内部;   return  a+b;    }//测试枚举void  testEnum(){   enum   week p;   //枚举在调用的时候,直接使用枚举的变量名;   printf("Monday=%d,Tuesday=%d,Wensday=%d,Thursday=%d,Friday=%d",Monday,Teusday,Wensday,Thursday,Friday);}//测试联合体的声明,使用void  testUnionDef(){    union   String{    char  c;    int  num;    } str;    str.c='a';    str.num=0;    printf("c=%c,num=%d",str.c,str.num);    printf("\n*********************change start*************************\n");     str.c='b';    str.num=10;  printf("c=%c,num=%d",str.c,str.num);}//结构体指针的使用void  testStructUse(){    struct Person{    char name[10];    int  gender;    int  age;    } *per;  per=(struct Person*)malloc(sizeof (struct Person));//分配类存空间,似乎只有结构体指针才有     strcpy(per->name,"yangliang");     per->gender=1;     per->age=28;     printf("name=%s,gender=%d,age=%d",per->name,per->gender,per->age);//注意指针使用不当,造成数据出错}//测试 结构体变量的使用;void  testStructVarUse(){}//结构体的void   testStructDef(){ struct  Person{ char name; int  sex; double grade; } ; struct  Person yang,li,zhang,wang;  yang.name='y';  yang.sex=1;  yang.grade=100;   li.name='l';   li.sex=0;   li.grade=90;   zhang.name='z';   zhang.sex=1;   zhang.grade=90;   wang.name='w';   wang.sex=0;   wang.grade=86;   struct Person persons[4];   int i;   for(i=0;i<4;i++){    switch(i){case 0:    persons[0]=yang;    break;case  1:    persons[1]=li;    break;case 2:    persons[2]=zhang;    break;case 3:    persons[3]=wang;    break;    }   }   struct  Person  per,*p=&persons[0];   for(p;p<&persons[3];p++){    per=*p;    printf("name=%c,sex=%d,grade=%f",per.name,per.sex,per.grade);    printf("\n");   }}//测试指针移动void  testPointMove(){    int  arr[5]= {1,2,3,4,5};    char  *p=arr;    //注意这里的p++;是移动一个指针存储单元,这个指针的类型有关系,如果是int移动两个字节,char 一个字节,等等;    for(p; p<&arr[4]; p++)    {        int  num=*p;        printf("测试数组和指针");        printf("num=%d",num) ;        printf("\n");    }}//测试数组 和指针;void   testArrayAndPointer(){    int  arr[5]= {1,2,3,4,5};    int  *p=arr;    //注意这里的p++;是移动一个指针存储单元,这个指针的类型有关系,如果是int移动两个字节,char 一个字节,等等;    for(p; p<&arr[4]; p++)    {        int  num=*p;        printf("测试数组和指针");        printf("num=%d",num) ;        printf("\n");    }}// 测试数组的初始化void  testArrayInnite(){    int  arr[5]= {1,2,3,4,5};    int  arr2[]= {1,2,3};}//测试数组的一般使用void   testArraCommonUse(){    int  arr[10];    int  flag=1;    int  i=0;    while(flag)    {        if(i==10) //注意运算符和 赋值符号        {            flag=0;        }        arr[i]=i;        printf("数组赋值:");        printf("arr[%d]=%d",i,arr[i]);        printf("\n");        i++;    }    printf("\narray arr:");    int  j;    for(j=0; j<10; j++)    {        printf("arr[%d]=%d",j,arr[j]);        printf(" ");    }}//测试指针参数算术运算void  testPointArithmeticOperation(){    int num1,num2, r,r2,r3,r4,r5,*a=&num1,*b=&num2;    num1=10;    num2=20;    r=*a+*b;    r2=*a*(*b);    r3=*a-*b;    r4=*b/(*a);    r5=r4*(*a);    printf("\n");    printf("r=%d,r2=%d,r3=%d,r4=%d,r5=%d",r,r2,r3,r4,r5);}//测试指针运算void  testPointBj(){    int  a,r,*a1,*a2;    a=10;    a1=&a;    a2=&a;    if(a1==a2)    {        r=1;    }    else    {        r=3;    }    printf("r=%d",r);//打印结果,r=1;}void  testPoint(){    int  a,b,*a1=&a;    a=20;    b=*a1;    printf("\n");    printf(a1);//打印出来是一个地址,不是20;由此可知道,指针变量保存的是一个地址;    printf("\n");    printf("b=%d",b);}//测试 goto关键字void  testGotoKeyWords(){    int i=0;loop:    for(i; i<10; i++)    {        printf("\n");        printf("TEST FUNCTION AND  GOTO");        if(i==10)        {            printf("End FUNCTION  AND  GOTO");        }    }    printf("Start loop:");    goto  loop;}//  定义一个函数int  testFunction(int  a,int  b){    return  a+b;}// 测试基本语句;void testBaseFunction(int  a){    //测试for循环,注意C语言中,for 循环的变量是在loop外面定义的;    int  i=0;    for(i=0; i<a; i++)    {        printf("***********test function  execute  for circlerunning******************\n");        printf("i=%d",i);        printf("\n");        if(i>10)        {            printf(" test function  execute  continue\n");            continue;        }        if(i==a)        {            printf("***********test function  execute  for circlerunning******************");        }    }    //测试wlie循环    int  count=0;    while(a>0)    {        count++;        printf("\n***********test function  execute  wile circlerunning******************");        if(count>50)        {            printf("\n***********test function  execute  wile circlerunning******************");            break;        }    }}//执行入口int main(){    printf("Hello world!\n");    //正型    //  unsigned  short  int num1;    //  unsigned  long   int   num2;//signed  short  int  num3;    //   signed  long  int    num4;    //  printf("\n------- i 'm  separating  line-----------\n");    //浮点型    // float   a=2.6;//单精度有精度损失,所以一般使用,double//double  a1=2.6;    //  int  size_a=sizeof(a);    //   int  size_a1=sizeof(a1);    //  printf("size_a=%d,size_a1%d",size_a,size_a1);    //  printf("\n------- i 'm  separating  line-----------\n");    // 字符型  //  char  c='c';    //   char  *c1="555";    //  com_num=1;    //  com_num2=2;    //com_fnum=1.0;    //  com_fnum2=1.0;    // com_c='p';   // printf("c=%c",c);  //  printf("com_num=%d,com_num1=%d,com_fnum=%f,com_fnum2=%f,com_c=%c",com_num,com_num2,com_fnum,com_fnum2,com_c);    // printf(c1);  //  printf("\n");  //  printf(c0);  //  printf("\n");   // int  num_test=testFunction(5,8);    //  testBaseFunction(10);    //testGotoKeyWords();    //  testPoint();    //testPointBj();// testPointArithmeticOperation();    //testArraCommonUse();// testArrayInnite();// testArrayAndPointer();  //  testPointMove();  //testStructVarUse();  //testStructDef();  //testStructUse();//testUnionDef();//testEnum();   testDefine();    return 0;}

下一篇博文:C标准函数库

0 0
原创粉丝点击