IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 从 typedef struct T *T 看C语言的命名空间 -> 正文阅读

[C++知识库]从 typedef struct T *T 看C语言的命名空间

最近在看《C语言接口与实现》一书. 第二章提到, 一个ADT(抽象数据类型)就是一个借口, 其标准范例是栈. 其接口定义如下所示:

//stack.h
#ifndef STACK_INCLUDED
#define STACK_INCLUDED


#define T Stack_T
typedef struct T *T;

extern T    Stack_new   (void);
extern int  Stack_empty (T stk);
extern void Stack_push  (T stk, void* x);
extern void*Stack_top   (T stk);
extern void*Stack_pop   (T stk);
extern void Stack_free  (T* stk);

#undef T
#endif

众所周知宏定义的作用仅仅是一个替换而已, 因此typedef这句话实际为:

typedef struct Stack_T *Stack_T;

按照书上说法,?Stack_T对外接口表现为一个“不透明指针”. 我起初理解是, 以后凡是看到Stack_T的地方实际指代的都是指针Stack_T*. 乍看起来这种理解没错, 但看一下栈的实现后, 便发生了理解不能的事情:

//stack.c
#include <stddef.h>
#include "assert.h"
#include "mem.h"
#include "stack.h"

#define T Stack_T

struct T {
    int count;
    struct elem {
        void* x;
        struct elem* link;
    }* head;
};

T Stack_new(void) {
    T stk;

    NEW(stk);
    stk->count = 0;
    stk->head = NULL;
    return stk;
}

int Stack_empty(T stk) {
    assert(stk);
    return stk->count == 0;
}

void Stack_push(T stk, void* x) {
    struct elem* t;

    assert(stk);
    NEW(t);
    t->x = x;
    t->link = stk->head;
    stk->head = t;
    stk->count++;
}

...

这里#define 指令又把T定义为Stack_T的缩写. 问题来了,? 以下结构体的定义和分配并初始化一个结构体函数中的Stack_T分别指什么呢:

struct Stack_T {
    ...
};

Stack_T Stack_new(void) {
    Stack_T stk;

    NEW(stk);
    ...
    return stk;
}

如果按照上述理解?Stack_T 指代的就是指针 Stack_T*, 显然没有这种定义式无法通过编译:?struct?Stack_T*. 函数返回类型和结构体名称的重名令人困惑, 但这确实是合法而正规的.

究其根本原因是, struct后面的 Stack_T 和 函数的返回类型?Stack_T 不是同一个东西. 这就牵扯到C语言的命名空间约定(不同于C++的namespace, 是个全局的区分C语言标识符的约定):

1) 预处理器宏名
2) 语句标签(goto类型)
3) 结构、枚举、联合结构的标签(结构,联合和枚举的名称)
4) 成员名
5) 其他名称 包括变量名、函数名、typedef名称和枚举常量

因此struct后面的 Stack_T 属于 3), 而函数返回类型的 Stack_T 属于 5), 两者并不冲突. 即前者是个名为Stack_T 结构体的标签, 后者是个typedef的名称, 实际类型式?Stack_T* . 这里我对typedef的Stack_T 重新用 Stack_P 命名下, 上述代码就看的比较清楚了:

//stack.h
#ifndef STACK_INCLUDED
#define STACK_INCLUDED


typedef struct Stack_T* Stack_P;

extern Stack_P    Stack_new   (void);
extern int  Stack_empty (Stack_P stk);
extern void Stack_push  (Stack_P stk, void* x);
extern void*Stack_top   (Stack_P stk);
extern void*Stack_pop   (Stack_P stk);
extern void Stack_free  (Stack_P* stk);

//#undef T
#endif
//stack.c
#include <stddef.h>
#include "assert.h"
#include "mem.h"
#include "stack.h"


struct Stack_T {
    int count;
    struct elem {
        void* x;
        struct elem* link;
    }* head;
};

Stack_P Stack_new(void) {
    Stack_P stk;

    NEW(stk);
    stk->count = 0;
    stk->head = NULL;
    return stk;
}

int Stack_empty(Stack_P stk) {
    assert(stk);
    return stk->count == 0;
}

void Stack_push(Stack_P stk, void* x) {
    struct elem* t;

    assert(stk);
    NEW(t);
    t->x = x;
    t->link = stk->head;
    stk->head = t;
    stk->count++;
}

...

?这种 typedef struct T *T 其实C语言接口库中比较标准的写法, 值得引起借鉴和学习.

参考:
C Namespaceshttps://www.spinellis.gr/cscout/doc/name.html
也谈C语言标识符的NAMESPACE | Tony Baihttps://tonybai.com/2008/05/15/also-talk-about-namespace-in-c

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 22:37:15  更:2022-07-04 22:37:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:55:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码