C语言基础知识之五

xiaoxiao2021-02-28  109

函数指针

int *a; //定义变量,a是整型指针变量 int a(); //定义函数,a是函数,返回值为int int * a(); /定义函数,a是函数,返回值为int* int *a[10]; //定义变量,a是数组,存放10单元整型指针的数组 int (*a)[10]; //定义变量,a是指针,指向10个数组单元的指针 int (*a)(); //定义函数,a是指针,指向函数的指针,返回值为int

1.函数代码存储空间的起始地址(又称入口地址)称为这个函数的指针。 如:

int (* p)( int ,int );

这是定义一个指向函数的指针变量,指针变量p的返回值类型是整型,并且这个函数有两个整型参数。 2.用函数指针变量调用函数 举例:

int Max(int a,int b) { return a>b?a:b; } int main() { int a=5; int b=3; //int c=Max(a,b); //1)通过函数名调用Max函数 //printf("%d\n",c); int (*p)(int ,int ); //定义指向函数的指针变量p, //只需要说明p的返回值是整型且有两个整型参数就行,即只指明int,用int x也可以 p=Max; //使p指向Max函数首地址, p=&Max也可以 //int c=(*p)(a,b); //2)通过指针变量调用Max函数 printf("%d\n",p(a,b)); //printf("%d\n",(*p)(a,b));也可以 return 0; }

3.定义和使用指向函数的指针变量

形式:类型名 (*指针变量名)(函数参数表列); 如: int (*p)(int ,int ); 说明: (1)定义指向函数的指针变量,只能指向在定义时指定的那个类型的函数,如int (*p)(int ,int);是属于一个整型返回值,两个整型变量的参数的类型。即函数指针指向一个函数族 (2)如果指针调用函数,必须使指针指向该函数,如 p=Max; (3)在给函数指针变量赋值时,只给出函数名不必给出参数 如:p=Max; //将函数入口地址赋给p (4)函数指针调用函数时,只需用(*p)代替函数名即可 (5)指向函数的指针变量不能进行算术运算 (6)函数名调用函数,只能调用指定的某一个函数;而指针变量调用函数,可以根据不同的情况先后调用不同的函数。

结构体

C语言允许用户自己建立有不同类型数据组成的组合型的数据结构,它称为结构体。 1.结构体类型形式: struct 结构体名 { 类型名 成员名; }; 2.结构体中可以使用的类型: (1)基本数据类型 (2)前面已经定义好的结构体 (3)结构体本身的指针

//以下是举例,不是具有功能的完整代码 #include<stdio.h> #include<string.h> struct Student //struct Student是类型名,student是结构体名 { char name[20]; int age; }; struct A { int a; //char a;//error,不能同名 char b; }; struct B { int c; //(1) struct A sa; //(2) //struct B sb; //error,因为不知道sb的内存大小 struct B *pb; //OK,因为指针为4个字节,已知 (3) }; struct C { struct A c; int a;//此处的结构体名称a与结构体A中的a不在一个级别,不冲突 }; int main() { struct Student stu1={"liubei",30}; struct Student stu2; stu2=stu1; //同类的结构体变量可以互相赋值 //stu2.name="caocao";//error 不能直接将字符串常量赋给字符数组 strcpy(stu2.name,"caocao");//ok,用字符串拷贝函数 printf("%s,%d\n%s\n",stu1.name,stu1.age,stu2.name); struct C sc; sc.c.a=10; sc.a=100;//a不冲突,因为等级不同 printf("%d.%d\n",sc.c.a,sc.a); return 0; }

3.定义结构体类型变量 (1)先声明结构体类型,再定义该类型的变量 如:

struct Student { char name [20]; int age; }; int main() { struct Student stu1; struct Student *p; return 0; }

(2)在声明类型的同时定义变量

struct Student {char name[20]; int age; };stu1;

4.访问成员的方式:(1)结构体普通变量通过 · 访问成员;(2)结构体指针变量通过->访问成员

struct A { int a; int *p; }; struct B { struct A c; struct A *d; int e; int *f; }; struct Student { char name[20]; int age; }; int main() { struct B bb; struct B *pb; bb.c.a; //访问成员 bb.c.p; bb.d->a; bb.d->p; bb.e; bb.f; pb->c.a;//或(*pb).c.a (*pb)是对pb进行解引用,不过用起来麻烦,使用较少 pb->c.p; pb->d->a; pb->d->p; pb->e; pb->f; struct Student stu1={"liubei"};//聚合类型(数组和结构体)只初始化一部分时,其余部分默认为0,此处即age=0 stu1.age=33;//修改stu1的年龄为33 struct Student *ps=&stu1; (*ps).age=28;//或ps->age=28;比较常用 //指向符->和[]自带解引用 }

区分函数调用与函数声明的方法:函数声明有数据类型,函数调用没有数据类型 在C语言中,调用不带参数的函数,如 Student stu1(); 在C++中,调用不带参数的函数,如 Student stu1; //c++没有参数的时候不用带括号 在C语言中,结构体关键字struct在调用时不可以省略; 在C++中,结构体关键字struct在调用时可以省略;

struct A { int a; A() { printf("haha "); } A(int x) { a=x; printf("A(int x)\n"); } }; int main() { A aa; //c++没有参数的时候不用带括号 A bb(3); return 0; }

打印结果: haha A(int x)

用typedef声明新类型名

typedef是关键字,作用是类型重定义,即给类型取个别名 如:typedef unsigned longlong uint64;即给unsigned long long类型取个别名叫uint64 1.用一个别名代替复杂的类型名 (1)用别名代替结构体类型 typedef struct Student Student;    //Student是别名

即:

typedef  struct Student { char name[20]; int age; }Student;   //Student为新的类型名(别名),代替typedef  struct Student{code}

用typedef声明后再去定义变量时不需要再写类型名struct Student,如直接定义为Student sa; (2)用别名代替数组类型 typedef int Num[20];    //声明Num为整型数组类型名 Num  a;    //定义整型数组a (3)用别名代替指针类型 typedef int * p;    //声明p为整型指针类型 p a[10];    //a是指针数组 (4)用别名代替指向函数的指针类型 typedef int (* pfun)(int ,int);   //pfun是函数指针类型,该函数返回整型值 pfun p;    //p为函数指针类型

归纳  声明新类型名的方法: 按定义变量的方式,把变量名换上新类型名,并且在最前面加上typedef,就声明了新类型名代替原来的类型。

typedef 与#define

typedef int * Pint;//重定义类型 # define PINT int *//字符替换 int main() {     Pint d,e;    //d为指针,e为指针     PINT f,h;//int *f,h,故f为指针,h为int型 }

typedef 是类型重定义,在编译阶段有效,有类检查功能,有自己的作用域 # define 作用是字符替换,是预编译命令,没有检查功能,没有作用域的限制

转载请注明原文地址: https://www.6miu.com/read-66262.html

最新回复(0)