码迷,mamicode.com
首页 > 编程语言 > 详细

C语言程序设计之C语言概述

时间:2018-08-11 10:56:17      阅读:326      评论:0      收藏:0      [点我收藏+]

标签:点击   调试   内存地址   top   hat   提高   删除   dcl   公司   

2.1 浅谈计算机系统架构

2.1.1 计算机硬件系统

现代计算机是由运算器、控制器、存储器、输入设备、输出设备五大部分组成,它们各司其职,完成了数据的计算、存储、传输任务,计算机整体架构如下图所示
技术分享图片
下面是它们各个组件的功能介绍:

  • CPU:也被称为中央处理器,由运算器和控制器组成,其主要作用是数据计算(从内存中获取指令并执行后将结果返回给内存或者写入到磁盘)和控制其他设备(声卡显卡,鼠标键盘)协同工作。目前主流的CPU架构有基于Intel的复杂指令集的X86架构(32位和64位)和手机(ARM指令集),服务器(SPARC指令集)的精简指令集。CPU通过总线(数据总线、地址总线、控制总线)和外部进行交互。

  • 内存:采用编址存储,其主要作用是用来作为程序的工作区,程序运行时其数据和指令会被加载到内存,断电后数据会丢失。

  • 硬盘:其主要作用是永久性存储海量数据,分为机械式硬盘和固态硬盘两大类。

  • IO设备:其主要作用是用来数据的输入输出,常见的输入设备包括鼠标键盘,常见的输出设备包含声卡,显卡,打印机等等。网卡主要是负责数据在网络上的传输。

在后期程序排错时除了考虑程序本身的错误之外还要考虑计算机硬件故障(例如磁盘被写满,网络不通)等问题。

2.1.2 计算机软件系统

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

不同平台的软件有不同的交互方式:
通常在服务器端,运维开发人员基于命令行的字符界面实现人机交互,
在PC桌面端,开发人员、普通用户通常是基于图形化界面实现人机交互,
在移动端,用户通常是通过手势触控实现人机交互。

而软件通常被分为系统软件和应用软件
系统软件有Unix,Linux,macOS,Windows,Android,ios,编译器、数据库等等。
应用软件有淘宝、京东、微信、支付宝等等。
通常由操作系统(Windows,Linux,macOS)的内核负责和底层硬件交互,应用软件运行在操作系统之上。因此操作系统起着承上启下的作用。

2.2 C语言概览

起源
1972年,贝尔实验室的Dennis Ritch和Ken Thompson在开发Unix操作系统时设计了C语言,该操作系统的90%以上的代码都是由C语言实现,后期的Linux,MacOS,Android,IOS都是基于Unix发展而来的。

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

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

应用场景
偏向操作系统、硬件驱动、底层应用、嵌入式应用开发

硬件驱动的绝大部分实现是由C语言和汇编语言实现的。

目前主流操作系统(Unix,Linxu,MacOS,Windows,Android,IOS)的底层实现都是由C语言和部分汇编实现的。

C++,Java,Python,Swift的编译器或者解释器都是由C语言实现的。

Git,Nginx,Redis,MySQL都是使用C语言实现的,而且都是开放源代码的,可以通过阅读源码提升自己的设计和编码能力。

C语言还可以开发游戏引擎、图形界面、网站后台的程序。

标准
1987年Dennis Ritch和Brian Kernighan编写了The C Programming Language第一版是公认的C标准实现,而没有定义C库。

而后期ANSI/ISO先后于1990年、1999年和2011年发布了C90标准、C99标准和C11标准,该标准定义了C语言和C标准库。

如果没有特殊说明,后面的样例代码都采用C11标准实现。

精髓
32个关键字(赋予了特殊的含义)+9种控制语句+34种运算符

学习C语言的好处
学完C语言可以快速掌握其他常用语言,例如C++,C#,Java,Python,Objective-C,Go,因为这些语言在许多方面都模仿了C语言,而且必须深入掌握C语言,才能对其他语言的底层实现有比较深入的了解。

C语言是目前众多编程语言中综合性能最好的编程语言。

2.3 C语言开发环境搭建

目前主流操作系统(Windows,Linux,MacOS)都有完善的C语言集成开发环境,用于编辑、编译、调试、打包部署C程序,下面表格是各个操作系统对应的集成开发环境说明。

操作系统开发工具
Windows10 Visual Studio2017
macOS10.14 XCode10
Ubuntu18.04 QT5.10

Windows作为世界上最流行的桌面操作系统,最新版本为Windows10 1803,VisualStudio作为Windows上最强大的集成开发环境,可以开发Windows软件,游戏,Web应用等等,最新版本为VisualStudio2017 15.7.5。后续的C语言应用案例如果没有强调集成开发环境,默认就是基于Windows10+VisualStudio2017上实现。

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

MacOS平台推荐使用XCode来编写C/C++程序。

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

2.4 C语言helloworld实现

1 启动VisualStudio2017并安装GitHub插件

启动界面如下图所示
技术分享图片

通过菜单工具->扩展和更新->联机来搜索GitHub插件,然后根据提示安装后重启即可,安装成功后如下图所示。
技术分享图片

2 连接并登录到GitHub
在Visual Studio右侧的团队资源管理器视图中点击管理连接并选择连接到GitHub,如下图所示
技术分享图片

然后输入用户名和密码登录到GitHub,如下图所示。如果你没有GitHub账号,请前往官网去注册
技术分享图片

3 然后创建仓库
选中Visual Studio右侧的团队资源管理器中的GitHub Create菜单,如下图所示。
技术分享图片

然后设置仓库信息,包括仓库名字、本地存储路径以及,Git ignore,License信息,如下图所示。
技术分享图片

4 然后在团队资源团管理器示图下新建并配置解决方案,如下图所示
新建解决方案
技术分享图片
配置解决方案

 

技术分享图片
配置解决方案

 

5 然后在解决方案的源文件目录下新建文件筛选器Chapter1,并在该目录下创建helloworld.c源文件
技术分享图片
6 然后编写如下代码

#include <stdio.h>

void main() {

    printf("hello world with windows10&visual studio 2017");
    getchar();
}

7 启动程序(快捷键F5)并查看运行结果
技术分享图片

2.5 helloworld深入解析

  1. 在Windows下,一个C语言的应用程序如果想独立运行,必须有main方法作为程序的入口,main方法的声明格式如下代码片段所示,所有的程序代码从main方法开始执行。
void main(){
    
}

其中void表示该函数没有返回值,而在Linux下,编译器强制要求main函数返回为int,代码片段如下所示

int main(){
    
}

  1. 如果想要调用函数的某个方法,必须首先包含该方法所在的头文件,例如这里调用的printf()函数,就是位于系统目录C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\ucrt下的头文件stdio.h。如果该文件在当前目录下,使用#include "头文件",如果该头文件在系统目录下,则使用#include <>。编译器查找当前目下的头文件时如果未找到,还会去系统目录下查找对应的头文件。

  2. #include的作用实际上就是将包含的文件全部复制到原文件中。
    这里来编写一个程序演示#include的作用。
    首先编写头文件guanglei.h,如下图所示
    技术分享图片
    源码如下所示

#include <stdio.h>

void main() {

    printf("执行guanglei.h头文件中的内容\n"); //这里的\n表示换行
    getchar(); //等待输入任意字符退出
}

然后编写C语言源文件include.c,源码如下所示

#include "guanglei.h"

然后按快捷键F5运行程序,会发现程序报错,错误如下所示
技术分享图片
这是因为在VisualStudio中,同一个解决方案下的所有源文件中只能有一个main方法,这里只需要把之前在源文件helloworld.c中的main方法重命名为main_helloworld即可,然后运行程序,会得到如下图所示的结果,结果表明当include.c包含了guanglei.h后会在预编译时将guanglei.h的内容复制到include.c中。
技术分享图片

4.为了提高程序的复用性,可以在头文件的文件夹中定义一个通用的头文件(common.h),源码如下所示,

#include <stdio.h>
#include <stdlib.h>

后期在引用头文件时,只需要引用common.h即可。
如果需要引用到其他的头文件,也只需要在该头文件中添加即可。

  1. return通常用在函数中,表示退出该函数,这也就意味着return之后的代码都不会被执行。而C语言的编译器比较松散,即使函数在定义时有返回值,而实现没有返回值也不会编译错误,但是却会得到一个错误的结果,应用案例(Chapter1/return.c)如下所示
#include "common.h"


int sub(int one,int two) {
    return one - two;
    printf("return之后的语句不会在执行了");
}

int add(int one,int two) {
}

void main() {
    printf("sub方法调用的结果是%d\n",sub(20, 10));
    printf("add方法调用的结果时%d\n",add(100,200));
    getchar();

}

6.在后期程序开发中可能会遇到各种各样的错误,这时我们就需要利用VisualStudio提供的强大的调试功能来查找错误。
首先需要下断点,断点会中断程序的执行,然后可以结合printf()函数查看变量的值以及内存地址,如下图所示
VisualStudio下断点,只需要在指定的行数单击即可。
技术分享图片
然后便可以在Visual Studio的菜单调试->窗口->内存中查看变量的存储。
技术分享图片
应用案例(debug.c)如下所示

#include "common.h"

void main() {

    int age = 29;
    printf("整数变量age的地址是%p\n", &age);
    printf("整数变量age的值是%d\n",age);
    system("pause");
}

7 为了便于程序的后期维护,C语言支持单行注释//和多行注释/**/,注释用于描述程序的功能,编译器在编译时会将注释的内容删除,需要注意的是多行注释的内容不能嵌套,否则会发生编译错误,应用案例(comment.c)如下所示

#include "common.h"

/*
    程序的入口
    所有的代码从这里开始执行
*/

void main() {

    //打印输出helloworld的两种方式

    printf("hello world \n"); // \n表示换行
    system("echo hello world\n");
    system("pause"); //程序暂停,按任意键退出

}

最后将之前编写的代码提交到远程仓库,具体的操作是切换到团队资源管理器示图,然后点击菜单项目->更改
技术分享图片
然后输入提交消息,点击全部提交
技术分享图片
然后同步
技术分享图片
最后点击推送,推送到远程分支
技术分享图片
当推送成功之后会看到如下的消息
技术分享图片

还可以通过访问地址 https://github.com/ittimeline/Learning-C-Programming 查看项目,后期所有的C语言代码都会推送到这个仓库。
技术分享图片

2.6 Windows常用命令

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

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

Windows系统可以使用快捷键Windows+r调出运行,如下图所示

 

技术分享图片
cmd

 

后输入cmd,便可以进入Windows下的命令行终端,如下图所示
技术分享图片

Windows下常用的文件目录和系统应用相关的命令如下所示,只要开启了终端就可以在终端内通过使用文件目录相关和系统应用相关的命令实现快捷操作。

2.6.1 文件目录相关

命令名称功能描述
dir 列出当前目录列表
cd 切换目录(只能在根盘符(例如C盘)内切换)
md 创建目录
del 删除文件
type 显示文本文件内容
cls 清除屏幕内容
exit 退出终端

2.6.2 系统应用相关

命令名称功能描述
notepad 记事本
calc 计算器
mspaint 画图
explore 文件资源管理器
timedate.cpl 日期和时间
cleanmgr 磁盘清理
desk.cpl 分辨率设置
powercfg.cpl 电源设置
regedit 注册表编辑器
msconfig 系统配置
mstsc 远程连接
firewall.cpl 防火墙
appwiz.cpl 添加或修改程序
tasklist 查看进程列表
taskkill /f /im process.exe 关闭指定进程
msinfo 系统信息
sticky notes 便签
ipconfig 查看ip
winver 查看windows版本
echo 显示文本内容 例如echo %path% 查看系统环境变量
dxdiag DirectX诊断工具

2.7 system函数的使用

system函数是位于系统路径下的stdlib.h头文件中,用于调用各大操作系统的应用程序,如下应用案例所示(system.c)展示了读取用户输入的命令后通过system函数执行调用应用程序。

#include "common.h"

/*使用system调用windows系统命令*/
void main() {

    printf("请输入你要执行的命令\n");
    //定义数组保存用户输入的指令
    char str[100] = {0};
    //使用scanf函数读取用户输入的指令
    scanf("%s",str);
    //执行命令
    system(str);

}

在使用scanf()函数时,需要在common.h头文件中定义常量#define _CRT_SECURE_NO_WARNINGS //关闭编译器安全检查来关闭编译器检查。

当使用system调用多个应用应用程序时会产生同步的效果,如下应用案例(system_sync.c)所示

#include "common.h"

/*system函数的同步特性*/
void system_sync() {
    //system函数的同步特性
    system("notepad"); //当打开记事本之后
    Sleep(5000);//等待5秒钟
    system("tasklist"); //只有自己手动关闭记事本后才会执行查看任务列表
    system("taskkill /f /im notepad.exe");//并没有关闭记事本
}
void main() {
    system_sync();
    

}

运行该程序之前需要在common.h中包含Windows.h头文件,完整的common.h头文件如下

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

而如果想要system函数异步执行,只需要传递start参数即可,如下应用案例(system_async.c)所示

#include "common.h"

/*如果想异步执行调用多个应用程序,可以加上start参数实现*/
void system_async() {
    //加上start参数之后会发现记事本和计算器同时打开,此时异步执行
    system("start notepad");
    system("calc");

}

void main() {
    system_async();

}


2.8 C语言编程流程

2.8.1 实现打开windows下的记事本,并在5秒之后关闭

实现思路:
首先使用sytem函数加上start参数异步打开记事本
然后借助Windows.h头文件的Sleep函数实现程序等待5秒
最后借助taskkill /f /im notepad.exe 命令关闭记事本。

完整应用案例(notepad.c)实现如下所示

#include "common.h"  //预处理优先于编译

/*
打开记事本并在5秒之后就关闭
*/
void openAndCloseNotepad() {
    //异步执行
    system("start notepad");

    Sleep(5000);

    system("taskkill /f /im notepad.exe");

}

void main(){
    openAndCloseNotepad();
}

2.8.2 实现打开windows下的QQ,并根据用户输入的时间关闭QQ

实现思路

引入头文件

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

首先定义一个打开QQ的函数openQQ,如下所示
,使用ShellExecuteA()函数可以避免system函数的同步问题,因为system函数的start参数只能作用于不带路径的程序。

/*
    打开QQ
    
*/
void openQQ() {
    ShellExecuteA(0,"Open","\"C:/Program Files (x86)/Tencent/QQ/Bin/QQScLauncher.exe\"",0,0,1);
}

然后定义sleep函数,如下所示:使用printf函数给予用户提示输入指定的秒数,使用scanf函数读取用户输入的数据,使用Sleep()函数暂停

/*
    暂停
*/
void sleep() {
    int second = 0;
    printf("请输入多久后关闭QQ\n");
    scanf("%d", &second);
    printf("QQ将在%d秒后关闭\n", second);
    int i =1;
    while (i<=second) {
    
        Sleep(1000);
        printf("睡了%d秒\n",i);
        i++;
    }
}

最后定义关闭QQ的函数closeQQ,如下所示,只需要使用命令taskkill /f /im QQ.exe,即可关闭QQ。

void closeQQ() {
    system("start taskkill /f /im QQ.exe");
}

最后在main函数中分别引用上述函数即可实现功能

#include "common.h"
void main() {
    openQQ();
    sleep();
    closeQQ();

}

2.9 C程序的运行流程

C语言编写的程序如果没有使用特定平台的库,那么便可以运行在各大操作系统之上,这里以Ubuntu上的gcc编译器为例,了解C程序的运行流程。

首先编写源程序

#include <stdio.h>
int  main(){

    printf("hello world with ubuntu18.04&visual studio code\n");

    return 0;
}

C程序运行时首先会进行预编译,目前得知预编译主要是完成以下任务

1 将源文件中包含的头文件的内容复制到源文件中

2 将源文件中采用#define定义的常量值完成替换

3 将源文件中的注释删除。

安装gcc编译器,命令如下所示

$ sudo apt install -y gcc

预编译

然后使用gcc的-E选项预编译helloworld.c,-o是指定预编译输出的文件名,
预编译完成之后使用你喜欢的编辑器(例如Visual Studio Code)查看helloworld.E,便可更加直观的明白预编译具体是做什么事情了。

$ gcc -E helloworld.c  -o helloworld.E

转汇编

C语言的源代码计算机是不能识别的,因此在运行之前需要转换成汇编语言,通过gcc编译器的-S选项来实现转换成汇编,命令如下:

$ gcc -S helloworld.c  -o helloworld.S

转汇编
计算机最底层只能识别二进制(010101)的指令,编译器会将汇编指令转换成顶层的二进制机器码,可以使用gcc编译器的-c选项来实现编译二进制的机器指令,命令如下:

$ gcc -c helloworld.c -o helloworld.o

windows默认编译生成的是.obj后缀的二进制文件,linux默认生成的是.out后缀的二进制文件。

链接
在编译成机器码之后还不能直接运行,还需要一个链接的过程,就是将C语言的库函数,启动代码以及源码编译后的二进制文件打包到一起组成可执行的二进制文件。
链接不需要加任何参数即可,命令如下。

$ gcc helloworld.c -o helloworld.out

完整的命令如下所示

guanglei@ubuntu:~$ pwd
/home/guanglei
guanglei@ubuntu:~$ cd Desktop/
guanglei@ubuntu:~/Desktop$ ls
helloworld.c  
guanglei@ubuntu:~/Desktop$ gcc -E helloworld.c -o helloworld.E
guanglei@ubuntu:~/Desktop$ gcc -S helloworld.c -o helloworld.S
guanglei@ubuntu:~/Desktop$ gcc -c helloworld.c -o helloworld.o
guanglei@ubuntu:~/Desktop$ gcc helloworld.c  -o helloworld.out
guanglei@ubuntu:~/Desktop$ ./helloworld.out
hello world with ubuntu18.04&visual studio code

如果想查看你的程序引用了哪些系统库,可以使用ldd命令查看,如下所示

guanglei@ubuntu:~/Desktop$ ldd helloworld.out
    linux-vdso.so.1 (0x00007ffcee79e000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7ea52cc000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f7ea58bf000)

C程序完整的流程图如下所示

 

技术分享图片
C语言运行流程

 

C语言程序设计之C语言概述

标签:点击   调试   内存地址   top   hat   提高   删除   dcl   公司   

原文地址:https://www.cnblogs.com/ittimeline/p/9458710.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!