EP6 嵌入式连续申明的指针

文章讨论了在C语言中typedef和#define两种预定义方式的使用,特别是在声明指针类型别名和处理数组及结构体时的应用。通过代码示例展示了如何声明和使用int_p指针类型,并分析了typedef和#define在类型别名、作用域和类型安全性等方面的不同。此外,提到了预处理、编译过程以及typedef和#define在处理连续变量定义时的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值