>
xml地图|网站地图|网站标签 [设为首页] [加入收藏]

银河至尊官网网址调用的函数要提前写出来

- 编辑:银河至尊官网网址 -

银河至尊官网网址调用的函数要提前写出来

知的,因此再加上额外的 MenuCount指明子菜单的个数,显然就能正确的表述整个子菜单
缺点:不能由用户动态的更改菜单结构,而是在编程代码中确定结构,因此不是很灵活

mytest1(); //如果函数没有明确标明函数的返回值类型,则默认为返回int(不要这样写)
print("%dn",mytest1());

这样的菜单结构定义就不必要求 子菜单指向的是一个数组结构,因为指针的数组可以把每个子菜单地址单独的指出来,但这个结构需要定义一个常量 MAX_SUBMENU_NUM 不好确定(因此在一定范围内可以添加子菜单)

include

#define  MAX_SUBMENU_NUM  10

void testarr(char s[]){
s[0] = 'a';
s[1]='b';
}

Function.h

#ifndef        __FUNCTIONS_h__
#define        __FUNCTIONS_h__
/****************************************************
* 支持库说明:系统菜单功能文件宏                    *
* 日期:      2005年6月9日                          *
****************************************************/
    #include "TimeSet.h"
    #include "VoiceCenter.h"
    #include "RobotControl.h"
    #include "FlashOption.h"

/*--------------------------------
   上面包含的头文件里面包含了菜单
   功能选项所要调用的函数。
--------------------------------*/
#endif

include

struct student{
char name[100];
int age;
int sex;
}; // 声明一个结构体

void main(){
struct student st; // 定义了一个结构体的变量,名字叫st
//struct student st2 = {.name="周杰伦",.sex=0}; 结构体中通过.来给属性赋值
struct student st3 = {0}; // 定义结构体变量,并把结构体变量的所有属性设置为0
struct student st4;
memset(&st,0,sizeof(st)); // 结构体变量初始化
st.age = 25;
st.sex = 1;
strcpy(st.name,"刘德华");

printf("%dn", st.age );

}

  1. 结构体的内存对齐模式:
    结构体在内存中是一个矩形,而不是一个不规则形状,以结构体中占地最大的元素对齐。而且不同类型的属性要跨偶数个字节
    struct A
    {
    int a; // 4字节
    char b; // 以4字节对齐
    }; // 总共8字节

struct B
{
char a; // 1个字节
short b; // short不同于char类型,所以要夸2字节,从第3个字节开始对齐 , 占2个字节
char c; // 占1个字节
int d; // 第二个8字节对齐行
long long e; // 8个字节,占地最多的属性,所以其他属性以8字节对齐;
};

printf("%dn", sizeof(B));

  1. 结构体成员的位字段
    struct A
    {
    char a:2; // char占1个字节,但是这样声明的结构体中的a字段,只有前2bit能通过结构体使用,但值得注意的是此时整个结构体仍然占1个字节而不是2bit
    };
    void main(){
    struct A a;
    a.a = 3; //二进制11,有符号char,所以会打印-1
    printf("%dn", );
    }

struct B
{
char a:2;
unsigned char b:4;
char c:1;
};

printf("%dn", sizeof(struct B));

  1. 指针操作结构体不了的内存地址
    struct H
    {
    char a; // 1个字节,但是后三个字节由于结构体对齐而操作不了
    int b;
    };

void mian(){
struct H h = {1,2};
char *p1 = &h;
p1 ++;

  • p1 = 4;
    (++p1) = 5; (++p1) = 6;
    *(++p1) = 7;
    printf("%dn", &h+4);
    }
  1. 结构体模仿数组(用字段地址连续的结构体成员)
    struct D
    {
    char a;
    char b;
    char c;
    };

void main(){
struct G g;
char *p = &g;
p[0] = 'a';
p[1] = 'b';
p[2] = 'c';
printf("%d,%d,%dn", g.a,g.b,g.c);
}

  1. 结构体数组
    struct People
    {
    int age;
    char name[10];
    };

void main(){
struct People p[3] = {{11,"aa"},{22,"bb"},{33,"cc"}};
for (int i = 0; i < 3; ++i)
{
printf("%d,%sn", p[i].age,p[i].name);
}
}

  1. 结构体可以变相实现数组的赋值
    struct A
    {
    char arr[10];
    };

void main(){
struct A a1 = {"hello"};
struct A a2= {0};
a2 = a1;
printf("%sn", a2.arr);
}

  1. 结构体的嵌套
    struct A{
    char a;
    char b;
    }
    struct{
    struct A a;
    int b;
    } // 一共占8字节

结构体赋值,其实就是结构体之间内存的拷贝
struct strss
{
char s[100];
};
void main(){
struct strss s1,s2;
strcpy(s1.s,"hello");
// s2 =s1; 这句话等同于下面的memcpy,结构体是变量,所以可以赋值
memcpy(&s2,&s1,sizeof(s1));
printf("%sn", s2.s);
}

指向结构体的指针操作结构体
void main(){
struct A a;
struct A p = &a;
// (
p).a = 10; 这样写是对的,但是太麻烦,没人这么写
p -> a = 10; // 用->代表结构体的一个成员
}

指向结构体数组的指针

void main(){
struct A *p ;

/* struct A array[10] = {0};
p =  array;  // 指针指向数组首地址 */

//也可以在堆中创建结构体
p = malloc(sizeof(struct A) * 10);
memset(p,0,sizeof(struct A) * 10)
struct A *array = p;

p->a = 10;
p->b = 11;

p++;  // p已经变化了,所以free时要从头free,就是array。如果free(p),就从当前p的位置往下数10个字节,这样就free了不属于结构体数组的内存,运行报错
p->a = 3
p->b = 4;

for (int i = 0; i < 10; ++i)
{
    printf("%d,%dn", array[i].a,array[i].b);
}

free(array);

}

结构体作为函数参数时,尽量使用指针传递参数,不要直接使用结构体作为形参
因为结构体和int等变量一样,作为参数传递时是值拷贝传递,如果传递指针,则函数只需要拷贝8字节的地址号,而且如果函数想要操作结构体的话,也只能通过指针进行参数操作

void setname(struct student a,int age){ a->age = age;
}

四。联合体

  1. 联合体所占内存的大小等于联合体中最长属性所占狄村的大小,联合体的所有属性公用一块内存地址
    union A{
    int a;
    char b;
    }
    void main(){
    union A a;
    a.a = 0X12345678;
    printf("%dn", sizeof(union A)); // 4 ,最长的int属性,栈4字节
    printf("%p,%pn", &a.a,&a.b); // 2个地址一样
    printf("%d,%dn", a.a,a.b); // 12345678, 78
    }

一个经典的错误写法
union A{
int a;
char *b;
}
void main(){
union A a;
a.b = malloc(100);
a.a = 100;
// 此时改变了a的值就是改变了b的值,下面free的地址就不再是原来的地址,会报错
free(b)
}
所以:如果一个联合体中包含了含有指针变量,那么一定要在使用完这个指针后,病free掉它,才能使用联合体的其它成员

五。 枚举

  1. 枚举是一个int常亮,不能改变他的值
  2. 美剧中的每个量都相当于#define x 整数
    //#define red 0 相当于下面的枚举定义
    //#define black 1
    //#define yellow 2
    enum A{
    red,black,yellow
    };
    void main(){
    printf("%fn", red); // 打印0
    }

六。typedef

  1. typedef char BYTE; 自定义一个BYTE类型,作为char类型
    相当于

    define BYTE char

  2. typedef 通常用于简化结构体变量的名字为一个简短的名字
    struct A{
    int a;
    }
    typedef struct abc A; // 本来声明变量时需要struct A a, 现在只需要abc A即可

  3. typedef定义结构体的简写形式
    typedef struct A{
    int a;
    }abc; // 张扬相当于上面2句话的简写, A也可以不写形成第三种写法,如下

typedef struct {
int a;
}abc;

  1. typedef定义函数指针

    include

    include

    void mystrcat (char s1,char s2){
    strcat(s1,s2);
    }
    // 定义一个函数,有三个参数,函数指针,形参1,形参2
    void
    test(void (p)(char ,char ),char s1,char s2){//函数指针p,返回值是void ,形参有两个,都是char *类型
    p(s1,s2);
    }

// 上面的test函数太复杂,因为参数里包含一个函数指针
typedef void (MYSTRCAT)(char ,char ) // 把一个函数指针定义为MYSTRCAT类型

void main(){
MYSTRCAT aa[10];
char s1[100] = "hello";
char s2[5] = "world";
test(mystrcat,s1,s2);
printf("%sn", s1);
}

七。文件操作
写文件

但是这样的多叉树编码比较麻烦,需要一定的编程功底  20090614


贴一段代码大家看看哈(我用来做目录的引擎)
(以上的是我在羚羊上实现的,但是原理是一样的,特别是Menu.h可以直接使用)

include

int main(){
FILE *p = fopen("aaa.txt","w");
fputs("hello worldn",p);
fclose(p);
return 0;
}

读文件

main.c

#include "GRAPH_Command.h"
#include "Functions.h"
#include "Menu.h"

/***********************
*   按键功能键宏定义   *
***********************/
# define UP        0
# define Down      4
# define Enter     5
# define Esc       1
# define Reset     2

/***********************
*     全局变量声明区   *
***********************/

    
    struct MenuItem (*MenuPoint) = MainMenu;
    short DisplayStart = 0;
    short UserChoose = 0;
    short DisplayPoint = 0;
    short MaxItems;    

/*****************************
* Struct MenuItem:           *
*    short MenuCount;        *
*    char *DisplayString;    *
*    void (*Subs)();         *
*    MenuItem *ChildrenMenus;*
*    MenuItem *ParentMenus;  *
*****************************/

/***********************
*     函 数 声 明 区   *
***********************/
extern void ClearWatchDog();
void MenuInitialation(void);
void SystemInitialation(void);
void ShowMenu(void);
short GetKeyNum(void);

/**************************************************************
*  函数说明:系统初始化函数                                   *
**************************************************************/
void SystemInitialation(void)
{
        Init_sys();          
        Enable_LCD();                          //初始化字库      函数定义在
        MenuInitialation();               //初始化菜单
        GRAPH                             //图形初始化
}

/**************************************************************
*  函数说明:目录初始化函数                                   *
**************************************************************/
void MenuInitialation(void)
{
    MainMenuInit();
    TimeMenuInit();
    VoiceMenuInit();
    RobotMenuInit();
    FlashMenuInit();
}

/**************************************************************
*  函数说明:目录显示函数                                     *
**************************************************************/
void ShowMenu(void)
{
    short n = 0;

    MaxItems = MenuPoint[0].MenuCount;
    DisplayPoint = DisplayStart;
        if (MaxItems >= 4)
        {
             for (n = 0;n<4;n++)
             {
                         
                 LOCATE(n+1,1);
                 PRINT(MenuPoint[DisplayPoint].DisplayString);
                 
                 if ((DisplayPoint) == UserChoose)
                     {
                         BOX(1,n*16+1,126,(n+1)*16-2,1,1);
                     }
                 
                     DisplayPoint +=1;
                     if ((DisplayPoint) == (MaxItems))
                     {
                         DisplayPoint = 0;
                     }
             }
         }
         else
         {
             for (n = 0;n<MaxItems;n++)
             {
                         
                 LOCATE(n+1,1);
                 PRINT(MenuPoint[DisplayPoint].DisplayString);
                 
                 if ((DisplayPoint) == UserChoose)
                     {
                         BOX(1,n*16+1,126,(n+1)*16-2,1,1);
                     }
                 
                     DisplayPoint +=1;
                     if ((DisplayPoint) == (MaxItems))
                     {
                         DisplayPoint = 0;
                     }
                 
             }
         }
        //BOX(0,0,127,63,2,2);
}

/**************************************************************
*  函数说明:获得键值函数                                     *
**************************************************************/
short GetKeyNum(void)
{
    short TempKeyNum = 0;
        TempKeyNum = F_Key_Scan();       //获取按键值
        *P_IOA_Dir = 0x01ff;
        *P_IOA_Attrib = 0x01ff;       
        *P_IOA_Data = 0x01ff;
            
        return TempKeyNum;

}

/**************************************************************
*  函数说明:主函数                                           *
**************************************************************/
int main()
{                      
    short KeyNum = 0xff;
    
    SystemInitialation();            //系统初始化
    
    ShowMenu();
        while(1)
        {
            ClearWatchDog();             //喂狗
            KeyNum = GetKeyNum();        //获取按键值

            /*******************目录操作*********************/
            
            /***************************************
            *   [按键说明]                         *
            *  ----------------------------------- *
            *   [K1]            UP(向上)           *
            *   [K5]            Down(向下)         *
            *   [K2]            Esc(后退)          *
            *   [K6]            Enter(确定)        *
            *   [K3]            返回根目录         *
            ***************************************/
            if (KeyNum != 0xff)
            {
             ShowMenu();
                 switch(KeyNum)
                 {
                     case UP:
                         UserChoose --;
                         if (UserChoose < 0)
                         {
                             UserChoose = MaxItems-1;
                         }
                         break;
                     case Esc:
                         if (MenuPoint[0].ParentMenus != &Null)
                         {
                             MenuPoint = MenuPoint[0].ParentMenus;
                             UserChoose = 0;
                             DisplayStart = 0;
                         }
                         break;
                     case Down:
                         UserChoose ++;
                         if (UserChoose == MaxItems)
                         {
                             UserChoose = 0;
                         }
                         
                         break;
                     case Enter:
                         if (MenuPoint[UserChoose].Subs != NullSubs)
                         {
                             (*MenuPoint[UserChoose].Subs)();
                         }
                         else if (MenuPoint[UserChoose].ChildrenMenus != &Null)
                         {
                             MenuPoint = MenuPoint[UserChoose].ChildrenMenus;
                             UserChoose = 0;
                             DisplayStart = 0;
                         }
                         break;
                     case Reset:
                         MenuPoint = MainMenu;
                         UserChoose = 0;
                         DisplayStart = 0;
                         break;
                 }
                 
                 if ((UserChoose < DisplayStart) || (UserChoose > (DisplayStart+3)))
                 {
                    DisplayStart = UserChoose;
                 }
                 
                 CLS
                 ShowMenu();
                 
            }
            /*******************目录操作*********************/
        }         

}

说明一下:
我定义了一个结构体来表示菜单的每一个选项
通过指针来跳转子目录或者调用功能函数

支持滚屏、多级子菜单、网络式超链接方式(非树形)、风格修改简单。

使用这样的结构,可以很方便的通过修改单独的菜单项来更形菜单,不用在主程序里面修改任何东西,扩展方便,节约资源(某种程度上来说

是的,不用因为添加了一个新的子菜单,就重新扩展无用的代码)。程序里面有很详细的说明,大家可以看一下哈,交流一下哈。

include

void main(){
FILE *p = fopen("a.txt","r");
while(!feof(p)){
int a,b;
fscanf(p,"%d + %d =",&a,&b); //文本格式为a + b =,从中截取a,b
printf("%d,%d",a,b);
}
}

void main(){
FILE *p = fopen("a.txt","w");
char buf[100] = "hello world fuck ";
int a=1,b=2;
fprintf(p,"%s,%d,%d",buf,a,b);
fclose(p);
}

  1. fread与fwrite读写二进制文件
    上面的函数只能操作字符文件,字符文件每次只能读一行
    void main(){
    FILE *p = fopen("a.txt","rb"); // 以二进制方式读取
    char buf[100] = {0};
    fread(buf,sizeof(char),1,p); // 读取字节的缓冲区,读取单位,一次读取几个单位,文件指针
    printf("%sn", buf);
    fclose(p);
    }

指针数组与多级指针
int main(){
int a[10]; //一个数组,数组内有10个元素,64为系统中,指针站8字节,64位
printf("%d,%dn", sizeof(a),sizeof(a[0])); // 40,8
short
b[10];
printf("%d,%dn", sizeof(b),sizeof(b[0])); // 40,8
}

int main(){
int a = 10;
int p = &a;
int pp = &p; // pp指向p的地址 pp= 100; //修改a的值 如果
p=100,则是把p这个地址号改为100. pp就是地址号的内容相当于改变p的内容,pp就是地址号中记录的地址号的内容
printf("a=%dn",a);
int
ppp = &pp;
a = ppp;
println("%d,%d",
**ppp,&pp); // 三级指针的内容=二级指针的地址
}

指针完成字符串操作
int mian(){
char buf[100] = "hello world";
char p = buf;
p += 5;
p = 'c';
printf("%sn", buf); // hellocworld
return 1;
}

如果字符串中包含0字符,则打印到此位置就结束了。泪库里面的函数都是有识别字符串结尾的


c语言主函数也是有输入参数的,而且有2个,第一个表示输入参数的个数,第二个是一个指针数组,每个指针指向char类型
输入参数个数:永远大于1,因为程序名本身作为一个输入参数
指针数组:这个指针数组的长度是第一个参数,每个元素指向一个输入参数
int main(int argc,char *args[]){
if(argc!=4){
printf("请输入完整的数学表达式,以空格分开" );
return 0;
}

int a = atoi(args[1]);
int b = atoi(args[3]);

switch(args[2][0]){
    case '+':
        printf("%dn", a+b);
    case '-':
        printf("%dn", a-b);
    case '*':
        printf("%dn", a*b);
    case '/':
        if(b){
            printf("%dn", a/b);
        }
}
return 0;

}

栈:不会很大,栈空间是操作系统为每个程序固定分配的大小以k为单位。栈空间是操作系统为每个程序固定分配的大
每个线程都有自己的栈
int main(){
char array[102410241024] = {0}; //定义一个超大的数组就会栈溢出
return 0;
}

堆:堆没有大小限制,只是无力限制。但是堆内存不能由编译器自动释放

struct MenuItem         
{
    short MenuCount;
    char *DisplayString;
    void (*Subs)();
    struct MenuItem *ChildrenMenus;
    struct MenuItem *ParentMenus;
}
说明:之所以能使用struct MenuItem *ChildrenMenus; 指向多个子菜单,是因为子菜单本身就是一个数组类型的线性空间
      因此在使用ChildrenMenus指向了子菜单数组的首地址后,我们就已经达到了对应的一片线性空间,而每个子菜单项占据的空间大小是已

}

typedef struct tagMenuTree {
    char MenuName[20];                //关联数据为菜单项名称

include "abc/myhead.h"

int main(){
int c = MAX;
printf("%d",c)
}

三. 指针
计算机内存的最小单位使BYTE
每个BYTE的内存都有一个唯一的内存编号,这个编号就是内存地址
编号在32为系统下是一个32位的整数,编号在64位系统下是一个64位的整数

  1. 用指针型变量来表示这个内存地址号。
  2. :指针变量指向的内容。指针型变量不能向int变量一样显示的声明出来,只能用变量名来声明一个int值,则该变量是指针型变量,*变量名是一个int值
  3. &:得到变量对应的指针变量(内存地址)

void main{
int a=3;
int p; // p是int型变量,p是指针型变量
p = &a; // 指针型变量就是内存号,所以&符号取得a的内存号
int b = p;
printf("%d",b);
p = 100;
printf("%d",a) // 通过内存号修改变量值

char chs[10];
printf("%u,%u,%u,%u",chs,chs[0],chs[1],chs[2])  // %u:unsigned无符号整形,数组首地址,第一个元素的地址,第二个元素的地址

int ints[10];
printf("%u,%u,%u,%u",ints,ints[0],ints[1],ints[2])  // %u:unsigned无符号整形,数组首地址,第一个元素

}

  1. 无类型指针:

    void *p:说明p只是一个指针比那辆,而不去指向任何一个变量

    include

    void main(){
    int a = 100;
    int p; // int p是声明写法:整体代表一个地址号,这个地址号上存着整数。单独一个p:定义写法,也是内存号
    int q;
    p = &a;
    //int
    p = 1; // p指向的地址号是1(声明+定义写在了一起)
    printf("%u",p); // 3852910012
    printf("%u",*p); // 100
    printf("%dn",sizeof(p)); //8:指针在64位系统下就是一个64位的整数,所以占8字节。无论指针指向什么类型的数据,64位下都占8字节
    printf("%dn",sizeof(a)); //4:int型占4字节

    int p; //声明指针,没有指向,就是野指针。野指针使导致程序崩溃的主要原因 p = 1; // 为地址上赋值1,会出现错误 [1] 6285 segmentation fault (core dumped) a.out

    int *p = NULL; // 空指针使合法的,野指针是非法的

}


/** int p 与p一致 /

更灵活的方式(WINDOWS 采用的就是这种构架,可以随意的添加)
typedef struct tagMenuTree {
    char MenuName[20];                    //关联数据为菜单项名称

int main(){
sayhello(); // 调用的函数要提前写出来,如果要写在后面,需要先在前面声明
}

Menu.h

#ifndef        __MENU_h__
#define        __MENU_h__
#include "Functions.h"
/****************************************************
* 支持库说明:提供了使用菜单的基本数据结构          *
* 作者:      傻孩子                                *
* 日期:      2005年6月9日                          *
****************************************************/

/**********************
*    目录结构体定义   *
**********************/
struct MenuItem        
{
    short MenuCount;
    char *DisplayString;
    void (*Subs)();
    struct MenuItem *ChildrenMenus;
    struct MenuItem *ParentMenus;
}Null;

void NullSubs(void)
{
}

/****************************************************
*   使用说明:                                      *
*      要定义一个菜单,需要做以下几步工作           *
*      1、定义一个结构体数组                        *
*      2、如果这个菜单是子菜单,那么把上级菜单的    *
*         *ChildrenMenus指针指向该数组的首地址,     *
*         并且设置ParentMenus为上层目录的地址       *
*      3、如果这个菜单是跟菜单,那么直接将MenuPoint *
*         指针指向该数组的首地址                    *
*      4、通过写一个函数为该数组的每一个元素初始化  *
*      5、如果菜单项是最终选项,那么将*ChildrenMenus*
*         置为NULL,将函数指针*Subs指向实现功能的   *
*         函数。                                    *
****************************************************/

/**************************************************************** zyd  20090614
说明:之所以能使用struct MenuItem *ChildrenMenus; 指向多个子菜单,是因为子菜单本身就是一个数组类型的线性空间
      因此在使用ChildrenMenus指向了子菜单数组的首地址后,我们就已经达到了对应的一片线性空间,而每个子菜单项占据的空间大小是已

知的,因此再加上额外的 MenuCount指明子菜单的个数,显然就能正确的表述整个子菜单
缺点:不能由用户动态的更改菜单结构,而是在编程代码中确定结构,因此不是很灵活

#define  MAX_SUBMENU_NUM  10

typedef struct tagMenuTree {
    char MenuName[20];                //关联数据为菜单项名称

    int  SubMenuNum;                //当前结点的子菜单个数   
    struct tagMenuTree * NextNode[MAX_SUBMENU_NUM];    //记录当前结点的子菜单
    struct tagMenuTree * Parent;            //记录上级菜单
} MenuTree,*pMenuTree;

这样的菜单结构定义就不必要求 子菜单指向的是一个数组结构,因为指针的数组可以把每个子菜单地址单独的指出来,但这个结构需要定义一

个常量 MAX_SUBMENU_NUM 不好确定(因此在一定范围内可以添加子菜单)

更灵活的方式(WINDOWS 采用的就是这种构架,可以随意的添加)
typedef struct tagMenuTree {
    char MenuName[20];                    //关联数据为菜单项名称

    struct tagMenuTree* pParent;        //上级菜单
    struct tagMenuTree* pChildHead;        //子菜单头指针
    struct tagMenuTree* pChildTail;        //子菜单尾指针
    struct tagMenuTree* pNext;        //兄弟菜单中下一个菜单
    struct tagMenuTree* pPrev;        //兄弟菜单中前一个菜单
} MenuTree,*pMenuTree;
但是这样的多叉树编码比较麻烦,需要一定的编程功底  20090614  *****************************/

struct MenuItem MainMenu[3];
struct MenuItem TimeMenu[4];
struct MenuItem VoiceMenu[5];
struct MenuItem RobotMenu[5];
struct MenuItem FlashMenu[5];

/***********************
*     函 数 声 明 区   *
***********************/
void MainMenuInit(void);
void TimeMenuInit(void);
void VoiceMenuInit(void);
void RobotMenuInit(void);
void FlashMenuInit(void);

/**************************************************************
*  函数说明:Flash处理目录初始化函数                          *
**************************************************************/
void FlashMenuInit(void)
{
    FlashMenu[0].MenuCount = 5;
    FlashMenu[0].DisplayString = "  Flash Record  ";
    FlashMenu[0].Subs = FlashRecord;
    FlashMenu[0].ChildrenMenus = &Null;
    FlashMenu[0].ParentMenus = MainMenu;
    
    FlashMenu[1].MenuCount = 5;
    FlashMenu[1].DisplayString = "      Play      ";
    FlashMenu[1].Subs = FlashPlay;
    FlashMenu[1].ChildrenMenus = &Null;
    FlashMenu[1].ParentMenus = MainMenu;
    
    FlashMenu[2].MenuCount = 5;
    FlashMenu[2].DisplayString = "      Pause     ";
    FlashMenu[2].Subs = FlashPause;
    FlashMenu[2].ChildrenMenus = &Null;
    FlashMenu[2].ParentMenus = MainMenu;
    
    FlashMenu[3].MenuCount = 5;
    FlashMenu[3].DisplayString = "  Flash Delete  ";
    FlashMenu[3].Subs = FlashDelete;
    FlashMenu[3].ChildrenMenus = &Null;
    FlashMenu[3].ParentMenus = MainMenu;
    
    FlashMenu[4].MenuCount = 5;
    FlashMenu[4].DisplayString = "      Back      ";
    FlashMenu[4].Subs = NullSubs;
    FlashMenu[4].ChildrenMenus = MainMenu;
    FlashMenu[4].ParentMenus = MainMenu;
}

/**************************************************************
*  函数说明:机器人控制目录初始化函数                         *
**************************************************************/
void RobotMenuInit(void)
{
    RobotMenu[0].MenuCount = 5;
    RobotMenu[0].DisplayString = "   Turn  Left   ";
    RobotMenu[0].Subs = RobotTurnLeft;
    RobotMenu[0].ChildrenMenus = &Null;
    RobotMenu[0].ParentMenus = MainMenu;
    
    RobotMenu[1].MenuCount = 5;
    RobotMenu[1].DisplayString = "   Turn Right   ";
    RobotMenu[1].Subs = RobotTurnRight;
    RobotMenu[1].ChildrenMenus = &Null;
    RobotMenu[1].ParentMenus = MainMenu;
    
    RobotMenu[2].MenuCount = 5;
    RobotMenu[2].DisplayString = "    Go  Ahead   ";
    RobotMenu[2].Subs = RobotGoAhead;
    RobotMenu[2].ChildrenMenus = &Null;
    RobotMenu[2].ParentMenus = MainMenu;
    
    RobotMenu[3].MenuCount = 5;
    RobotMenu[3].DisplayString = "     Go Back    ";
    RobotMenu[3].Subs = RobotGoBack;
    RobotMenu[3].ChildrenMenus = &Null;
    RobotMenu[3].ParentMenus = MainMenu;
    
    RobotMenu[4].MenuCount = 5;
    RobotMenu[4].DisplayString = "      Back      ";
    RobotMenu[4].Subs = NullSubs;
    RobotMenu[4].ChildrenMenus = MainMenu;
    RobotMenu[4].ParentMenus = MainMenu;
    
}

/**************************************************************
*  函数说明:声音处理目录初始化函数                           *
**************************************************************/
void VoiceMenuInit(void)
{
    VoiceMenu[0].MenuCount = 5;
    VoiceMenu[0].DisplayString = "  Voice Record  ";
    VoiceMenu[0].Subs = VoiceRecord;
    VoiceMenu[0].ChildrenMenus = &Null;
    VoiceMenu[0].ParentMenus = MainMenu;
    
    VoiceMenu[1].MenuCount = 5;
    VoiceMenu[1].DisplayString = "      Play      ";
    VoiceMenu[1].Subs = Play;
    VoiceMenu[1].ChildrenMenus = &Null;
    VoiceMenu[1].ParentMenus = MainMenu;
    
    VoiceMenu[2].MenuCount = 5;
    VoiceMenu[2].DisplayString = "      Pause     ";
    VoiceMenu[2].Subs = Pause;
    VoiceMenu[2].ChildrenMenus = &Null;
    VoiceMenu[2].ParentMenus = MainMenu;
    
    VoiceMenu[3].MenuCount = 5;
    VoiceMenu[3].DisplayString = "  Voice Delete  ";
    VoiceMenu[3].Subs = VoiceDelete;
    VoiceMenu[3].ChildrenMenus = &Null;
    VoiceMenu[3].ParentMenus = MainMenu;
    
    VoiceMenu[4].MenuCount = 5;
    VoiceMenu[4].DisplayString = "      Back      ";
    VoiceMenu[4].Subs = NullSubs;
    VoiceMenu[4].ChildrenMenus = MainMenu;
    VoiceMenu[4].ParentMenus = MainMenu;
}

/**************************************************************
*  函数说明:时间设定子目录初始化                             *
**************************************************************/
void TimeMenuInit(void)
{
    TimeMenu[0].MenuCount = 4;
    TimeMenu[0].DisplayString = "    Time Set    ";
    TimeMenu[0].Subs = TimeSet;
    TimeMenu[0].ChildrenMenus = &Null;
    TimeMenu[0].ParentMenus = MainMenu;
    
    TimeMenu[1].MenuCount = 4;
    TimeMenu[1].DisplayString = "    Date Set    ";
    TimeMenu[1].Subs = DateSet;
    TimeMenu[1].ChildrenMenus = &Null;
    TimeMenu[1].ParentMenus = MainMenu;
    
    TimeMenu[2].MenuCount = 4;
    TimeMenu[2].DisplayString = "    AlertSet    ";
    TimeMenu[2].Subs = AlertSet;
    TimeMenu[2].ChildrenMenus = &Null;
    TimeMenu[2].ParentMenus = MainMenu;
    
    TimeMenu[3].MenuCount = 4;
    TimeMenu[3].DisplayString = "      Back      ";
    TimeMenu[3].Subs = NullSubs;
    TimeMenu[3].ChildrenMenus = MainMenu;
    TimeMenu[3].ParentMenus = MainMenu;
    
}

/**************************************************************
*  函数说明:根目录初始化                                     *
**************************************************************/
void MainMenuInit(void)
{
     MainMenu[0].MenuCount = 3;
     MainMenu[0].DisplayString = "    Time Set    ";
     MainMenu[0].Subs = NullSubs;
     MainMenu[0].ChildrenMenus = TimeMenu;
     MainMenu[0].ParentMenus = &Null;

     MainMenu[1].MenuCount = 3;
     MainMenu[1].DisplayString = "  Voice Center  ";
     MainMenu[1].Subs = NullSubs;
     MainMenu[1].ChildrenMenus = VoiceMenu;
     MainMenu[1].ParentMenus = &Null;
/*
     MainMenu[2].MenuCount = 3;
     MainMenu[2].DisplayString = "  Robot Control ";
     MainMenu[2].Subs = NullSubs;
     MainMenu[2].ChildrenMenus = RobotMenu;  
     MainMenu[2].ParentMenus = &Null;
*/     
     MainMenu[2].MenuCount = 3;
     MainMenu[2].DisplayString = "  Flash Option  ";
     MainMenu[2].Subs = NullSubs;
     MainMenu[2].ChildrenMenus = FlashMenu;     
     MainMenu[2].ParentMenus = &Null;

}

#endif

include

    int  SubMenuNum;                //当前结点的子菜单个数   
    struct tagMenuTree * NextNode[MAX_SUBMENU_NUM];    //记录当前结点的子菜单
    struct tagMenuTree * Parent;            //记录上级菜单
} MenuTree,*pMenuTree;

main.c:

    struct tagMenuTree* pParent;        //上级菜单
    struct tagMenuTree* pChildHead;        //子菜单头指针
    struct tagMenuTree* pChildTail;        //子菜单尾指针
    struct tagMenuTree* pNext;        //兄弟菜单中下一个菜单
    struct tagMenuTree* pPrev;        //兄弟菜单中前一个菜单
} MenuTree,*pMenuTree;

  1. 自定义函数
    (1)在函数使用之前定义函数
    (2)先声明这个函数,然后使用,使用的代码后面定义这个函数

    include

    void syahello(){
    println("helloo");
    }

内存管理

  1. 作用域
    (1)文件作用域:全局变量,定义在函数外面的变量
    int a=10;
    void main(){
    int a = 20; // 函数内部可以再次定义和全局变量同名的变量,定以后a为20,没有定义为10
    printf("%dn", a);
    }
    (2)extern关键字

    include "c.h" #在这个文件中定义了age=10

    extern int age ;// 该变量在其他文件中定义了,连接时使用就可以了。这个另一个文件需要时.c文件,不能是.h文件。gcc编译时后面加上两个文件名
    setage(int n){
    age = n;
    }
    getage(){
    printf("%dn", age);
    }
    void main(){
    setage(11);
    getage(); // 11
    }
    (3)auto自动变量:不写auto,就默认为auto变量
    (4)register 变量:建议变量放到空闲的寄存器中
    寄存器变量不能取地址操作
    (5)static 变量:只初始化一次,程序运行期间一直存在 。static只是增大了变量的存在时间,却没增大变量的作用域
    一旦全局变量被static修饰,则这个变量的作用域被限制在该文件内部,其他文件不能用extern使用
    void mystatic(){
    static int a = 0; // 不加static,循环打印每次打印都是0,加上static每次打印+1
    printf("%dn", a);
    a++;
    }
    void main(){
    for (int i = 0; i < 10; ++i)
    {
    mystatic();
    }
    }

  2. c语言中,函数都是全局的。
    (1)如果函数前面加了static,则函数被限制在文件内部使用
    (2)函数前面加不加extern一样。而变量前面的extern是可以省略的,比如:int a; 如果其他文件中定义了int a=10,则此处的变量是声明,如果其他文件中没有定义a,则此处是定义
    (此处也是说明c语言并不严谨)

  3. c语言内存管理
    程序在内存中分为4个区域:
    (1)堆
    (2)栈:此部分的内存表现为先进后出。所有自动变量,函数行参都有编译器自动放到栈中。当一个自动变量超出其作用域时,自动从栈中弹出。先进入栈中的变量放到大内存号中
    (3)静态区:所有的全局变量,以及程序中的静态变量都存储在静态区
    (4)代码区:程序在被操作系统加载到内存中时,所有可执行代码加载到代码段,这块内存不能再程序运行期间修改
    int c= 0;
    void main(){
    int a=1;
    int b=2;
    static int d = 3;
    printf("%d,%d,%d,%d,%dn", &a,&b,&c,&d,main); // 1321929276,1321929272,6295612,6295604,4195632
    }
    上述程序的a和b在栈区,所以地址号紧挨着:1321929276,1321929272 发现a所在的内存号在高位。
    c和d在静态区:地址号紧挨着
    main在代码段

二进制文件读写

  1. fscanf:读文件时,可以根据固定格式读取
    fprintf:写文件,和printf一样,可以定义输出格式,只是输出到文件中

int main(){
char arr1[100]="asdad";
char arr2[100]="1111";
mergearr(arr1,arr2);
printf("%sn",arr1); // 发现数组2已经合并了
printf("%sn",arr2);
}


include

  1. : 尖括号表示文件在系统路径中

    "abc/myhead.h":表示abc目录下的myhead.h

    myhead.h:
    #define MAX 300 // #define就是简单的字符串替换

int main(){
char chs[100] = "hello world"
testarr(chs);
printf("%d",chs); // 数组变为abllo world
}

void mergearr(char arr1[],char arr2[]){
int len1 = 0;
while(arr1[len1++]);
len1--; // 记录数组一的长度

二. 多文件编译

include

void main(){
int buf[10] = {1};
memset (buf,0,sizeof(buf));

int buf2[] = {1,2,3,4,5,6,7,8,9,0};
int buf3[];
memcpy(buf3,buf2,sizeof(buf2));
for (int i = 0; i < 10; i++)
{
    printf("%dn", buf2[i]);
}

}

指针数组与多级指针
int main(){
int a[10]; //一个数组,数组内有10个元素,64为系统中,指针站8字节,64位
printf("%d,%dn", sizeof(a),sizeof(a[0])); // 40,8
short
b[10];
printf("%d,%dn", sizeof(b),sizeof(b[0])); // 40,8
}

int main(){
int a = 10;
int p = &a;
int pp = &p; // pp指向p的地址 pp= 100; //修改a的值 如果
p=100,则是把p这个地址号改为100
printf("a=%dn",a);
int ppp = &pp;
a = ppp;
println("%d,%d",
ppp,&pp); // 三级指针的内容=二级指针的地址
}

指针完成字符串操作
int mian(){
char buf[100] = "hello world";
char p = buf;
p += 5;
p = 'c';
printf("%sn", buf); // hellocworld
return 1;
}

如果字符串中包含0字符,则打印到此位置就结束了。泪库里面的函数都是有识别字符串结尾的


c语言主函数也是有输入参数的,而且有2个,第一个表示输入参数的个数,第二个是一个指针数组,每个指针指向char类型
输入参数个数:永远大于1,因为程序名本身作为一个输入参数
指针数组:这个指针数组的长度是第一个参数,每个元素指向一个输入参数
int main(int argc,char *args[]){
if(argc!=4){
printf("请输入完整的数学表达式,以空格分开" );
return 0;
}

int a = atoi(args[1]);
int b = atoi(args[3]);

switch(args[2][0]){
    case '+':
        printf("%dn", a+b);
        break;
    case '-':
        printf("%dn", a-b);
        break;
    case '*':
        printf("%dn", a*b);
        break;
    case '/':
        if(b){
            printf("%dn", a/b);
        }
        break;
}
return 0;

}

2.形参和实参是值传递v,是单向传递,只能由实参传递给形参,不能由形参传递给实参
入股哦函数的参数是数组,则可以通过形参修改实参的值

银河至尊官网网址调用的函数要提前写出来。}

一维数组作为参数的指针
void swap(int a,int b){
int tmp = a; a = b; b = tmp;
}
// 当数组名作为参数传递时,数组名解析为数组首地址指针,所以多写为void setarray(int buf)
void setarray(int buf[]){
printf("占%d位n", sizeof(buf)); //8:64位系统指针占8字节
buf[0] = 100;
buf[1]=200;
int i;
for(i=0;i<10;i++){
printf("%dn", buf[i]);
}
}
void setarray(int
buf,int n){ // n为数组的长度
buf[0] = 100;
buf[1]=200;
int i;
for(i=0;i<n;i++){
printf("%dn", buf[i]);
}
}
void main(){
int a = 10;
int b = 20;
swap(&a,&b);
printf("%d,%dn", a,b);

// 因为数组名是数组的首地址,所以数组名作为行参传递的时候,就相当于传递的指针
int buf[]= {1,2,3,4,5,6,7,8,9,0};
printf("%dn", sizeof(buf)); //40
setarray(buf,sizeof(buf)/sizeof(int));  // 数组长度写成sizeof(buf)/sizeof(type)

参数为int和char*类型

将一块内存初始化为0最常见的方法:memset(buf,值,size(buf)):要设置的内存地址,设置的值,内存大小(单位字节)
memcpy(buf2,buf1,sizeof(buf1)):将buf1的内容全部拷贝到buf2
memmove (buf2,buf1,sizeof(buf1));

include

int len2=0;
while(arrp[len2+1]);
len2--;

int i;
for(i=0;i<len2;i++){
    arr1[len1+i] = arr2[i];
}

include

void main(){
int a =100;
int p = &a;
int
q;
q = &a;
printf("p:%u,q:%un",p,q); // p:2373644580,q:2373644580
printf("p:%d,q:%d",p,q);// p:100,q:100
}

  1. 指针的兼容性

    include

    void main(){
    int a = 0X1013;
    char b = 13;

    int p;
    p=&a;
    printf("%x",
    p); // 1013

    p=&b; // 10130d 用int指针指向char类型变量,因为int指针指向了连续4字节的地址,所以除了1013外后面还有3个字节的数据当做一体来指向
    printf("%x",*p);

    int q;
    char buf[] = {0x12,0x34,0x56,0x78,0x90,6,7,8,9,10};
    q = buf;
    printf("%xn",
    q);

    //指针不兼容的情况
    float i = 3.14;
    int p = &i;
    printf("%d",
    p); // 此时并不能打印出3,这就是指针类型不兼容
    }

  2. 指向常量的指针和指针常量
    void main(){
    int a = 100;
    const int p = &a; // 指向常量的指针只能读内存,但可以改变指向
    printf("%dn",
    p); // 100

    int const q = &a; // 常量指针可以读写指向的内存,但不能改变指向 q = 200;
    printf("%dn",*q); //200
    printf("%dn",a); //200
    }

  3. 数组与指针
    void printarr(char s[]){
    int i;
    for(i=0;i<10;i++){
    printf("s[%d]n", %d);
    }
    }
    void main(){
    char buf[10] = {1,2,3,4,5,6,7,8,9,0};
    char p = buf;
    char
    p1 = &buf[0];
    char *p2 = &buf[1];

    printf("%dn", p); //1
    printf("%dn",
    p1); //1
    printf("%dn", *p2); //2

    p2 ++; // 指针是地址号,p+1
    *p2 = 100; // 更改为100
    printarr(buf);

    }

    ip地址在网络中不是以字符串传输,字符串太长,而是以DWORD传输(4字节),飙戏那位一个int数值

    include

    void change2char(int i){
    unsigned char p = &i;
    printf("%d.%d.%d.%d",
    p,(p+1),(p+2),(p+3));
    }
    void main(){
    int a = 0;
    unsigned char
    p1 = &a; // 无符号使得最大值为255
    *p1 = 192;
    /**(p+1) = 168;
    (p+2) = 0; (p+3) = 1;/
    p1++;
    p1 = 168;
    p1++;
    p1=0;
    p1++;
    p1=1;
    printf("ip:%d",ip);
    // a已经被改变为一个ip地址
    change2char(a);

    }

    int s2ip(char s[]){
    int a = 0;
    int b = 0;
    int c = 0;
    int d = 0;
    sscanf(s,"%d.%d.%d.%d",&a,&b,&c,&d);
    printf("a=%d,b=%d,c=%d,d=%dn", a,b,c,d);
    int ip=0;
    char p = &ip;
    p++;
    p = a;
    p++;
    p=b;
    p++;
    p=c;
    p++;
    *p=d;
    }
    void main(){
    char s[] = "192.168.0.1";
    printf("%dn", s);
    }

eg:用指针合并数组
void main(){
char s1[] = "hello";
char s2[]="world";
char p1 = &s1;
char
p2 = s2;
while(p1){ //p1指向的元素为0时跳出循环
p1 ++;
}
while(p2){ p1++ = *p2++; // 先指向,后指针移位
}

}

指针运算不是简单地数值加减法,而是指针指向的数据类型在内存中所占字节数为倍数的运算
void main(){
int buf[10];
int *p = buf;
printf("%dn", p); //-1670667696
p+=3;// 实际上内存地址好涨了12
printf("%dn", p);
p = (int)p+3; // 此时把内存地址号强制转为int型,此后加3就是数值运算:-1670667684
printf("%dn", p); // -1670667681

char *p2 = buf;
p2 += 4;
printf("%dn", *p2);  // 0

short *pp1 = &buf[1];
short *pp2 = &buf[3];
printf("%dn", pp2 - pp1);   // buf3和buf1差8个字节,但是一个short指针变量指向2个字节的连续块,所以值位4

}


二维数组的指针
void main(){
int buf[2][3] arr = {{1,2,3},{4,5,6}};
// int p[3] ; //定义一个指针数组
int (
p)[3]; // 定义了一个指针,指向int[3]这种数据类型,也叫作指向二维数组的指针
printf("%dn",sizeof(p)) ; //8 因为指针在64位系统都是占8位
printf("%d,%dn",p,p+1); //相差12字节

p = buf; //p指向了二维数组的第一行
p++; //p指向了二维数组的第二行

// 指针遍历
int i,j;
for(i=0;i<2;i++){
    for(j=0;j<3;j++){
        //printf("%dn", *(*(p+i)));   //打印结果1,1,1,4,4,4
        printf("%dn", *(*(p+i)+j);  // 遍历每个元素
        printf("%dn", p[i][j]);  // 每个元素,与上面相等
    }
}

}

指针作为函数参数
void test(int n){
n++;
}
void test2(int p){
(
p)++;
}
void main(){
int i =100;
test(i); //c语言是值传递,所以普通函数参数的改变是不能传回给参数的,但如果参数是地址,改变地址上的值
printf("%dn", i);

test2(&i);
printf("%dn", i);

include

void main(){
int buf[2][4] = {{1,2,3,4},{5,6,7,8}};
for(int i=0;i<4;i++){
int sum = 0;
for (int j = 0; j < 2;j++)
{
sum += buf[j][i];
}
printf("%dn", sum);
}
}

函数指针
函数也有地址,这个地址存放的是代码
int getmax(int x, int y){ // 也可以写为int getmax(int x, int y) 意思一样,函数名同数组名一样,都是即表示本身,又表示指向自身开头的指针
return x>y?x:y;
}
int getmin(int x, int y){
return x<y?x:y;
}
int main(){
int (
p)(int,int) ; //定义一个指针p指向函数,该函数反获知是int,2个输入参数是(int,int)
int fun = 0;
scanf("%d",&fun);
if(fun==1){
p = getmax; //函数名就是指针
}else{
p = getmin; //函数名就是指针
}
int i = p(2,4); // 通过函数指针调用函数
printf("%dn", i);
}

31min
函数指针是指向函数的指针变量
void p(int,char) // 定义一个函数,函数名为p,参数为int和char类型,返回值为void类型
void (
p)(int,char*) // 定义一个指针,该指针指向函数。返回值为void,

}

二维数组的指针作为函数参数
void printarr2(const int (*p)[4],int m,int n){//mn分别是二维数组的第一个和第二个角标。通过const标识,保护函数不会改变数组中的值
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("p[%d][%d] = %dn", i,j,p[i][j]);
}
}
}
int main{
int buf[][4] = {{1,2,3,4},{5,6,7,8}};
printarr2(buf,sizeof(buf)/sizeof(buf[0]),sizeof(buf[0])/sizeof(int));
return 1;
} 33 min 18 s
--------------计算二维数组每一列的平均值----------------

include

int main(){
int p = malloc(sizeof(int)10); // 在堆中申请了10个int的大小
char p2 = malloc(sizeof(char)10);

memset(p,0,sizeof(int)*10);  // malloc申请的堆内存 ,在代码的操作上相当于数组
for(int i=0;i<10;i++){ 
    p[i] = i;  // 操纵数组
}

free(p) ; // 释放通过malloc申请的堆内存
free(p2);

}

  1. 不能将一个栈变量的地址作为函数的返回值,e因为函数结束后,栈变量被释放
    eg: int *geta(){
    int a = 10;
    return &a;
    }

  2. 但是可以把堆变量的地址作为函数返回值返回
    int geta(){
    int
    p = malloc(sizeof(int));
    return p;
    }

int main(){
int *p = geta();
malloc(p);
}

  1. 一个经典的错误模型:
    void getheap(int p){
    p = malloc(sizeof(int)
    10);
    }
    void main(){
    int *p = NULL;
    getheap(p); // 此处是错误的,因为函数的参数是值传递,虽然语义是getheap(p),但是mallo的内存地址只是付给了函数的形参,函数退出后,形参的值并不能传递给实参(指针的值也一样不能传递),导致p还是空指针,下面的p[0]=1发生空指针异常
    p[0] = 1;
    printf("%dn", p[0]);
    free(p);
    }

  2. 经典的正确模型:二级指针作为形参,对上面错误模型的改写
    void getheap(int **p){
    p = malloc(sizeof(int)10); // 所致地址号的内容,就是指以及指针的内容
    }
    void main(){
    int *p = NULL;
    getheap(&p); // 此处是错误的,因为函数的参数是值传递,虽然语义是getheap(p),但是mallo的内存地址只是付给了函数的形参,函数退出后,形参的值并不能传递给实参(指针的值也一样不能传递),导致p还是空指针,下面的p[0]=1发生空指针异常
    p[0] = 1;
    printf("%dn", p[0]);
    free(p);
    }


不能用变量声明一个数组,eg:int arr[i], 如果申请内存的大小靠程序运行期间决定,那么就要使用 malloc(sizeof(int)*i),要记得free
代码区和静态区的大小都是固定的,静态区是编译器根据代码提前申请的。堆和栈所占大小是动态,但是栈有一个操作系统规定的栈上线

cd /proc // 每个进程号都是一个文件
cd pid
cat maps // 查看内存映射,这里列出了代码段,堆,栈,静态区的使用情况(栈的预设范围)


堆的分配和
操作系统分配内存的单位不是字节,而是页。cat smps之后,发现堆有个项是内存页大小:4k。页太大,浪费的内存空间太大,但操作系统维护起来很简单,因为不用频繁的申请释放内存

malloc申请的堆内存上会存在旧数据,所以申请后需要用memset清空 : memset(p,p,sizeof(int)10)
这两句话的简写就是calloc,这样内存上全部是0
int main(){
char
p = calloc(10,sizeof(char)); // 申请大小是10*sizeof(char)
}
relloc用于扩展已经申请的堆内存,在原有内存上,增加连续的内存,如果没有连续空间可扩展,则会新分配一个连续空间,将原有内存拷贝到新空间,然后释放原有内存
但是relloc只申请,不打扫(内存中有旧数据)

rello(p,新的内存大小),.如果p为NULL,则realloc等于malloc,不指定分配空间的起始位置
void main(){
char p1 = calloc(10,sizeof(char));
char
p2 = realloc(p1,5); // p1指向的地址变为5
// realloc(NULL,5) = malloc(5)
}


结构体:


include

int main(){
char s[1024] = {0};
FILE *p = fopen("aaa.txt","r");
while(!feof(p)){ // 如果文件已经到最后,则文件返回真)
memset(s,0,sizeof(s));
fgets(s,sizeof(s),p); // 从p位置读取10个字节
printf("%s", s);
};

    fclose(p);
    return 0;

}

如果文件不存在,则新建文件,如果存在就追加文件内容
fopen("aaa.txt","a");

void syahello(); //提前声明,没有实现
int main(){
sayhello(); // 调用的函数要提前写出来,如果要写在后面,需要先在前面声明
}
void syahello(){
println("helloo");
}


include

本文由系统资讯发布,转载请注明来源:银河至尊官网网址调用的函数要提前写出来