zoukankan      html  css  js  c++  java
  • C的基本语法:函数,数组,指针

    1 什么是C语言

      面向过程编程的高级语言;既可以像高级语言那样使用逻辑算法来编程,也具备低级语言面向计算机硬件编程;

      (常说的面向对象编程的对象是指类对象,将具有特定逻辑功能的多个函数包装成类,可以专注于模块化编程;)

      (而C语言中的常说的对象指的是数据所占用的物理内存;对象指的是存储一个或多个值的一块内存;)

      (程序的环境可以分为翻译环境和执行环境;所有的注释在编译器中将以空格代替;)

      预处理器:在开始编译之前,由编译器调用的一段独立的程序,处理注释和预处理指令;

      keil-MDK是集成开发环境,集成了C编译器、宏汇编、链接器、库管理和仿真调试器等在内的完整开发方案;

      1.1 全局变量与局部变量

        全局变量:定义在函数外的变量,存储在静态内存中,从程序运行开始存在,直到程序销毁;默认初始值为0;

        局部变量:定义在函数内的变量,存储在堆栈中,默认初始值为该堆栈之前的值,使用时尽量软件初始化;

             定义外设结构体时,定义在函数内部但是又没有初始化就直接使用的话,受随机值影响可能会跑不起来;

    2 数据类型

      

      ARM架构:  1bytes: char;

            2bytes:short int;

            4bytes:int, unsigned int, long int, float;

            8bytes: long long int, double;

      2.1 数据举例

        2.1.1 C语言中字符串的结尾默认为null ;"Hello"=="H" 、"e"、"l"、"l"、"o"、"NULL" 共6个字节 ;

        2.1.2 ARM架构下的long int是4bytes的,不是8bytes;

      2.2 常见换算

        1 M-Bytes = 2^10 K-Bytes = 2^20 Bytes;

        1 MHz = 1000 KHz = 1000 000 Hz;

        1 byte可以表示8bit二进制数据,但是只需要4bit数据线;

        秒,毫,微,纳,皮的时间单位进制为1000;

      2.3 && 和&

        &&表示逻辑与,是布尔运算,非真即假;( reg1_status&&0x01 ) :如果reg1_status为真,且0x01为真,则运算结果为真;

        &表示按位与,是位运算,(reg1_status&0x01):reg1_status与0x01按位与运算,运算结果非假即真;

    3 函数

      说明:实现具体功能的代码块,使程序结构清晰;先声明,后调用。

      使用:函数和变量类似,也具有类型;所以函数在使用之前需要声明。将函数原型写在main()调用前则可以省略声明。

        在一个函数体内不能嵌套定义新的函数原型,但是可以调用其他的函数;

        函数名就是函数的首地址,要是赋值给指针,直接用函数名作为地址赋值,不用&;

      3.1 函数声明 

    void func1_name(int param1,int param2);
    int func2_name(void);
    /*声明*/    
    /*函数类型 函数名 (参数类型 参数名,...)*/
    
    /*使用事项*/
    /*函数类型与函数的返回值类型相同,void表示函数无返回值*/
    /*参数类型的参数名可以省略*/ 

      3.2  函数原型

    /*将函数原型写在main函数前,这在main函数调用的时候可以省略函数声明;
    **平常使用的话都是把函数原型写在.c文件里,然后把函数声明写在.h文件里,通过包含.h文件来调用的;*/
    int add(int a,int b)
    {
       return a+b;             
    }

      3.3 函数调用

    function1(x);
    function1(int num){...}
    
    function2(&y);
    /*函数调用,在一些函数中调用另外一些函数;*/
    
    function2(int *positon){...}
    /*被调用的函数称为被调函数,上面这个是被调函数的原型*/ 

        3.3.1 形参:被调函数声明或定义中出现的变量;作用域只在该函数中,函数结束后随函数销毁。

        3.3.2 实参:主调函数即将传递的具体值;应该作用域只在主调函数中,随主调函数的结束而销毁,中断不算。

              参数在主调函数和被调函数中应该分别定义名字(变量)

        3.3.3 当数组名作为实参传递时表示该数组的首地址,数组名就是数组第一个元素的地址。

    int array[10]={0};
    if( array==&array[0]) 
    printf(" if等式是成立的。");

      3.4 main()函数的固定参数

    void main( int argc, char * argv[ ] ) 
    
    /*argc 参数记录命令行的命令和参数个数*/
    /*argv 参数记录命令行的命令和参数个数的内容*/
    /*具体的又忘记了,以后再补充吧*/ 

     4 数组

      4.1 一维数组

        4.1.1 数组声明

    int array[10];       /*整型数组array[],有10个int型对象*/
    float candy [10];   /*浮点型数组candy[], 有10个float型对象*/
    char zifu [10];      /*字符型数组 zifu[], 有10个char型对象*/
    int *add[10];        /*给指针型数组留个位置*/

        4.1.2 数组初始化

    int day[7]={1,2,3,4,5,6,7};
    /*声明数组的同时对所有变量初始化*/
    
    int day[7]={1,2,3};
    /*声明数组的同时对部分变量初始化,未初始化部分默认值为0*/
    
    int day[7]={1, [3]=4,[5]=6,[6]=7};
    /*声明数组的同时对部分变量初始化,未初始化部分默认值为0*/

        4.1.3 数组使用

    int array[10] ={1,2,3,4,5,6,7};
    for(i=0;i<10;i++)
        printf( " array[ %d ] " ,array[i] );        
    /*数组的下标从0开始,只能逐个引用,编译器不会检查数组下标是否大于数组声明的个数*/

          ps:数组的调用为传址调用,修改后的参数会同步给原函数;如下array[10]就会,value不会;

    int read( int array[10] , int value ) ; 

      4.2 二维数组:表示数组的数组 

        4.2.1 数组声明

    float Salary [5][10];
    /*二维数组salary中有5个一维数组,其中每个一维数组有10个float型对象*/

        4.2.2 数组初始化

    float salary [2][3]={{7000,8000.8,9000},{10000,9500.50,12000}};
    /*一 一 赋值初始化*/
    
    float salary [2][3]={{7000,8000},{9000}};
    /*部分初始化,未赋值部分初始化为0*/
    
    float salary [2][3]={7000,8000,9000};
    /*按顺序初始化salary[0][0], salary[0][1] salary[0][2],  
       然后初始化salary[1][0] salary[1][1] salary[1][2],未赋值部分初始化为0*/

        4.2.3 数组使用

    float salary [2][3]={7000,7500,8000,8500,9000,9500};
    int i,j;
    float salary_sum=0;
    for(i=0;i<2;i++)
        for(j=0;j<3;j++)
        {    salary_sum+=salary[i][j];    
        }
    /*二维数组的存储顺序是依次存放,先排完第一个一维数组的地址,然后依次排第二个一维数组的地址*/

    5 指针

      定义:值为内存地址的变量类型,未经赋值的指针不能使用;不允许将数值赋值给指针变量;      

      声明

    int a = 5 ;
    int *p ;    //声明指针,但是未赋值,  int *p; 的意思是p是一个指针,p的值是地址,*p是int类型
    p = &a ;
    /*int *a ,b , c ; 不等于 int *a ,*b , *c ;*/
    int a;
    int *p = &a; //声明指针的同时赋值

      5.1 使用事项  

        5.1.1 间接运算符* : 用*指向符来指向地址取出或修改地址内的值;

           ps:指针是值为地址的变量,用指针与数据交互的时候要与*间接运算符使用;

    /******交换指针m与n 地址内的值******/
    void swap(int *m,int *n)
    {
        int temp;
        temp = *n;
         *n = *m;
        *m = temp;   
    }             
    /******ps:'*’称之为间接运算符的原因 ******/
    int value1,value2;
    int *pointer;    
    
    /******下面语句等价于 value1=value2 ******/
    pointer = &value2;    
    value1 = *pointer; 

        5.1.2 在函数原型或函数定义头文件中,由于数组名和指针均表示地址,所以可以互相替代;

    int sum(int ar[],int n);
    /*表示形参ar是一个指针,指向int类型的数组*/
    
    int sum(int *ar, int n);
    /*表示形参ar是一个指针,指向int类型对象*/

        5.1.3 指针变量也像其他变量一样有自己的地址,地址直至销毁前不变;

    int num;
    int *ptr =&num;
    printf("%p ,%p" , ptr ,&ptr);
    /*第一个%p是指针变量自己的地址,第二个%p是num变量的地址*/ 

         5.1.4 指针的自加加 加的是指针所指向的数据类型的长度;

    int * ptr;
    int total=0;
    total+=*  ptr++;
    total+=* (ptr++);
    /*一元运算符*与自加加优先级相同,所以从右像左,先计算++ */
    
    int array[10];
    &array[2]==array+2;   /*等式成立,地址array的值加上8个字节,int类型=4字节*/
    array[3]==*(array+3); /*等式成立,此处是数值*/
    /*   array+2可以遍历数组地址*/
    /*   *(array+3)可以遍历数组内的数值  */   

      5.2 指针与二维数组

        5.2.1 声明二维数组指针

    int (* ptr)[3] ;
    /* 声明指针为二维数组指针,每个一维数组有3个对象;(*ptr)表示指针名字为ptr; */
    
    int * ptr[3]; 
    /*[]的优先级高于*,所以先结合为ptr[],数组个数为3,表示定义一个数组,数组对象是3个指向int型的指针*/
    /*声明指针的数组*/
    int array[2][3] ;
    int (*ptr)[3];
    ptr=array;
    /*-- array+1 表示二维数组的首地址加上一个一维数组的大小,1个一维数组共3个int型对象12字节 --*/
    /*-- array[0]+1 表示将二维数组的对象顺序排列为一维数组后,加上一个int型对象的大小,共4字节 --*/
    
    *&array[0][0]==**ptr;        /*等式成立*/ 
    array[2][1]== *(*(ptr+2)+1); /*等式成立*/
    ptr[2][3]==array[2][1];      /*等式成立*/

        5.2.2 二维数组使用

    int array[2][3]={0};
    /*声明一个2行3列的数组*/
    /*array[0]表示数组第一行的首地址,每行有3个int型对象*/
    /*array[1]表示数组第二行的首地址,每行有3个int型对象*/
    
    int i,j,total=0;
    for(i=0;i<2;i++)
    {
        for(j=0;j<3;j++)
        {    
         //total+=*(array[i]+j);
    //total+= *(*(array+i)+j);
    total+=array[i][j]; } } /*不知道这里理解的对不对*/

       5.3 函数指针:指向函数的指针;

        声明一个特定函数的指针时,可以先写出函数的原型,然后将函数名替换成 (*pfunc) 即可;

    char fruits[20]="orange papaya";
    void upper(char *);        /*函数:无返回值类型,参数为字符型指针;*/
    void (*pf)(char *);        /*指向函数的指针:指向的函数类型无返回值,参数为字符型指针;*/
    pf=upper;
    pf(fruits);                /*使用指针调用upper函数;*/
    (*pf)(fruits);             /*通过指向函数的指针的声明定义,可知pf和(*pf)是相等的;*/

    /*声明普通变量的指针时,需要给指针定义一个标识符,以及指针指向的数据类型;而声明函数指针,同样需要给函数指针定义一个标识符,以及指出:指针指向的函数的返回值类型和参数;*/

         5.3.1 括号和成员运算符(. ->)的优先级最高,是从左往右结合;其次是解引用和取址运算符( * &),从右往左运算 ;

           由于运算符的优先级限制,所以声明函数指针时,必须将*与指针标识符括起来:(* pfunc);

    int check[6][8];                  //声明数组check有6个元素,每个元素包含8个整型变量;
    int ** ptr;                       //声明一个指向指针的指针,被指向的指针指向int型;用来遍历像int *check[10];这样的数组;
    int * check[10];                  //数组check有10个元素,每个元素都是指向int型的指针;
    
    int (*check)[10];                 //(*check)表示该声明是指针的声明;是指向元素个数为10的数组的指针;数组元素为int型对象;二维指针声明;
    int * off[3][4];                  //声明语句的主语是off[3][4]数组,数组元素是int型指针;
    int ( *uuf )[3][4];               //(*uuf)表示是指针uuf,指针指向[3][4]二维数组,数组元素为int型;
    int ( *uof[3])[4];                //*uof[3]是一个数组,数组内有3个指针;该指针是指向4个元素的int型数组;
    char * fump(int);                 //首先是函数fump(int),表示函数返回值是字符型指针;       
    char (*frump)(int);               //(*frump)是一个指针,(*frump)(int)指向函数的指针,函数的返回值为char;
    char (*flump[3])(int);            //flump[3]是一个数组,(*flump[3])表示数组内有3个指针;该指针为指向函数的指针,函数的返回值类型为char;
  • 相关阅读:
    一般删除网页数据和jquery下使用Ajax删除数据的区别
    JavaScript 局部刷新
    ASP.net 网站开发知识点总结
    deque
    DHCP协议
    IP分类以及特殊IP
    重载运算符函数及其注意事项
    linux gdb基本概念
    std::vector 源代码
    iterator 的设计原则和traits
  • 原文地址:https://www.cnblogs.com/caesura-k/p/9799058.html
Copyright © 2011-2022 走看看