摘自【你必须知道的495个c语言问题】

本文深入探讨了C语言中typedef和#define的区别、结构指针定义的常见错误及解决办法、相互引用结构的定义方法,以及复杂类型声明的理解与实现。详细解释了typedef、指针、结构体在C语言中的应用,包括如何正确使用typedef定义类型、避免结构体自我引用的误区、相互引用结构的正确声明方式,并通过实例展示了如何理解并实现复杂的C语言声明。

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

英文链接:http://c-faq.com

1、对于用户定义类型,typedef#define有什么区别?

typedef char *String_t;
#define String_d char *
String_t s1, s2;
String_d s3, s4;

s1、s2、s3都被定义成了char*,但s4却被定义成了char型。这可能并非原来所希望的。

#define也有它的优点,因为可以在其中使用#ifdef。另一方面,typedef具有遵守作用域规则的优点(也就是说,它可以在一个函数或块内声明)


2、我似乎不能成功定义一个链表。我试过

typedef struct {
    char *item;
    NODEPTR next;
} *NODEPTR;

但是编译器报了错误信息。难道在C语言中结构不能包含指向自己的指针吗?

答案肯定是可以的,这里的问题在于typedef,typedef定义了一个新的类型名称,不能在定义typedef类型之前使用它。

可以修改成:

typedef struct node {
    char *item;
    struct node *next;
}*NODEPTR;
或者:
struct node;
typedef struct node *NODEPTR;
struct node{
    char *item;
    NODEPTR next;
}

使用哪种方式不过是个风格问题。


3、有了上面的基础,那么如何定义一个相互引用的结构呢,比如:

typedef struct{
    int afield;
    BPTR bpointer;
} *APTR;

typedef struct {
    int bfield;
    APTR apointer;
} *BPTR;
但是编译器在遇到第一次使用BPTR的时候,它还没有定义。

同样两种方法:

struct a{
    int afield;
    struct b *bpointer;
};

struct b{
    int bfield;
    struct a *apointer;
}
或者:
struct a;
struct b;
typedef struct a *APTR;
typedef struct b *BPTR;

struct  a{
    int afield;
    BPTR bpointer;
};

struct b{
    int bfield;
    APTR apointer;
};

4、有技术的来了,“typedef  int  (*funcptr)();”  是什么意思?

它定义了一个类型为funcptr, 表示指向返回值为int弄(参数未指明)的函数的指针。它可以用来声明一个或多个函数指针。

    funcptr fp1, fp2;

这个声明等介于以下这种更冗长而且可以更难理解的写法:

int (*pf1)(), (*pf2)();


5、【不是每个人都能理解的声明】怎样建立和理解非常复杂的声明?例如定义一个包含N个指向返回指向字符的指针的函数的指针的数组?

至少有以下两种答案:

char  * ( * ( * a[N] ) () )();

typedef char *pc;       /* pointer to char */
typedef pc   fpc();     /* fuction returning pointer to char */
typedef fpc *pfpc;      /* pointer to above */
typedef pfpc  fpfpc();  /* function returning...*/
typedef fpfpc *pfpfpc;  /* pointer to...*/
pfpfpc a[N];            /* array of ....*/

C语言中的声明令人困惑的原因在于,它们由两个部分组成:基本类型和声明符,后者包含了被声明的标识符(即名称)。声明符也可以包含字符*、[]和(),表明这个名称是基本类型的指针、数组以及为返回类型的函数或者某种组合。例如,在

char *p;

中,基本类型是char , 标识符是pc, 声明符是*pc;这表明*pc是一个char。解读复杂C声明一种方法是遵循“从内到外”的阅读方法,并谨记[ ]和()比*的结合度更紧。

例如,对于声明char *(*pfpc )();

我们可以看出pfpc是一个函数(从()看出)的指针(从内部的*看出),面函数则返回char型的指针(从外部的*可以看出)。当我们后来使用pfpc的时候。

另一种分析这种复杂声明的方法是,遵循“声明模仿使用”的原则逐步分解声明:

*(*pfpc)()    是一个      char

(*pfpc)()      是一个     指向char的指针

(*pfpc)         是一个     返回char型指针的函数指针

pfpc             是一个     指向返回char型指针的函数的指针


6、


未完待更新...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值