如何读懂 C 语言复杂的声明

    如何读懂 C 语言复杂的声明

作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢!


参考<<C专家编程>>

废话

虽说 C 语言相比于其他更高级的语言来讲,有着非常精简的语法结构,对于初学者非常的友好。 然而,使用 C 语言依然可以可以写出非常难懂的代码, 也许这也就是精简的语法所必须面对的缺点吧。 笔者就经常一些复杂的声明,看得一头雾水,这里就分享一个帮你读懂这些声明的技巧吧。

自测

先自己测试一下, 如下的声明你能读懂吗?

void (*signal(int sig, void(*func)(int))) (int); // 当然,比这个复杂的声明还有很多...

技巧

要读懂一个声明,必须要懂得其中的优先级规则

优先级规则如下:

A: 声明从它的名字开始读起, 然后按照优先级顺序依次读取
B: 优先级从高到低依次是:
    B.1: 声明中括号括起来的部分
    B.2: 后缀操作符:
        括号 () 表示这是一个函数
        方括号 [] 表示这是一个数组
    B.3: 前缀操作符: 星号 * 表示 “指向…的指针”
C: 如果 const 和 ( 或 ) volatile 关键字的后边紧跟类型说明符(如 long 等), 那么它作用于类型说明符。
    在其他情况下,const 和 ( 或 ) volatile 关键字作用于它左边紧邻的指针星号

示例

例1:

char * const *(*next)();
  1. 首先,变量名为 next
  2. 这里优先级最高的就是括号了。 括号中 \*next 为一个整体,具有最高优先级。 由 B.3 可以得知 "next 是一个指向 ... 的指针"
  3. 除括号外,最高优先级为后缀操作符,这里有括号紧跟着 (\*next)。 由 B.2 可知 "next 是一个函数指针,被指向的函数没有输入参数, 返回值还需要进一步分析"
  4. 接下来最高优先级的结构应该是 (\*next) 的前缀操作符------星号\*。 这里需要进一步分析更前面的结构
  5. 最后,我们应该将 "char \* const \*" 解释为一个结构。 由 C 可知它的意义为 "指向字符的常量指针"

总结,这个声明的含义为: next 是一个函数指针, 该函数指针指向的函数无输入参数且返回一个指向字符的常量指针

例2:

void (*signal(int sig, void(*func)(int))) (int); // 当然,比这个复杂的声明还有很多...

这就是我们前面提到的声明,我们来试着分析一下。

  1. 首先,变量名是 signal
  2. 其次就是括号了。 括号中 (\*signal(int sig, void(\*func)(int))) 为一个整体。 signal 前有星号,它的意义是 "signal 是一个指向 ... 的指针"
    1. 接着 signal 后有括号,标志着 signal 是一个函数指针,它有一些复杂的参数和不易分析的返回值。
    2. signal 函数指针指向的函数具有两个参数, 一个是 int sig, 一个是 void(\*func)(int)。
    3. void(\*func)(int) 表示一个函数指针,被指向的函数接收一个 int 参数返回值为 void。
  3. 接着就是最后的那个 (int), 它和最前面的 void 一起表示 signal 指向的函数返回一个函数指针。 后者所指向的函数接受一个 int 参数并返回 void.

总结, 这个声明的含义为: signal 是一个函数指针,它返回一个接收一个 int 参数并返回 void 的函数指针。而 signal 函数接收一个 int 和一个函数指针作为参数。 第二个参数所指向的函数接收一个 int 参数并返回 void

哈哈,其实我想说,即使我们分析清楚了这个声明的意义,它依旧像魔鬼一样难以理解。

欢迎交流任何想法.

End…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499687.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C 语言笔记: 链表节点实现技巧--struct的妙用

链表节点实现技巧–struct的妙用 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 废话 C 语言虽然只提供了非常简单的语法&#xff0c;但是丝毫不影响 C 语言程序员使用 C 来实现很多让人叹为观止的高级功能…

协议簇: Media Access Control(MAC) Frame 解析

Media Access Control(MAC) Frame 解析 前言 千里之行&#xff0c;始于足下。 因为个人从事网络协议开发&#xff0c;一直想深入的学习一下协议族&#xff0c;从这篇开始&#xff0c;我将开始记录分享我学习到的网络协议相关的知识 简介 引用百度百科的描述&#xff1a; 数…

协议簇:Ethernet Address Resolution Protocol (ARP) 解析

简介 前面的文章中&#xff0c;我们介绍了 MAC Frame 的帧格式。我们知道&#xff0c;在每个 Ethernet Frame 中都分别包含一个 48 bit 的源物理地址和目的物理地址. 对于源地址很容易理解&#xff0c;该地址可以直接从硬件上读取. 但是对于一个网络节点&#xff0c;他怎么知道…

协议簇:IPv4 解析

简介 IP 是一种无连接的协议. 操作在使用分组交换的链路层&#xff08;如以太网&#xff09;上。此协议会尽最大努力交付数据包。 尽最大努力意味着&#xff1a; IP 协议不保证数据的可靠传输, 没有流量控制机制, 不保证传输序列(意味着 IP 数据包会在传输过程中乱序), 没有…

协议簇:ICMP 解析

简介 ICMP 是 Internet Control Message Protocol 的简写. 它主要用来调试网络通信环境中存在的问题. 比如&#xff0c;当 IP 数据包总是无法正常的发送到目的地址, 当网关没有足够的 buffer 来转发对应的数据包 等问题. 值得一提的是&#xff0c;它属于网络层&#xff0c;不属…

协议簇:TCP 解析: 基础

简介 本文我们将从 RFC 学习一下 RFC793 中描述的 TCP 协议. 这将区别于通常讲解计算机网络书籍中所描述的 TCP. 但他们必然是相统一的&#xff0c;不会互相冲突. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&#xff1a;建立连接 协议…

协议簇:TCP 解析: 建立连接

简介 接前文 协议簇&#xff1a;TCP 解析: 基础&#xff0c; 我们这篇文章来看看 TCP 连接建立的过程&#xff0c;也就是众所周知的”三次握手“的具体流程. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&#xff1a;建立连接 协议簇&a…

协议簇:TCP 解析: 连接断开

简介 接前文 协议簇&#xff1a;TCP 解析: 建立连接&#xff0c; 我们这篇文章来看看 TCP 连接断开的过程&#xff0c;也就是众所周知的”四次挥手“的具体流程. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&#xff1a;建立连接 协议…

协议簇:TCP 解析: Sequence Number

简介 序列号&#xff08;Sequence Number&#xff09; 是 TCP 协议中非常重要的一个概念&#xff0c;以至于不得不专门来学习一下。这篇文章我们就来解开他的面纱. 在 TCP 的设计中&#xff0c;通过TCP协议发送的每个字节都对应于一个序列号. 由于每个字节都有自己的序列号&a…

协议簇:TCP 解析:TCP 数据传输

简介 前面&#xff0c;我们分别介绍了 TCP 基础知识以及连接的建立和关闭&#xff0c;以及最重要的 Sequence Number 的概念. 本篇文章&#xff0c;我们来介绍一下 TCP 如何传输数据. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&…

CodeTank iOS App Technical Support

CodeTank iOS App Technical Support For All Email: z253951598outlook.com TEL: 86-17782749061 App Screen Shoots

CentOS 7 防火墙命令

查看防火墙状态 systemctl status firewalld如果已经开启&#xff0c;状态为 active 如果未开启&#xff0c;状态为 inactive 开启防火墙 systemctl start firewalld关闭防火墙 systemctl stop firewalld查看当前防火墙的配置 firewall-cmd --list-all这里&#xff0c;我…

Go Concurrency Patterns: Context

Go Concurrency Patterns: Context 原文地址&#xff1a;https://blog.golang.org/context Introduction 在 Go 语言实现的服务器上&#xff0c;我们总是使用 goroutine 来处理与客户端建立的连接&#xff0c; 给每个连接分配一个独立的 goroutine. 在请求的 handler 中也通常…

Go Concurrency Patterns: Timing out, moving on

原文地址&#xff1a;https://blog.golang.org/concurrency-timeouts 并发变成有它自己的风格. 一个非常好的例子就是 timeout. 虽然 go 的 channel 没有直接支持 timeout 机制&#xff0c;但是要实现它非常容易. 比如说&#xff0c;我们想从一个 channel ch 中接收数据&#…

Go Concurrency Patterns: Pipelines and cancellation

原文地址&#xff1a; https://blog.golang.org/pipelines 简介 Go 语言提供的并发原语使得可以很方便的构建数据流 pipeline&#xff0c;使用这样的 pipeline 可以高效的利用 I/O 和多 cpu 的优势. 这篇文章我们将展示如何构建并使用 pipeline. 什么是 pipeline ? 在 go 语…

QTcpSocket connectToHost 建立连接速度慢问题

问题场景 在使用 QT 开发一个客户端 App 的时候&#xff0c;我们通过 QTcpSocket 与后台服务器进程通信。 后台程序使用其他语言编写。 问题&#xff1a; 在客户端启用之后尝试建立与后台程序的 TCP 连接的时候&#xff0c;发现连接速度非常慢&#xff08;肉眼可见的慢&#x…

WinSock I/O 模型 -- Select 模型

简介 Select 模型是 WinSock 中最常见的 I/O 模型&#xff0c;这篇文章我们就来看看如何使用 Select api 来实现一个简单的 TCP 服务器. API 基础 Select 模型依赖 WinSock API Select 来检查当前 Socket 是否可写或者可读。 使用这个 API 的优点是我们不需要使用阻塞的 So…

WinSock I/O 模型 -- WSAEventSelect 模型

简介 WSAEventSelect 模型也是 WinSock 中最常见的异步 I/O 模型。 这篇文章我们就来看看如何使用 WSAEventSelect api 来实现一个简单的 TCP 服务器. API 基础 WSAEventSelect WSAEventSelect 用来把一个 SOCKET 对象和一个 WSAEVENT 对象关联起来。 lNetworkEvents 表示…

WinSock I/O 模型 -- WSAAsyncSelect 模型

简介 WSAAsyncSelect 模型也是 WinSock 中常见的异步 I/O 模型。 使用这个模型&#xff0c;网络应用程序通过接收以 Windows 消息为基础的网络事件通知来处理网络请求。 这篇文章我们就来看看如何使用 WSAAsyncSelect api 来实现一个简单的 TCP 服务器. API 基础 要使用 W…

WinSock I/O 模型 -- OVERLAPPED I/O 模型

简介 OVERLAPPED I/O 模型也是 WinSock 中常见的异步 I/O 模型&#xff0c;相比于我们之前提到的 Select 模型&#xff0c;WSAAsyncSelect 模型 和 WSAEventSelect 模型有更好的性能. 为了方便描述&#xff0c;下文我们将称 Overlapped I/O 模型为 “重叠模型”. 重叠模型的…