C语言中的typedef(包含与#define的区别)

2024-06-08 13:48
文章标签 语言 区别 define typedef

本文主要是介绍C语言中的typedef(包含与#define的区别),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天在做一个编程练习的时候,想要使用链表,使用链表嘛就像使用以下typedef来定义以下链表节点,忽然感觉自己把typedef这个关键字给忘掉了,所以写这篇文章回忆以下N多年前用过的typedef

注:这部分内容中主要的内容来自百度百科typedef,还有一部分是自己的理解

简介:

typedef这个是关键字是用来为复杂的结构体或者类型定义简单的别名的关键字,注意加黑的部分,我觉得这个是理解这个结构体的关键。说白了就是赶脚一个东西太复杂比如一个人叫:尼古拉·阿列克谢耶维奇.奥斯特洛夫斯基,这么长你让谁去记下来。好吧来个简单的吧,typedef 尼古拉·阿列克谢耶维奇.奥斯特洛夫斯基  尼.阿.奥,我们就约定好了,以后一旦提到尼.阿.奥就是那个写炼钢技术的那个人。


基本用法:

(1)首先来看一下一个例子

    typedef int size,这个很简单呀,意思就是说:来吧我们给int 类型起个别名,就喊它叫size吧,说到这里我们在看一下宏定义的用法

    #define size int  这个意思就说嘿,编译器,如果你以后看到size 这个东西你就把他替换成为int就行了,注意这个里面的关键字是替换,到这里心底不禁悠然升起一个疑问,这两个意思不是一样吗?只不过一个放在前面,一个放在后面而已,真的一样吗?当然不一样,往后面看就知道了

    (2)当然了,两个都可以来掩饰一些符合类型,这个是什么意思呢?例如:

     typedef char* c_ptr;   #define c_ptr char*;这两个都可以把一种类型的指针实现定义好,以后我们可以简单直接的用这两个来定义一些指针

    (3)另外一个功能就是#define所没有的功能,这个就是可以掩饰符合类型,例如指针和数组

      char line[81]; char text[81];

      我们可以定义 typedef char Line[81];以后可以用Line text,line来定义和前面相同的数组。这个可是宏定义中没有的呀。

  (4)百度百科上还有一个提醒说在使用typedef的时候会有一个陷阱

   标准函数 strcmp()有两个‘ const char *'类型的参数。因此,它可能会误导人们像下面这样声明 mystrcmp(const pstr p1,const pstr p2):

  有些编译器会把const pstr 解释成为char *const;刚开始我一直想不明白这是为什么,后来想想,这个的确是的哈,因为使用typedef会将pstr当成一种类型来看,而我们知道const本来是可以穿过类型的,就是说const char p和char const p;其实是一样的,这样就好理解了,其实我倒是想在这里如果我们使用#define来定义的话应该就不会出错了。

     语言用法:

(1)

typedef struct tagNode
{
char *pItem;
pNode pNext;
} *pNode;
这个定义貌似很眼熟呀,我们在定义链表的是会经常用到这种方法来定义。但是编译器会报错,为什么呢?因为在定义的过程中pNext是一个指向pNode类型的指针,而我们这个pNode还没有定义完呢,现在使用当然会出错啦。解决方法如下:
1)
typedef struct tagNode
{
char *pItem;
struct tagNode *pNext;
} *pNode;
2)
typedef struct tagNode *pNode;
struct tagNode
{
char *pItem;
pNode pNext;
};
3)规范做法
struct tagNode
{
char *pItem;
struct tagNode *pNext;
};
typedef struct tagNode *pNode;
(2)还是要提一下typedef和#define的区别,前面说过一些,其实我觉得只要能够理解了typedef是起了一个别名,而#define只是简单地替换掉话应该很容易就能够理解下面的东西
typedef char * pStr1;
#define pStr2 char *
pStr1 s1, s2;
pStr2 s3, s4;
在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们所预期的指针变量
#define f(x) x*x
main( )
{
int a=6,b=2,c;
c=f(a) / f(b);
printf ( "%d \\n" ,c);
}
以下程序的输出结果是: 36
因为如此原因,在许多C语言编程规范中提到使用#define定义时,如果定义中包含表达式,必须使用括号,则上述定义应该如下定义才对:
#define f(x) ((x)*(x))
(3)
typedef & #define的另一例
下面的代码中编译器会报一个错误,你知道是哪个语句错了吗?
typedef char * pStr;
char string[4] = "abc" ;
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;
这个种问题出在p2++,因为我们其实前面提过,通过typedef来定义的是一个类型,而我们知道const是可以穿透类型的。所以问题也就明白了,这里如果看不明白的话可以参见const关键字
(4)总结
当然typedef和#define都能够存在,那么他们必然有存在的理由,下面就总结一下两者之间各自的优点
1) #define宏定义可以使用#ifdef和#ifndef来进行逻辑判断,还可以通过undef来取消。这个当然就是typedef没有的啦
2)typedef的特别长处就是它符合范围规则,使用typedef定义的变量类型的作用范围限制在函数或者文件内(这个取决于变量定义的位置),这个应该很好理解,百科后面还有一些关于和回调函数相关的东西就不说了,就写到这里吧,现在太难受了,感冒了今天。

这篇关于C语言中的typedef(包含与#define的区别)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1042365

相关文章

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

C# Semaphore与SemaphoreSlim区别小结

《C#Semaphore与SemaphoreSlim区别小结》本文主要介绍了C#Semaphore与SemaphoreSlim区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录一、核心区别概览二、详细对比说明1.跨进程支持2.异步支持(关键区别!)3.性能差异4.API 差

C语言逗号运算符和逗号表达式的使用小结

《C语言逗号运算符和逗号表达式的使用小结》本文详细介绍了C语言中的逗号运算符和逗号表达式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习... 在C语言中逗号“,”也是一种运算符,称为逗号运算符。 其功能是把两个表达式连接其一般形式为:表达

Go语言实现桥接模式

《Go语言实现桥接模式》桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化,本文就来介绍一下了Go语言实现桥接模式,感兴趣的可以了解一下... 目录简介核心概念为什么使用桥接模式?应用场景案例分析步骤一:定义实现接口步骤二:创建具体实现类步骤三:定义抽象类步骤四:创建扩展抽象类步

GO语言实现串口简单通讯

《GO语言实现串口简单通讯》本文分享了使用Go语言进行串口通讯的实践过程,详细介绍了串口配置、数据发送与接收的代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录背景串口通讯代码代码块分解解析完整代码运行结果背景最近再学习 go 语言,在某宝用5块钱买了个

Java中自旋锁与CAS机制的深层关系与区别

《Java中自旋锁与CAS机制的深层关系与区别》CAS算法即比较并替换,是一种实现并发编程时常用到的算法,Java并发包中的很多类都使用了CAS算法,:本文主要介绍Java中自旋锁与CAS机制深层... 目录1. 引言2. 比较并交换 (Compare-and-Swap, CAS) 核心原理2.1 CAS

GO语言zap日志库理解和使用方法示例

《GO语言zap日志库理解和使用方法示例》Zap是一个高性能、结构化日志库,专为Go语言设计,它由Uber开源,并且在Go社区中非常受欢迎,:本文主要介绍GO语言zap日志库理解和使用方法的相关资... 目录1. zap日志库介绍2.安装zap库3.配置日志记录器3.1 Logger3.2 Sugared

Go语言中如何进行数据库查询操作

《Go语言中如何进行数据库查询操作》在Go语言中,与数据库交互通常通过使用数据库驱动来实现,Go语言支持多种数据库,如MySQL、PostgreSQL、SQLite等,每种数据库都有其对应的官方或第三... 查询函数QueryRow和Query详细对比特性QueryRowQuery返回值数量1个:*sql

GO语言中gox交叉编译的实现

《GO语言中gox交叉编译的实现》本文主要介绍了GO语言中gox交叉编译的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录一、安装二、使用三、遇到的问题1、开启CGO2、修改环境变量最近在工作中使用GO语言进行编码开发,因

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础