zoukankan      html  css  js  c++  java
  • 架构师成长之道-C语言基础之C语言概述

     架构师成长之道-C语言基础之C语言概述

    1.1 信息技术发展趋势

    目前信息技术主要经历了互联网、移动互联网以及以大数据、云计算、物联网、人工智能、区块链为代表的新兴技术三个阶段。

    • 互联网
      互联网从20世纪90年代逐渐兴起,主要是通过网络连接了世界各地的笔记本、台式机以及背后提供后台数据服务的服务器集群,其中绝大多数笔记本和台式机都运行着Windows,macOS系统,而服务器主要是以类Unix(CentOS,Ubuntu)占据主要市场,依靠互联网成长起来的公司有微软、谷歌、苹果、亚马逊、百度、阿里巴巴、腾讯等等。

    • 移动互联网
      移动互联网主要是通过网络连接了世界各地的移动设备(最典型的就是手机),它们绝大多数都运行着Android,IOS系统,依靠移动互联网公司成长起来的有美团、滴滴、小米、蚂蚁金服,最近(2019/08)华为发布了鸿蒙操作系统。

    • 云计算、大数据
      当然随着用户数据的爆发式增长,以海量数据为基础的大数据、云计算技术在BAT,Apple,Microsoft,Amazon,Google级别的超大型互联网公司有广泛的应用场景。

    • 物联网
      物联网会以手机为中枢,通过网络连接所有智能设备,包括智能家居、汽车、电视等嵌入式设备,目前小米,华为等大厂在智能家居,电视开始布局。

    • 人工智能
      人工智能(AI)作为当前最火爆的技术之一,国内的BAT纷纷开始根据自身核心业务布局,阿里巴巴最早将人工智能应用在电商和物流领域,而百度开发出了对话时人工智能操作系统Dueros和自动驾驶平台Apollo,而腾讯则是在游戏领域应用人工智能。

    • 区块链
      而区块链经历了数字货币、智能合约、和超级账本三个发展阶段,区块链技术可以广泛使用在金融、供应链、物流、公共服务领域,解决互联网的信任问题。
      目前蚂蚁金服、京东已经有大量的区块链应用落地。

    1.2 浅谈计算机系统架构

    1.2.1 计算机硬件系统

    现代计算机是由运算器、控制器、存储器、输入设备、输出设备五大部分组成,它们各司其职,完成了数据的计算、存储、传输任务。

    • CPU
      也被称为中央处理器,由运算器和控制器组成,其主要作用是数据计算(从内存中获取指令并执行后将结果返回给内存或者写入到磁盘)和控制其他设备(声卡显卡,鼠标键盘)协同工作。目前主流的CPU架构有基于Intel的复杂指令集的X86架构(32位和64位)和手机(ARM指令集),服务器(SPARC指令集)的精简指令集。CPU通过总线(数据总线、地址总线、控制总线)和外部进行交互。
    • 内存
      采用编址存储,其主要作用是用来作为程序的工作区,程序运行时其数据和指令会被加载到内存,断电后数据会丢失。
    • 硬盘
      其主要作用是永久性存储海量数据,分为机械式硬盘和固态硬盘两大类。
    • IO设备
      其主要作用是用来数据的输入输出,常见的输入设备包括鼠标键盘,常见的输出设备包含声卡,显卡,打印机等等。网卡主要是负责数据在网络上的传输。
      在后期程序排错时除了考虑程序本身的错误之外还要考虑计算机硬件故障(例如磁盘被写满,网络不通)等问题。

    每个计算机组件的IO性能也各不相同,核心组件(CPU,内存,磁盘)都遵循容量越大,IO性能越差,如下图所示,汇总了它们的IO性能。

     

    IO性能汇总
    IO性能汇总

     

    在后期程序优化时,通常需要考虑时间复杂度和空间复杂度的问题。

    1.2.2 计算机软件系统

    软件出现的作用是实现了人和计算机更好的交互,它是由开发人员采用某种编程语言来编写一系列的指令以及根据不同的业务逻辑产生的数据组成。

    1.2.2.1 软件分类

    而软件通常被分为系统软件和应用软件

    • 系统软件:
      系统软件有运行在服务器端的Unix,Linux,运行在PC桌面的macOS,Windows;运行在移动设备(手机、电视)的Android,IOS;系统软件通常是负责管理硬件资源,同时给应用软件提供运行平台。

    • 应用软件:
      应用软件有运行在PC桌面、手机端的淘宝、京东、微信、支付宝等等。

    1.2.2.2 软件的交互方式

    不同平台的软件有不同的交互方式:

    • 服务器端:
      运维开发人员基于命令行的字符界面实现人机交互。
    • PC桌面端:
      开发人员、设计人员、产品经理、普通用户通常是基于图形化界面实现人机交互。
    • 移动端:
      普通用户通常是通过语音,手势触控实现人机交互。

    1.2.3 常用应用的软硬件协作实现

    计算机程序运行流程如下图所示
    计算机程序运行流程

    • 聊天:应用程序监听键盘输入的数据,放到内存,然后传给网卡,通过网络传递给另外一个网卡,再从网卡传到内存,显示在显示器上。
    • 听音乐:应用程序将音乐数据加载到内存之后,然后写到声卡上。
    • 看视频:应用程序将视频数据加载到内存,然后写到显卡上。
    • 读文档: 应用程序将磁盘中的文档数据加载到内存后显示到屏幕上。
    • 写文档: 应用程序将内存中的数据写入到磁盘上。

    1.3 程序和指令

    • 程序:
      程序是为了完成某项特定任务(例如聊天,听音乐等等)而使用某种编程语言编写的一组指令序列。
    • 指令:
      指令是对计算机进行程序控制的最小单位,由操作码和操作数组成,操作码指的是机器要执行什么操作(例如加减乘除),而操作数就是具体执行的对象(具体的数据以及存放数据的位置),所有指令的集合称为计算机的指令系统,常见的电脑指令系统有Intel X86指令集,常见的手机指令系统有ARM。因此手机上的应用程序不加修改是不能在电脑上直接运行,因为不同的指令集是不兼容的。

    1.4 编程语言发展史及其应用场景

    1.4.1 编译器与高级语言

    首先明确一点,计算机最底层只能识别二进制(010101)的机器指令,那些由汇编语言或者是高级程序设计语言编写的应用程序只是为了方便开发人员理解和维护,这就需要将汇编语言和高级语言翻译成计算机能够理解的机器语言,而编译器或者解释器就是做这个工作的。它的出现让开发人员在编写程序时不用考虑底层硬件的差异性,只需要专注具体业务逻辑的实现即可。

    C语言的编译器在各个操作系统之上都有实现,其中Windows系统可以使用Visual C编译器,而Linux可以使用GCC编译器,macOS可以使用LLVM CLang编译器。

    1.4.2 编程语言发展史

    任何事物都是从无到有,逐步发展壮大起来的,编程语言也是一样。

    计算机程序设计语言经历了机器语言到汇编语言和高级程序设计语言三个阶段,其特点是使得程序员用编程语言开发、测试、部署应用程序越来越方便、高效。但是是以牺牲效率为代价,但是随着计算机硬件的发展,绝大多数应用场景的效率损失可以忽略不计。

    • 机器语言
      计算机发展的最早期,程序员编写程序采用二进制的指令(010010101)来实现的,而每种CPU都有各自不同的指令系统(Ultra SPARC/Intel X86/ARM),因此在不同的机器上使用不同的机器语言实现。其特点是性能特别高效,而面向机器编程也就意味着不能移植,需要手动处理底层硬件的差异性,而且二进制的指令难以理解和维护。
    • 汇编语言
      随着时代和计算机技术的发展,汇编语言和编译器的出现解决了机器语言需要记住非常多的二进制机器指令的难题,但是还是没有从根本上解决移植性的问题,只是将机器指令转换为易懂的英文单词,然后由编译器编译成机器指令,因为计算机终归揭底只能识别二进制的0001110100110机器指令,而且汇编语言是面向机器的,不同机器(SPARC/Intel X86/ARM)的汇编指令是不相同的。
    • 高级程序设计语言
      高级程序设计语言的高级之处体现在开发人员在编写程序时无需关心计算机底层硬件差异而只需要专注于业务模块实现即可。甚至是可以实现 一次编译,到处运行,这里以Java为例子:通过实现不同平台的JVM,编译生成的字节码文件可以在任意的JVM上运行。
      高级语言通常都需要编译器或者是解释器将源码编译或者解释后执行。
      高级语言主要分为面向过程和面向对象两种,其中典型的面向过程编程语言就是C,面向对象的编程语言有Java,C++等等。

    1.4.3 编程语言应用场景

    如果想知道目前主流的编程语言有哪些,可以访问tiobe 首页获取编程语言排行榜。

    2019年8月编程语言排行榜Top20
    Tiboe编程语言排行榜

    根据Tiobe排行榜得知,Java/C/Python分别排在前三名, 随后紧跟着C++,C#等等.

    每种语言都有不同的应用场景和擅长的领域。

    编程语言 应用场景
    C 硬件驱动、操作系统、系统软件
    C++ 系统软件、网络通讯、科学计算 、游戏
    C# Windows应用,Web应用、游戏
    Java 大型互联网应用(淘宝、天猫),Android,大数据
    Python 人工智能、机器学习、自动化运维、数据分析 、图形处理
    PHP 中小型网站开发
    Objective-C/Swift macOS,iPhone,iPad应用开发
    JavaScript 浏览器端、服务端、PC桌面
    Go 高并发、区块链

    那么如果你作为初学者,面对如此之多的编程语言,到底应该先从哪门语言上车呢?如果你想深入的学习其他语言和架构相关的知识之前建议熟练掌握C语言。因为C++/Java/C#等编程语言都模仿了C语言。无论哪种语言,都是实现目标的工具,而不是目标本身。

    1.5 C语言概览

    C语言凭借其高效率、良好的移植性、功能强大的特性在操作系统、硬件驱动以及系统应用开发占据广阔的市场。

    1.5.1 C语言发展简史

     

    Dennis Ritchie
    Dennis Ritchie

     

    • 起源
      1972年,贝尔实验室的Dennis Ritchie和Ken Thompson在开发Unix操作系统时设计了C语言,该操作系统的90%以上的代码都是由C语言实现,后期的Linux,MacOS,Android,IOS都是基于Unix发展而来的。
    • 标准
      1987年Dennis Ritchie和Brian Kernighan编写了The C Programming Language第一版是公认的C标准实现,而没有定义C库。
      而后期ANSI/ISO先后于1990年、1999年和2011年发布了C90标准、C99标准和C11标准,该标准定义了C语言和C标准库。

    1.5.2 C语言特性

    C语言作为面向过程的高级程序设计语言,能够轻松的实现自顶向下的规划、结构化编程和模块化设计,这样使得程序结构更加简洁,可扩展性强以及更加容易维护。

    而且C语言有着高效(执行速度快)、功能强大(嵌套汇编)以及可移植性(标准库可移植)、功能强大等优点,而且也存在着对系统平台库依赖严重,由于编程风格自由,经验不足也会容易导致出错,编写代码实现周期长,同样的代码在不同的操作系统(或者编译器)下可能会有不同的表现等缺点。

    1.5.3 C语言应用场景

    C语言偏向操作系统、硬件驱动、底层应用(数据库、编译器)、嵌入式应用开发、游戏引擎等应用场景。

    • 硬件驱动的绝大部分实现是由C语言和汇编语言实现的。
    • 主流操作系统(Unix,Linxu,MacOS,Windows,Android,iOS)的底层实现都是由C语言和部分汇编实现的。
    • C++,Java,Python,Swift的编译器或者解释器都是由C语言实现的。
    • Git,Nginx,Redis,MySQL都是使用C语言实现的,而且都是开放源代码的,可以在GitHub中获取到,可以通过阅读源码提升自己的设计和编码能力。

    1.6 C语言集成开发环境搭建

    目前主流操作系统(Windows,Linux,MacOS)都有完善的C语言集成开发环境,用于编辑、编译、调试、打包部署C程序。

    操作系统开发工具
    Windows10 Visual Studio2019
    macOS10.14 XCode10.3
    Ubuntu18.04 QT5.13

    Windows作为世界上最流行的桌面操作系统,最新版本为Windows10 1903,VisualStudio作为Windows上最强大的集成开发环境,可以开发Windows软件,游戏,Web应用等等,最新版本为VisualStudio2019 16.2.2。
    Visual Studio 2019启动界面

    Ubuntu作为最受欢迎的桌面版Linux系统之一,推荐采用跨平台的集成开发环境QT来编写C/C++程序。
    QT Creator

    MacOS平台推荐使用XCode来编写C/C++程序,而且XCode在macOS系统上是自带的,无需额外安装。
    Xcode

    除此以外还有些跨平台的C/C++ 开发工具,例如来自Jetbrains公司的CLion也可以用来编写C/C++程序。
    Clion

    关于IDE的安装以及使用,它们的官网都提供了详细的教程,同学们可以自行去查阅。

    IDE官网地址
    Visual Studio 下载 文档
    CLion 下载 文档
    QT 下载 开发者
    XCode 官网

    C语言学习过程中会使用Windows10 1903+Visual Studio 2019作为主力开发工具,如果没有特别的说明,默认的环境就是Windows10 1903和Visual Studio 2019。

    1.7 Visual Studio Code实现HelloWorld

    HelloWorld是学习一门编程语言的入门程序,如果你能独立编写并运行HelloWorld,那么就意味着迈入了编程的大门了。

    Visual Studio Code是微软推出的一款开源、跨平台编辑器,这里使用它来编写C语言的源代码,如果想了解Visual Studio Code更多内容,可以去官网拜读文档。

    为什么首先要使用Visual Studio Code来编写第一个C程序呢,因为Visual Studio Code只是一个编辑器,用于编写源码,并不提供编译或者解释运行程序的功能。通过它来对比IDE,体验下使用IDE开发程序带来的好处,也有利于理解IDE背后的机制。

    1. 在D盘的code目录下创建源文件helloworld.c,C语言的源文件都是以.c结尾的。
    2. 编辑源文件
    #include <stdio.h>
    
    int main(int argc, char* argv[]) {
        printf("Hello World  Windows10 1903 & Visual Studio Code & C ");
        return 0;
    }
    1. 编译源文件
      将源文件编译成对应平台的可执行程序,因为计算机不能识别开发人员编写的源文件内容,只能识别二进制的机器指令。而C语言编写的源程序可以使用多种编译器来编译:Windows系统可以安装QT或者Visual Studio 2019后编译源文件

    QT中自带了GCC编译器,以QT5.13为例,将QT的默认安装路径(C:QtQt5.13.0Toolsmingw730_64in) 添加到系统的PATH环境目录下

    然后在Windows命令行的终端中输入gcc -v,看到类似如下输出,就可以使用gcc编译器了

    C:Usersittim>gcc -v
    Using built-in specs.
    COLLECT_GCC=gcc
    COLLECT_LTO_WRAPPER=C:/Qt/Qt5.13.0/Tools/mingw730_64/bin/../libexec/gcc/x86_64-w64-mingw32/7.3.0/lto-wrapper.exe
    Target: x86_64-w64-mingw32
    Configured with: ../../../src/gcc-7.3.0/configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --prefix=/mingw64 --with-sysroot=/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64 --enable-shared --enable-static --disable-multilib --enable-languages=c,c++,fortran,lto --enable-libstdcxx-time=yes --enable-threads=posix --enable-libgomp --enable-libatomic --enable-lto --enable-graphite --enable-checking=release --enable-fully-dynamic-string --enable-version-specific-runtime-libs --enable-libstdcxx-filesystem-ts=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-bootstrap --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-gnu-as --with-gnu-ld --with-arch=nocona --with-tune=core2 --with-libiconv --with-system-zlib --with-gmp=/c/mingw730/prerequisites/x86_64-w64-mingw32-static --with-mpfr=/c/mingw730/prerequisites/x86_64-w64-mingw32-static --with-mpc=/c/mingw730/prerequisites/x86_64-w64-mingw32-static --with-isl=/c/mingw730/prerequisites/x86_64-w64-mingw32-static --with-pkgversion='x86_64-posix-seh-rev0, Built by MinGW-W64 project' --with-bugurl=https://sourceforge.net/projects/mingw-w64 CFLAGS='-O2 -pipe -fno-ident -I/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64/opt/include -I/c/mingw730/prerequisites/x86_64-zlib-static/include -I/c/mingw730/prerequisites/x86_64-w64-mingw32-static/include' CXXFLAGS='-O2 -pipe -fno-ident -I/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64/opt/include -I/c/mingw730/prerequisites/x86_64-zlib-static/include -I/c/mingw730/prerequisites/x86_64-w64-mingw32-static/include' CPPFLAGS=' -I/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64/opt/include -I/c/mingw730/prerequisites/x86_64-zlib-static/include -I/c/mingw730/prerequisites/x86_64-w64-mingw32-static/include' LDFLAGS='-pipe -fno-ident -L/c/mingw730/x86_64-730-posix-seh-rt_v5-rev0/mingw64/opt/lib -L/c/mingw730/prerequisites/x86_64-zlib-static/lib -L/c/mingw730/prerequisites/x86_64-w64-mingw32-static/lib '
    Thread model: posix
    gcc version 7.3.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)

    gcc编译源文件并运行生成的可执行文件

    D:code>dir
     驱动器 D 中的卷是 DATA
     卷的序列号是 B0FB-1B0A
    
     D:code 的目录
    
    2019/08/18  10:48    <DIR>          .
    2019/08/18  10:48    <DIR>          ..
    2019/08/18  10:46               159 helloworld.c
                   1 个文件            159 字节
                   2 个目录 205,122,088,960 可用字节
    
    D:code>gcc helloworld.c -o helloworld.exe
    
    D:code>helloworld.exe
    Hello World  Windows10 1903 & Visual Studio Code & C

    Visual Stuido 2019只需要在路径C:ProgramDataMicrosoftWindowsStart MenuProgramsVisual Studio 2019Visual Studio Tools下运行 Developer Command Prompt for VS2019后 使用cl命令编译源文件命令即可。

     

    Visual Studio 2019编译运行C程序
    Visual Studio 2019编译运行C程序

     

    **********************************************************************
    ** Visual Studio 2019 Developer Command Prompt v16.2.2
    ** Copyright (c) 2019 Microsoft Corporation
    **********************************************************************
    
    C:Program Files (x86)Microsoft Visual Studio2019Enterprise>d:
    
    D:>cd code
    
    D:code>cl helloworld.c
    用于 x86 的 Microsoft (R) C/C++ 优化编译器 19.22.27905 版
    版权所有(C) Microsoft Corporation。保留所有权利。
    
    helloworld.c
    Microsoft (R) Incremental Linker Version 14.22.27905.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:helloworld.exe
    helloworld.obj
    
    D:code>helloworld.exe
    Hello World  macOS & Visual Studio Code & C

    1.8 Visual Studio 2019集成GitHub

    在正式使用Visual Studio 2019开发C语言的程序时,可以集成GitHub插件,编译后期代码统一管理。

    Github是开源的项目托管平台,在使用它之前得先创建一个账号。后续所有的C程序的源文件都会上传到GitHub,这样即使更换电脑,只需要从远程的GitHub将项目克隆到本地即可。

    1. 启动Visual Studio 2019
      继续,但无需代码

    2. 下载Visual Studio 的GitHub插件
      点击Visual Studio菜单 扩展->管理扩展
      管理扩展
      然后点击联机,选择GitHub Extension for Visual Studio 点击下载即可。
      下载插件

    3. 安装GitHub插件
      在Visual Studio 2019中下载完GitHub插件以后需要手动关闭Visual Studio 2019,然后会自动开启安装进程
      用户账户控制
      用户账户控制
      此时Visual Studio会去联网下载GitHub插件,如果遇到网络原因下载超慢,可以扫描下方的二维码下载
      GitHub

    然后关闭VisualStudio2019,进入C:Program Files (x86)Microsoft Visual Studio2019EnterpriseCommon7IDE目录下
    然后进入目录
    输入cmd
    输入cmd
    此时就已经进入C:Program Files (x86)Microsoft Visual Studio2019EnterpriseCommon7IDE目录下,只需要输入VSIXInstaller.exe C:UsersittimDesktopGitHub.VisualStudio.vsix并回车后便可开始安装GitHub插件
    执行安装

    开始安装
    Install

    安装完成
    安装完成

    1. 连接GitHub
      GitHub插件安装完成以后,重启Visual Studio 2019
      重启Visual Studio 2019

    首先将项目由解决方案资源管理器切换到团队资源管理器,然后点击连接GitHub
    连接GitHub

    1. 登录GitHub
      输入用户名和密码登录GitHub
      登录GitHub

    2. 创建仓库
      首先点击创建菜单
      创建仓库
      然后设置仓库名称、描述以及本地仓库路径、Git忽略、License
      设置项目信息

    如果一切顺利,可以使用浏览器访问地址https://github.com/ittimeline/c-core-programming 来访问项目,各位同学只需要将ittimeline替换成你们的账户即可。
    c-programming

    1.9 Visual Studio 2019实现HelloWorld

    1. 新建解决方案
      在之前创建的Git仓库c-core-programming基础上新建项目
      新建解决方案
      然后选择项目模板:基于C++的空项目
      基于C++的空项目
      然后设置项目名称、路径以及解决方案名称
      配置新项目

    2. 新建筛选器
      在解决方案资源管理器视图下,选中源文件,然后新建筛选器
      新建筛选器
      筛选器的名称为Chapter1
      Chapter1

    3. 新建项
      新建项
      新建源文件helloworld.c
      helloworld.c

    4. 编辑源文件

    #include <stdio.h>
    #include<stdlib.h>
    
    int main(int argc, char* argv[]) {
        printf("Windows10 1903 & Visual Studio 2019 Hello World 
    ");
        system("pause");
        return 0;
    }
    
    1. 运行helloworld
      点击本地Windows调试器,可以运行程序,也可以通过快捷键F5启动本地Windows调试器来运行程序
      本地Windows调试器
      程序运行结果
      程序运行结果
      如果想要关闭程序,可以通过快捷键Shift+F5实现。

    如果运行程序时出现如下提示
    在调试时停止自动关闭控制台
    可以根据提示设置在调试时停止自动关闭控制台
    在调试时停止自动关闭控制台

    Visual Studio遇到printf()语句自动弹出终端输出Windows10 1903 & Visual Studio 2019 Hello World,遇到return语句关闭终端,打开终端和关闭终端时间很短,感觉程序有闪退现象。
    这里可以调用stdlib.h头文件中的system函数并传递字符串参数pause让程序暂停。

    1. 推送代码到远程仓库
      首先切换到团队资源管理器视图下,然后点击更改
      更改
      然后填写提交信息,点击全部提交,此时会将代码提交到本地仓库
      commit log
      然后点击同步到远程仓库
      同步远程仓库
      推送到远程仓库
      推送到远程仓库

    然后就可以在GitHub仓库中查看提交的内容
    github/ittimeline/c-core-programming

    1.10 HelloWorld详解

    1.10.1 #include预处理

    在C语言中,如果想要调用系统的某个函数,必须首先包含该函数声明所在的头文件,例如hellowrld程序中调用printf()函数声明,就是位于系统目录C:Program Files (x86)Windows Kits10Include10.0.18362.0ucrt下的头文件stdio.h。
    stdio.h

    如果包含的文件在当前目录下,使用#include "头文件",如果该头文件在系统目录下,则使用#include <>。而编译器查找当前目录下的头文件时如果未找到,还会去系统目录下查找对应的头文件。

    #include的本质就是将包含的头文件内容全部复制到源文件中去。
    如何验证这一点呢?

    首先在项目c-core-programming-foundational的头文件下新建筛选器Chapter1,并创建头文件guanglei.h
    guanglei.h
    然后把之前源文件helloworld.c的源码复制到guanglei.h中
    guanglei.h
    之后定义源文件guanglei.c
    guanglei.c

    该源文件的内容只需要使用#include "guanglei.h" 即可运行。
    guanglei.h
    但是Visual Studio 2019 解决方案(例如c-core-programming)下每个项目(c-core-programming-foundational)只能有一个包含main方法的源程序,否则程序运行时会出错。
    定义多个main方法会出差错
    这里将之前helloworld程序中的main方法改成别的名字(例如helloworld_main)即可。

    然后再次运行程序,运行结果和之前的helloworld程序结果一样
    #include

    #include <stdio.h>表示包含头文件stdio.h,std表示标准库,是可以移植的。也就是helloworld.c可以运行在各个操作系统下。

    Windows10 1903 &CLion 2019.2
    Windows10 1903 &CLion 2019.2

    Ubuntu18.04 & CLion 2019.2
    运行之前必须先安装CMake,使用sudo apt install cmake安装即可
    Ubuntu18.04 & CLion 2019.2

    而stdio表示标准输入输出,printf()函数正是一个输出函数。
    stdlib表示标准库,system()函数正是一个标准库函数。
    头文件只存放了函数的定义,至于函数的实现,在对应的系统库文件中。

    1.10.2 main函数

    main函数是C程序的入口,一个项目只能有一个main函数,否则程序运行时会提示定义多个main函数。
    当程序运行时,系统自动调用main函数,程序从main函数的第一行开始执行,如果其他函数想要得到执行,那么必须被main函数直接或者间接调用

    int helloworld_main(int argc, char* argv[]) {
        printf("Windows10 1903 & Visual Studio 2019 Hello World 
    ");
        system("pause");
        return 0;
    }
    • main函数左边的int是函数的返回值,右边()的内容表示函数的参数,外部数据通过函数的参数传递到函数的内部处理。

    • {}表示函数的函数体,也就是函数执行的所有内容都包含在{}中,它是成对出现的。

    • printf函数是系统自带的函数,用于将""包含的字符串按照指定的格式输出到终端,终端可以是控制台、网页或者是文件,目前是输出到控制台。

    • 表示换行,这里就是输出内容之后换行。

    • 分号(;)表示一条语句结束,C语言每条执行语句都需要以分号(;)结束,如果不加上分号会发生编译错误。

    • system("pause")表示程序暂停,输入任意键后退出,如果在Visual Studio中编写C程序必须加上system("pause"),否则程序运行完成后就直接退出。使用CLion、QT不需要加上system("pause")。

    • return 0表示将int类型的值返回给main函数的调用方(系统)并结束main函数,return语句之后的代码都不会再执行了,0表示正常结束。

    在源文件function.c中定义了一个add方法,传递两个整数参数,返回两个整数相加的结果。并且该方法在主函数的prinf方法中被调用,用于输出两个整数相加的结果。
    printf函数中的%d表示对应位置的参数按照整数输出。

    #include <stdlib.h>
    
    
    
    int add(int source,int target) {
        return source + target;
        printf("不可达代码
    ");
    }
    
    
    int main(int argc,char* argv[]) {
        int source = 50;
        int target = 100;
        printf("%d加上%d的结果是%d
    ",source,target,add(source,target));
        system("pause");
        return 0;
    }

    程序运行结果表明add方法的return语句之后的输出语句printf("不可达代码 ")并没有执行,如果想要add方法得到执行,在main方法中调用即可,调用时需要传递对应的参数。
    程序运行结果

    1.10.3 注释

    注释是用于描述程序的功能,为了便于程序后期的维护,在开发过程中应该添加适量的注释,编译器在预编译时会删除注释,所以注释的内容不会影响程序的结果。

    C语言中支持的注释包含单行注释(//)和多行注释(/**/)两种,单行注释顾名思义就是注释一行,多行注释可以注释多行,需要注意的是多行注释不能够嵌套使用,否则会发生编译错误。

    增加单行注释和多行注释后的helloworld

    #include <stdio.h> 
    #include<stdlib.h>
    /*
    
     我的第一个C程序
     @author liuguanglei ittmelinedotnet@gmail.com
     @version 2019/08/20
    
    */
    int main(int argc, char* argv[]) {
        //快捷键F12可以查看函数定义  Ctrl+ -返回
        printf("Windows10 1903 & Visual Studio 2019 Hello World 
    ");
        system("pause");
        return 0;
    }
    

    1.11 Windows常用命令

    1.11.1 Windows命令概述

    主流的操作系统(Windows,Linux(Ubuntu),MacOS)及大多数应用程序都提供了基于命令行和图形化界面两种交互方式,而移动端是采用手势触控、语音等进行交互。作为普通用户来讲,图形化界面容易上手,而且交互效果更加直观。

    但是作为一个程序员来讲,应该去熟悉各个操作系统的命令行的使用,因为命令行相对图形化界面而言,绝大多数场景下使用更加高效。而且图形化界面本质是对命令行的封装,能用图形化界面实现的基本都可以采用命令行实现。而且在服务器端(CentOS,RedHat)基本上是不会安装图形界面。

    Windows系统可以使用快捷键Windows+r调出运行
    运行
    后输入cmd,便可以进入Windows下的命令行终端
    命令行终端
    Windows下常用的文件目录和系统应用相关的命令如下所示,只要开启了终端就可以在终端内通过使用文件目录相关和系统应用相关的命令实现快捷操作。

    1.11.2 Windows常用命令

    • 文件目录相关命令
    命令名称功能描述
    dir 列出当前目录列表
    cd 切换目录(只能在根盘符(例如C盘)内切换)
    md 创建目录
    del 删除文件
    type 显示文本文件内容
    cls 清除屏幕内容
    exit 退出终端
    • 系统应用相关命令
    命令名称 功能描述
    notepad 记事本
    calc 计算器
    mspaint 画图
    explore 文件资源管理器
    timedate.cpl 日期和时间
    cleanmgr 磁盘清理
    desk.cpl 分辨率设置
    powercfg.cpl 电源设置
    regedit 注册表编辑器
    msconfig 系统配置
    mstsc 远程连接
    firewall.cpl 防火墙
    appwiz.cpl 添加或修改程序
    tasklist 查看进程列表
    taskkill /f /im process-name.exe 关闭指定进程
    msinfo 系统信息
    sticky notes 便签
    ipconfig 查看ip
    winver 查看windows版本
    echo 显示文本内容 例如echo %path% 查看系统环境变量
    ping 检测网络是否畅通

    1.11.3 system函数

    system函数用于C程序中调用各大操作系统的命令和应用程序,被调用的命令和应用程序以字符串的方式作为system函数的参数传入。

    实现读取用户输入的命令,并执行该命令

    #include <stdio.h>
    #include <stdlib.h>
    
    /*
        使用system函数执行用户输入的命令
        @author tony ittimelinedotnet@gmail.com
        @version  2019/08/20
    */
    int main(int argc,char* argv[]) {
    
        printf("请输入你要执行的命令
    ");
        //定义数组保存用户输入的指令
        char str[100] = { 0 };
        //使用scanf_s函数读取用户输入的指令
        scanf_s("%s", str);
        //执行命令
        system(str);
        return 0;
    
    }

    因为system函数位于stdlib.h头文件中,意味着它是一个可以跨平台使用的函数,Visual Studio 2019中可以使用F12快捷键跳转到函数的定义。使用Ctrl+-快捷键实现后退。
    但是各大操作系统的命令和应用程序是不相同的,例如在Windows上使用system函数传递字符串参数"notepad"时可以打开记事本,而移植到了类Unix上则无法调用记事本。

    1.12 C语言的运行流程

    C语言编写的程序一般都要经过编写源文件->预处理->编译->汇编->链接后运行这几个流程。
    C语言程序运行流程

    • 预处理
      预处理主要是宏替换、包含头文件、条件编译以及删除注释等操作,预编译阶段生成文件的后缀名通常是.i。
    • 编译
      编译主要是将预处理好的文件生成汇编文件,编译后文件的后缀名通常是.s。
    • 汇编
      汇编主要是将汇编文件生成二进制文件,汇编后的文件的后缀名通常是.o。
    • 链接
      链接主要是将各个二进制文件、库函数、启动代码生成可执行文件。

    接下来编写源程序program_running_process.c,然后结合Windows上的GCC编译器提供的各个选项实现预处理、编译、汇编、链接,关于GCC的安装和配置可以参考
    Visual Studio Code实现Hello World章节的内容。

    #include <stdio.h>
    //定义浮点型的常量
    #define PI 3.14
    /*
        C语言程序的运行流程
        @author tony ittimelinedotnet@gmail.com
        @version  2019/08/20
    */
    int main(int argc, char* argv[]) {
    
        printf("PI =%lf
    ", PI);
        return 0;
    }

    预处理使用 gcc -E 选项即可实现,其中-o表示输出文件的名称

    D:workspacecvisualstuido2019c-core-programmingc-core-programming-foundationalc-core-programming-foundational>gcc -E  program_runing_process.c -o program_runing_process.i

    预处理完成以后,生成的文件program_running_process.i的大小是54kb
    预处理
    当预处理完成以后,定义的常量被替换成实际的值,而#include包含的头文件内容也被复制到预处理的生成的文件中
    预处理

    编译通过gcc -S 选项实现

    D:workspacecvisualstuido2019c-core-programmingc-core-programming-foundationalc-core-programming-foundational>gcc -S program_runing_process.i -o program_runing_process.s

    编译会生成汇编文件

        .file	"program_runing_process.c"
        .text
        .def	__main;	.scl	2;	.type	32;	.endef
        .section .rdata,"dr"
    .LC1:
        .ascii "PI =%lf12"
        .text
        .globl	main
        .def	main;	.scl	2;	.type	32;	.endef
        .seh_proc	main
    main:
        pushq	%rbp
        .seh_pushreg	%rbp
        movq	%rsp, %rbp
        .seh_setframe	%rbp, 0
        subq	$32, %rsp
        .seh_stackalloc	32
        .seh_endprologue
        movl	%ecx, 16(%rbp)
        movq	%rdx, 24(%rbp)
        call	__main
        movq	.LC0(%rip), %rax
        movq	%rax, %rdx
        movq	%rdx, %xmm1
        movq	%rax, %rdx
        leaq	.LC1(%rip), %rcx
        call	printf
        movl	$0, %eax
        addq	$32, %rsp
        popq	%rbp
        ret
        .seh_endproc
        .section .rdata,"dr"
        .align 8
    .LC0:
        .long	1374389535
        .long	1074339512
        .ident	"GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.3.0"
        .def	printf;	.scl	2;	.type	32;	.endef
    

    汇编通过gcc -c 选项实现

    D:workspacecvisualstuido2019c-core-programmingc-core-programming-foundationalc-core-programming-foundational>gcc -c program_runing_process.s -o program_runing_process.o

    链接gcc没有提供选项,这里只要执行gcc program_running_process.o -o program_running_process.exe就会链接生成可执行文件

    D:workspacecvisualstuido2019c-core-programmingc-core-programming-foundationalc-core-programming-foundational>gcc program_runing_process.o -o program_runing_process.exe

    windows下的可执行文件后缀名默认是.exe,当然gcc编译器不关心后缀名,如果你的ubuntu或者macOS下安装了gcc,也可以将C程序编译生成.exe后缀的可执行文件。

    在Linux下如果想要查看你的C序(编译生成的可执行文件引用了哪些系统库,可以使用ldd命令查看

     

    ldd查看程序依赖的系统库
    ldd查看程序依赖的系统库

     

    guanglei@ubuntu:~/CLionProjects/c-core-programming$ cd cmake-build-debug/
    guanglei@ubuntu:~/CLionProjects/c-core-programming/cmake-build-debug$ ls
    c_core_programming  c_core_programming.cbp  CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile
    guanglei@ubuntu:~/CLionProjects/c-core-programming/cmake-build-debug$ ldd c_core_programming
            linux-vdso.so.1 (0x00007ffdc1fcf000)
            libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0011a14000)
            /lib64/ld-linux-x86-64.so.2 (0x00007f0012007000)

    1.13 Visual Studio 2019调试程序

    在后期编写程序时,经验不足的开发人员通常会遇到两种错误:编译错误和运行时错误,编译错误通常是编写的程序不满足编译器的语法规范,而运行时错误则是程序运行时发生的错误,想要排查程序运行时的错误,就需要使用IDE提供的调试功能。

    在源文件debug.c中定义一个返回两个整数相乘的方法mul,然后在main函数中定义两个变量,并调用两个整数相乘的方法,输出计算结果

    #include <stdio.h>
    #include <stdlib.h>
    
    
    /*
        定义两个整数相乘并返回
    */
    int mul(int source,int target) {
    
        return source * target;
    }
    /*
        调试程序
        @author liuguanglei ittimelinedotnet@gmail.com
        @version 2019/08/21
    */
    int main(int argc, char* argv[]) {
    
        //定义两个变量
        int source = 12;
        int target = 12;
        printf("source = %d 	 target = %d 
    ", source,target);
    
        //调用两个整数相乘的方法,并将计算的结果保存到整数变量result中
        int result = mul(source,target);
        //输出两个整数相乘的结果
        printf("result = %d 
    ",result);
        system("pause");
        return 0;
    }

    在调试程序前首先需要下断点,可以使用快捷键F9下断点或者取消断点
    下断点
    然后使用F5调试运行程序,程序会在之前下过断点的地方暂停,此时可以在Visual Studio提供的窗口中观察变量的值
    观察变量
    如果想要一行一行调试代码,可以使用快捷键F11,当遇到函数时(例如这里的mul函数),会进入函数的内部一行一行执行,直到该函数结束为止。

    如果调试时不想进入函数的内部,可以使用快捷键F10,当程序中调用了其他函数时不会进入其他函数内部,但是函数会被调用。

    如果调试时想要从一个断点跳到另外一个断点,可以使用shift+F11实现。

    如果想要查看函数调用的定义,可以使用快捷键F12,退出查看函数定义则使用Ctrl+ -。
    在调试代码的过程中,还可能会注释部分错误的代码,注释可以使用快捷键Ctrl+k,u实现,而取消注释可以使用Ctrl+k,u实现。

    如果源文件中的代码格式比较凌乱,可以使用Ctrl+k,f快速格式化代码。

    1.14 Visual Stuido 2019技巧锦集

    1.14.1 Visual Studio 2019解决4096错误

    Visual Studio 希望用户使用Visual Studio提供的非标准库函数,但是程序员希望使用标准库函数,因为标准库是可以移植的。
    如果在Visual Studio中使用标准的库函数,就会引发4996错误类似于这种提示:error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.这里的strcpy是标准的库函数,而在Visual Studio中使用这个函数引发了4996错误。

    #define _CRT_SECURE_NO_WARNINGS //防止4996错误
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /*
        vs4996错误
         error C4996:  'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
    
        @author liuguanglei ittimelinedotnet@gmail.com
        @version 2019/08/21
    */
    int main(int argc,char *argv[]) {
        //定义一个字符串
        char buf[32] = "";
        //使用strcpy实现将字符串hi string复制到变量buf中
        strcpy(buf, "hi string");
        //输出字符串的内容
        printf("buf = %s 
    ",buf);
        system("pause");
        return 0;
    
    }

    如何解决Visual Studio中的4996错误呢?

    方案1:在源文件(例如这里的vs4996.c)的第一行定义宏

    #define _CRT_SECURE_NO_WARNINGS //防止4996错误

    方案2:在源文件(例如这里的vs4996.c)的第一行定义如下内容:

    #pragma warning(disable:4996)

    1.14.2 Visual Studio 2019配置代码片段

    在后期编写C程序中,需要反复使用到如下的代码片段

    //#define _CRT_SECURE_NO_WARNINGS 
    #include <stdio.h>
    #include <stdlib.h>
    /*
    
        @author liuguanglei ittimelinedotnet@gmail.com
        @version
    */
    int main(int argc,char *argv[]) {
    
        
    }

    这里为了减轻工作量,使用Visual Studio 2019提供的代码片段管理器来实现通过输入配置的快捷键生成模板代码。

    首先自定义代码片段文件MyCCode.snippet

    <?xml version="1.0" encoding="utf-8"?>
    <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
        <CodeSnippet Format="1.0.0">
            <Header>
                <Title>MyCCodeTemplate</Title>
                <Shortcut>mcct</Shortcut>
                <Description>c的标准模板代码</Description>
                <Author>Microsoft Corporation</Author>
                <SnippetTypes>
                    <SnippetType>Expansion</SnippetType>
                    <SnippetType>SurroundsWith</SnippetType>
                </SnippetTypes>
            </Header>
            <Snippet>
                <Code Language="cpp">
                <![CDATA[#define _CRT_SECURE_NO_WARNINGS
                #include <stdio.h>
                #include <stdlib.h>
          /*
            
              @author liuguanglei ittimelinedotnet@gmail.com
              @version 
          */
                int main(int argc, char *argv[])
                {
                    system("pause");
                    return 0;
                }]]>
                </Code>
            </Snippet>
        </CodeSnippet>
    </CodeSnippets>
    

    然后进入Visual Studio 2019 菜单 工具->代码片段管理器
    代码片段管理器
    选择代码片段管理器的语言为C++,然后选中My Code Snippets
    导入自定义代码管理器
    把MyCCodeTemplate.snippet导入进来
    MyCCode.snippet
    代码片段设置位置
    MyCCode.snippet

    导入成功之后新建源文件,在源文件中输入快捷键mcct就可以生成如下的代码片段

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    /*
    
        @author liuguanglei ittimelinedotnet@gmail.com
        @version
    */
    int main(int argc, char* argv[])
    {
        system("pause");
        return 0;
    }

    想要了解代码片段的更多内容,请移步官网

  • 相关阅读:
    Java调用CMD命令
    java在线截图---通过指定的URL对网站截图
    【好的技术员网站】蓝飞技术部落格==蓝飞技术部落格==蓝飞技术部落格
    事务管理最佳实践全面解析
    Javascript摸拟自由落体与上抛运动 说明!
    dwz中给表单项获取,设置值
    jquery操作select(取值,设置选中)[转]
    Flex 笔记整理 三
    Myeclipse 工具优化 [内存一直增加, jsp,javascript 编辑很卡]
    Spring: 读取 .properties 文件地址,json转java对象,el使用java类方法相关 (十三)
  • 原文地址:https://www.cnblogs.com/ittimeline/p/10213275.html
Copyright © 2011-2022 走看看