求解:在这里的typedef是一种数据类型吗?那sqlist 和 sqlist L 分别表示啥东西?该程序的名字,类似宏吗

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求解:在这里的typedef是一种数据类型吗?那sqlist 和 sqlist L 分别表示啥东西?该程序的名字,类似宏吗相关的知识,希望对你有一定的参考价值。

const mansize =最多容量
typedef struct

datatype data[maxsize];
int last;
sqlist;
sqlist L;

typedef 是c++ 里相当于给变量类型取一个别名,不是一种数据类型哦。
sqlist 就是用typedef 给struct 取的一个别名,即sqlist就可以代替struct类型,可以用它来定义一个struct数据,因此下面的sqlist L; 这条语句就是定义一个struct 类型的数据L;

希望对你有所帮助,谢谢~追问

我的理解是:typedef struct sqlist
在这里,struct 变量类型经过定义了以后就 = sqlist
而下面的sqlist L = struct L;
而L又是 {
datatupe data[];
int last;
}的引用名
请问我理解得对吗?

追答

对的哦~
L就相当于一个struct的对象,然后L里含有data[] 和 last两个属性哦~

参考技术A

typedef是C中给已有类型起别名的机制(也可以是你自己定义的struct类型),语法是你正常定义一个某个类型的变量,比如int a,struct sqlist...b等等,前面加一个typedef关键字,就可以把这里的a,b当做你前面定义的int或者struct sqlist类型来使用了。

首先你要把语法弄明白,纯C中关于结构体struct,也就是你自己创建的数据类型,是分数据类型的名字和这种类型的变量的名字,只不过可以在声明struct类型的时候同时初始化一个变量,但是这两个名字不要混淆。

例如:

struct sqlist 
ElemType data[MaxSize];
int lenth;
;
以上这样写是创建了一个以sqlist为类型名的结构,也就是定义了新的数据类型,以后你想创建sqlist
变量时就可以写:
struct sqlist list;

这是一种方法。sqlist类型还可以这么创建:
struct
ElemType data[MaxSize];
int lenth;
sqlist;
这样写是创建了一个sqlist 变量 ,注意是变量,其实也创建了struct类型,只不过和上面的
区别是没有类型名,只有变量名sqlist,而上面的sqlist是类型名。这样写的话这个类型的结
构就只有sqlist这一个变量,以后也没法声明其他的,因为没有类型名。

第三个,这么写:
struct sqlist
ElemType data[MaxSize];
int lenth;
list;
相当于把上两个结合起来,即定义了一个sqlist类型,同时创建了一个sqlist类型的变量list。
之后也还是可以用struct sqlist list1,list2等等创建新的struct sqlist类型变量。

使用typedef的方法:
typedef struct
ElemType data[MaxSize];
int lenth;
sqlist;
就像上面说的语法,去掉typedef其实这里是创建一个sqlist变量,这个变量是一个结构,但
这个结构类型没有名字。加上typedef后代表sqlist就成为这个结构类型的别名,即实际上此
类型有了名字,只不过不是通过上面说的第一种方式创建的,效果一样。唯一不一样的是在以
后创建变量的时候:
struct sqlist list; //使用第一种方法
sqlist list; //使用typedef
看出来了吧,少写一个struct。。。。。。

最近也在学数据结构。。。你这个问题里的代码我们书上也是这么写,,但是实际上这里你不用typedef也是一样,就是说你直接创建一个新的类型struct sqlist也是一样的,只不过接下来你想要声明线性表的时候,按照C的语法必须用struct sqlist list这样的声明,需要多打一个struct关键字……

这主要是牵扯到C的语法的问题,最近还在学C++,C++中定义struct结构后创建结体变量时是不需要struct关键字的,所以其实就不需要typedef关键字来这么写了。。。

啰嗦了,主要是还是要先弄清基本语法,然后再谈实现,这可以说是最基础了。C的话推荐看看C Primer Plus,讲的十分细致。

typedef那回事儿

typedef是一种特殊的声明方式,不过它与普通声明(详见这里)的含义取大不相同。普通声明的主角是“变量”,它或是创建一个新变量或是对外文件变量使用前的声明;而typedef声明的主角则是“类型”,通过这个声明对一种数据类型引入新的名字。从引入新名字这个角度来说,typedef声明又和宏定义有些相似:用新名字代替已有的名字。不过,在本文接下来的叙述中你会看到这两者之间的区别。

typedef是特殊的

正如本文一开始所说的那样,typedef是特殊的声明。我们最常见以及常用的方式如下:

    /* 代码段1 */
    struct stuinfo
    {
        char id[20];
        char name[20];
        int age;
    };
    typedef struct stuinfo stu; /* 语句1 */

通过typedef声明为stuinfo结构体引入了一个新的名字stu。现在stuinfo结构和stu属于同一种数据类型,只不过两者在声明一个变量时使用的名字不同:

    /* 代码段2 */
    stu mystu1;
    struct stuinfo mystu2; /* 语句2 */

通过上述两个代码段,可以再一次的理解typedef声明和普通声明的区别。代码段1通过typedef声明为stuinfo引入了一个新的名字stu;而代码段2则通过同一种数据类型的不同名称分别声明了两个同类型的变量。注意到语句1和语句2,除了语句1在声明前多了typedef关键字外,两者在形式上几乎一样,因此都可以通过上文所述的声明规则进行阅读。正是由于typedef这个关键字,使得这两种声明的含义有着巨大差异。

其实,像上面的举例那样通过typedef声明而省去一个struct并没有多大的意义。使用typedef声明的最大优点是可以简洁的表达一个指针。比如ANSI C中的signal(),它的定义如下:

void ( *signal(int signum, void (*handler)(int)) ) (int);

考验你的时刻到了!你是否能快速说出这个声明的含义?

这个复杂的语句声明了signal函数,这个函数有两个参数signum和handler;signum参数是一个整型变量。handler是一个函数指针,指向一个拥有整型参数并且返回空值的函数;signal函数的返回值是一个函数指针,该指针同样指向一个拥有整型参数并且返回空值的函数。

对于这个复杂声明的解读的确很令人费劲。但是经过typedef的改进,它的阅读过程就简化了很多:

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

通过typedef的声明,使得sighandler_t是这样一种类型:它是一个函数指针,该函数拥有一个整型参数并且返回空值。第二条语句则声明了函数signal,它拥有两个参数signum和handler。并且这个函数的返回值和参数handler都是sighandler_t类型的。

虽然这样的声明在形式上简洁许多,不过和普通声明一样,此时阅读声明时仍然要记住声明符号的优先级规则。这种困扰在C语言中是难以避免的。

 

typedef int x和#define x int是不一样的

typedef和宏定义看似都是文本替换,但其实质不同。typedef表面上是对已有数据类型引入新名称,实则是对数据类型的严格封装。这种封装体现在下述两个方面。

首先,经过宏定义后的类型名可以进行再次扩展,但是经过typedef引入的类型名则不能进行扩充。比如:

    #define myint1 int
    unsigned myint1 x; /* 正确 */
    
    typedef int myint2;
    unsigned myint2 x; /* 语法错误! */

由于typedef是一种严格的数据封装,它只引入了myint2类型而没有引入unsigned myint2类型。也就是说,通过typedef的声明,编译器只能识别myint2类型。而unsigned myint2既不是基本类型也不是经过typedef声明过的类型,编译器就无法识别。

其次,在连续的几个变量声明中,使用typedef定义的类型能够保证所有变量均为相同类型,而用宏定义的变量则无法保证统一性。比如:

    #define myint1 int *
    myint1 x,y; /* 经过宏替换后为: int *x,y; */
    
    typedef int * myint2;
    myint2 x,y;
由于宏定义只是直接的文本替换,因此只能保证x是整型的指针变量而y为整型变量。而typedef定义过的类型myint2则是对int *的完全封装,所以x和y均为整型的指针变量。

 

C语言中的名字空间

在说明名字空间之前,请先阅读下面的代码:

    /*
     *Author: edsionte
     *Email:  [email protected]
     *Time:   2011/02/03
     */
    
    #include < stdio.h >
    #include < string.h >
    
    struct id
    {
        int id;
    }id;
    
    typedef struct name
    {
        char name[20];
    }name;
    
    struct name name1;
    name name2;
    
    int main()
    {
        id.id = 1;
        strcpy(name1.name,"hello,");
        strcpy(name2.name,"edsionte!");
        printf("id.id = %d, %s%s\n",id.id,name1.name,name2.name);
        return 0;
    }
    /* 运行结果 */
    [email protected]:~/code/expertC$ gcc tpdef.c -o tpdef
    [email protected]:~/code/expertC$ ./tpdef
    id.id = 1, hello,edsionte!

你可能已经发现在上述代码中出现了多个id和name,并且这样的代码可以成功的编译。这些相同的名字标签为何可以同时出现?每个标签代表什么含义?这些问题将是下面分析的重点。

以上述代码中10到13行的代码为例,这条语句中包含三个id标签。它们分别对应C语言中三种常见的名字空间:

  • 结构标签:这种标签用于结构体、联合体和枚举类型;struct后的id即为此类型的名字空间;
  • 成员名:每个结构体或联合体内部都与属于自己的名字空间;struct内部的成员id即为此类型;
  • 标签名:声明中的标示符;比如最后一个id,他是struct id类型的变量;

由于这三种标签所处的名字空间不同,因此它们可以同时存在。但是在同一个名字空间中不能出现多个同名的标签。常见的例子就是一个结构体内不可能出现同名的变量。

根据上面对名字空间的划分,15到18行的代码的解释为:struct后的name属于结构体标签;结构体内部的name属于成员名;而最后一个name属于声明的标示符;整条语句的含义是通过typedef声明将name结构体重命名为name。

通过上面对typedef的分析,你应该对于struct name和name均可以声明一个变量不再陌生。此处我们用名字空间的来理解他们的区别,20句中的name属于结构标签,21句中的name属于一种类型的名称。

上述同名的情况在日常的代码中实属罕见,这里只是为了说明名字空间而特别的举例。一般为了提高代码的可阅读性,最好对容易产生混淆的标签加上特别标记。比如VFS中inode和dentry结构体,两者内部均有flag一字段。尽管不同的结构体内有各自的名字空间,但是实际命名时仍然采用i_flag和d_flag。

有了上面的基础,本部分一开始所举例的代码也就可以轻松阅读了。

参考:

《C专家编程》 人民邮电出版社;(美)林登(LinDen.P.V.D) 著,徐波 译;

 

以上是关于求解:在这里的typedef是一种数据类型吗?那sqlist 和 sqlist L 分别表示啥东西?该程序的名字,类似宏吗的主要内容,如果未能解决你的问题,请参考以下文章

求解释python一行代码

typedef那回事儿

C/C++语言typedef的用法详解以及与define的区别

typedef enum FALSE , TRUE bool ; 求解意思

C语言typedef详解

数据结构基础-结构体struct及类型别名typedef的使用