1、typedef的基本使用
#include <stdio.h>
/*
1.作用:给已经存在的类型起一个新的名称
2.使用场合
1>基本数据类型
2>指针
3>结构体
4>枚举
5>指向函数的指针
*/
//*******************************************
typedef int MyInt; // 可以为int起一个别名MyInt
typedef MyInt MyInt2; //还可以为MyInt再起一个别名MyInt2
//*******************************************
// 给指针类型char *起一个新的类型名称string
typedef char* string;
//*******************************************
/*
struct student
{
int age;
};
typedef struct student MyStu;
*/
typedef struct student
{
int age;
}MyStu;
/*也可以,但是struct student stu = {20};不能使用
typedef struct
{
int age;
}MyStu;
*/
//*******************************************
/*
enum sex {man, woman};
typedef enum sex MySex;
*/
typedef enum sex
{
man,
woman
} MySex;
/*
typedef enum
{
man,
woman
} MySex;
*/
//**************************************
typedef int (*MyPoint)(int, int);
int minus(int a, int b)
{
return a - b;
}
int sum(int a, int b)
{
return a + b;
}
//***************************************
/*
struct person
{
int age;
};
typedef struct person* personpoint;
*/
typedef struct person
{
int age;
}* personpoint;
//***************************************
int main()
{
//***************************************
struct student stu = {20};
MyStu stu2 = {21};
//***************************************
enum sex s = man;
MySex s1 = woman;
//***************************************
/*
int (*p)(int, int) = sum;
int (*p2)(int, int) = minus;
p(10, 12);
*/
MyPoint p = sum;
MyPoint p2 = minus;
int sum = p(10, 12);
printf("sum = %d\n", sum); // 输出结果为22
//***************************************
struct person per = {20};
struct person* per2 = &per;
personpoint per3 = &per;
//***************************************
return 0;
}
//***************************************
void test2()
{
char* name = "jack";
string name2 = "jack";
printf("%s\n",name2);
}
//***************************************
void test()
{
/*也可以放到函数内,只是作用域范围变小,只在main函数内起作用,自定义的一般都有作用域
typedef int MyInt;
typedef MyInt MyInt2;
*/
int a;
MyInt i = 10;
MyInt2 c = 20;
printf("c is %d\n", c); // 输出结果为20
}
//***************************************
2、typedef使用注意点
#include <stdio.h>
// 预处理指令不需要写分号“;”,其他语句都要写分号“;”
#define Integer int
//typedef int Integer
typedef char* String;
#define String2 char*
int main()
{
int i = 10;
Integer j = 20;
/*
int a, b;
int a;
int b;
*/
//s1、s2 都是char*指针
String s1, s2;
/*
String s1;
String s2;
char * s1;
char * s2;
*/
s1 = "jack";
s2 = "rose";
//s3才是char*指针,s4只是char
String2 s3, s4;
/*
char* s3, s4;
char* s3;
char s4;
*/
s3 = "jack";
return 0;
}
3、关键字static和extern对函数的作用
/***************************************************
main.c文件
****************************************************/
#include <stdio.h>
/*
函数类型
外部函数:定义的函数能被本文件和其他文件访问调用,默认情况下所有函数都是外部函数
1> 默认情况下所有函数都是外部函数
2> 不允许有同名的外部函数
内部函数:定义的函数只能被本文件访问,其他文件不能访问
1> 允许不同文件中有同名的内部函数
static对函数的作用:
1> 定义一个内部函数
2> 声明一个内部函数
extern对函数的作用:
1> 完整地定义一个外部函数
2> 完整地声明一个外部函数
(extern可以省略,默认情况下声明和定义的函数都是外部函数)
*/
//调用一个函数,首先要声明,此处不再写头文件了,直接在源程序文件中声明,如下
// 声明一个test函数
// 完整地声明一个外部函数,默认情况下都是外部函数,所以extern又可以省略
//extern void test();
void test();
// extern的作用:定义一个外部函数,声明一个外部函数
// static的作用:定义一个内部函数,声明一个内部函数,不可省略
//void test2();
int main()
{
test();
//test2(); // 调用失败,因为这个函数是内部函数,但可以间接调用内部函数
return 0;
}
/*不可以,因为这个外部函数已经在one.c中定义过了,会造成重复定义的错误
void test()
{
}
*/
/*这个可以,虽然和one.c文件中的test2()一样,但他们是内部函数,作用域不冲突
static void test2()
{
}
*/
/*****************************************************
one.c文件
*****************************************************/
#include <stdio.h>
//这一句不能删,不然有警告,因为下面调用了printf()函数
//完整地定义一个外部函数如下,但是默认情况下所有函数都是外部函数,所以extern可以省略
/*
extern void test()
{
printf("调用了test函数\n");
}*/
//声明一个内部函数
static void test2();
/*
void test()
{
printf("调用了test函数\n");
}
*/
void test()
{
test2(); //这样实现了间接调用内部函数
printf("调用了test函数\n");
}
// 定义一个内部函数
static void test2()
{
printf("调用了test2函数\n");
}
4、关键字static和extern对全局变量的作用
/***************************************************
main.c文件
****************************************************/
#include <stdio.h>
/*
全局变量分2种:
1> 外部变量:定义的变量能被本文件和其他文件访问调用
@1 默认情况下,所有的全局变量都是外部变量
@2 不同文件中的同名外部变量,都代表着同一个变量
2> 内部变量:定义的变量只能被本文件访问,不能被其他文件访问
@1 不同文件中的同名内部变量,互不影响
static对全局变量的作用:
定义一个内部变量
extern对全局变量的作用:
声明一个外部变量
static对函数的作用:
定义和声明一个内部函数
extern对函数的作用:
完整定义和声明一个外部函数(extern可以省略)
*/
void test();
// 定义一个外部变量,不要extern int a;这种形式不是定义
int a;//与one.c文件中的int a;因为变量名一样,占据同一存储空间,不再是什么就近原则
int a;
int a;//这么多个a都是代表同一个a
int a;//不会报错,变量名一样代表是同一内存存储空间;
// C语言的封装性差,安全性差,容易被外部文件修改,
// static作用:定义一个内部变量
static int c;
// extern作用:声明一个外部变量
// extern int a;
int main()
{
c = 10;
a = 10;
int b;
//int b;//会报错,因为重复定义
printf("a == %d\n", a);
printf("&a == %p\n", &a);
test();
printf("a == %d\n", a);
return 0;
}
int a;
/*
// extern作用:声明一个外部变量
extern int a;
// int a; 也可以省略extern
void haha();//函数声明放到外面
int main()
{
// extern int a; 声明也可以放到这,类似函数的声明,但是extern就不能省略了,否则就成了定义一个新的局部变量了int a;
a = 10; // 会报错,因为还没定义就使用,可以像函数声明一样,声明一下定义在下面的变量int a;形式为extern int a;这样就能使用a这个变量了;
printf("a == %d\n", a);
void haha();// 函数声明放到函数里面
haha();
return 0;
}
int a;
void haha()
{}
*/
/*****************************************************
one.c文件
*****************************************************/
#include <stdio.h>
int a;
int c; // 全局变量默认值为0,
// static int c;
void test()
{
printf("c == %d\n", c);// 输出为0,而不是10,就算在声明时前面加上static,static int c; 结果还是0
printf("a的值是%d\n", a);
printf("a的存储地址值是%p\n", &a);
a = 20;
}
5、关键字static对局部变量的作用
#include <stdio.h>
/*
static修饰局部变量的使用场合:
1.如果某个函数的调用频率特别高
2.这个函数内部的某个变量值是固定不变的。
*/
void test()
{
// static的使用,提高性能
static double pi = 3.14; // 因为pi的值不变,当这个函数被调用多次时,不用每次分配内存,然后再释放,
double zhouchang = 2 * pi *10;
int a = 0;//当test函数调用结束后,释放a内存,下次调用时从新分配,从新赋值。
a++;
printf("a == %d\n", a);
/*
static修饰局部变量:
1> 延长局部变量的生命周期:程序结束的时候,局部变量才会被销毁
2> 并没有改变局部变量的作用域
3> 所有的test函数都共享着一个变量b
*/
static int b = 0;//第二次调用时,不再重新分配存储空间,保留第一次调用后b的值,之后以此类推
b++;
printf("b == %d\n", b);
}
int main()
{
test();
test();
test();
return 0;
}