1、题目
牛牛在学习C语言的预定义,他所知道的有方式有#define和typedef两种。请你选择一种方式声明int类型指针的同义字int_p,要求使用语句“ int_p p1, p2; ” 能够直接声明两个指针,将两个指针分别指向输入的数组首部m和n,并返回两个指针各自自增后的结果之和。
2、思路
(1)使用语句“ int_p p1, p2; ” 能够直接声明两个指针
(2)将两个指针分别指向输入的数组首部m和n
(3)自加并返回自加后指向的值的和
3、代码展示
//使用typedef表达
typedef int* int_p; //有逗号
int fun(int* m, int mLen, int* n, int nLen ) {
// write code here
int_p p1,p2; //两个都是指针类型
p1 = m;//m可以理解为数组名,是一个指向m[0]的指针,现在p1=m p1也指向m[0]
p2 = n;
p1++;//指向m[1]
p2++;
return ((*p1)+(*p2));
}
//使用define
#define int_p int* //没有逗号
int fun(int* m, int mLen, int* n, int nLen )
{
// write code here
int_p p1;
int_p p2;
p1 = m;
p2 = n;
p1++;
p2++;
return ((*p1)+(*p2));
}
但是有个问题是没有用上题目的mlen和nlen
所以修改代码如下
typedef int* int_p;
int fun(int* m, int mLen, int* n, int nLen ) {
// write code here
int_p p1, p2;
p1 = m, p2 = n;
mLen>1?p1++:p1, nLen>1?p2++:p2;
return ((*p1)+(*p2));
}
4、补充
tips:一个程序的运行过程,大致可分为:预处理->编译->程序执行。
typedef和define可对一个对象进行 取别名(typedef) 或 字符替换(define) ,以此增强程序的可读性
(1)typedef是关键字,有作用域限制(函数内部定义的话其他的函数就不能使用取的别名),对已经存在的数据类型取别名,而不是创造新的数据类型。
define是预处理指令(宏定义),只进行简单的字符替换,没有作用域限制,可以对类型/变量/常量等进行替换。
比如:
typedef char* pstr;
“const pstr”会被解释为“char* const”:不能更改指向的地址(常量指针)
//“const pstr”即const修饰char*类型,即char* const p
如果是#define pstr char*
“const pstr”则会被解读为const char*:(指针常量)指针指向一个常量,可以更改指向的地址,但地址里的内容是常量
//直接替换,不认类型
可以使用其他类型说明符对宏类型名进行扩展,但对 typedef 所定义的类型名却不能这样做。typedef理解为一个彻底的封装,声明之后就不能再往里面加东西。
#define INTERGE int
unsigned INTERGE n; //没问题
typedef int INTERGE;
unsigned INTERGE n; //错误,不能在 INTERGE 前面添加 unsigned
(2)typedef:它在自己的作用域内给一个已经存在的类型一个别名。它在编译时才进行处理
int main()
{
typedef int size;
size a=3; //等同于int a =3;
fun();
}
int fun()
{
size a=3; //报错 不在作用域了
}
(3)#define 是预处理指令。在预处理时就进行简单的替换
a.预处理:执行预处理指令,进行简单的替换(替换后删除预处理指令)。
#define a 3
int main()
{
printf("%d",a);
return 0;
}
等同于
int main()
{
printf("%d",3);
return 0;
}
注意此时程序还远远没有执行,只是编译器在执行预处理(比如我们用记事本写东西,假设可以发送,那么记事本先改正拼写,然后再提交给别人,记事本自我改正拼写的功能就是预处理)
显而易见,预处理仅是进行简单的字符替换,不作正确性检查,不管含义是否正确,直接替换,也没有数据类型一说。
当要替换的字符和定义的变量同名时就会产生定义冲突,如下:
#define a 3
int main()
{
int a=5;
printf("%d",a);
return 0;
}
//报错
b.编译:进行程序的语法检查,检查无错程序再执行,否则直接报错。
平时我们程序运行直接出错,实际就是编译检查出语法错误,如上的定义冲突错误。程序还没到执行的那一步。
所以define宏替换,可能带来的错误只有在编译时才可能发现并报错。
由上可知,define只是程序执行前的字符替换而已,不牵扯程序本身语法或者执行,因此想替换谁替换谁,也没有作用域一说,至于错误,那是编译时候检查的事情了
(4)在连续定义几个变量的时候,typedef 能够保证定义的所有变量均为同一类型,而 #define 则无法保证。
#define X int*
typedef int* Y
X p1, p2;
等同于int *p1,p2;//一个指针变量,一个整形变量
Y p1,p2; //两个都是指针变量
//int* 可以是一个类型,显然define把int当做类型,更印证的宏替换没有数据类型。
格式:typedef oldName newName;
格式:#define newname oldname
oldName 是类型原来的名字,newName 是类型新的名字
(5)使用到数组上。注意,数组也是有类型的。例如char a1[20];
定义了一个数组 a1,它的类型就是 char [20]。若:
typedef char ARRAY20[20];
则表示 ARRAY20 是类型char [20]
的别名。它是一个长度为 20 的数组类型。接着可以用 ARRAY20 定义数组:
ARRAY20 a1, a2, s1, s2;
等价于
char a1[20], a2[20], s1[20], s2[20];
(6)使用在结构体上
typedef struct stu{
char name[20];
int age;
char sex;
} STU;
STU 是 struct stu 的别名,可以用 STU 定义结构体变量:
STU body1,body2;
等价于:
struct stu body1, body2;