高效c语言1快速入门

本章将开发你的第一个C语言程序:传统的 "Hello, world!"程序。然后讨论一些编辑器和编译器的选项,并阐述移植性问题。

高效c语言1快速入门

Hello, world!

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

int main(void) {
puts("Hello, world!");
return EXIT_SUCCESS;
}

在Linux和其他类似Unix的操作系统上,你可以用cc命令调用系统编译器:

$cc hello.c
$ls
a.out hello.c
$./a.out
Hello, world!
% cc -o hello hello.c
% ./hello
Hello, world!

cc命令有许多标志和编译器选项。例如,-o文件标志让你给可执行文件起名字,而不是a.out。

hello.c程序的前两行使用了#include预处理器指令,它的行为就像你在完全相同的位置用指定文件的内容替换它一样。我们包括<stdio.h>和<stdlib.h>头文件来访问这些头文件中声明的函数,然后我们可以在程序中调用这些函数。puts函数在<stdio.h>中声明,而EXIT_SUCCESS宏在<stdlib.h>中定义。正如文件名所示,<stdio.h>包含了C语言标准I/O函数的声明,而<stdlib.h>则包含了一般实用函数的声明。

C定义了两种可能的执行环境:独立的和托管的。独立环境可能不提供操作系统,通常用于嵌入式编程。这些执行环境提供了一套最小的库函数,程序启动时调用的函数的名称和类型是执行环境定义的。

我们定义main返回int类型的值,并将void放在括号内,表示该函数不接受参数。int类型是有符号的整数类型,可以用来表示正、负整数值以及零。与其他程序性语言类似,C语言程序由可以接受参数和返回值的过程(称为函数)组成。每个函数都可重用,你可以根据需要在程序中频繁调用。在本例中,主函数返回的值表示程序是否成功终止。

puts("Hello, world!")打印出"Hello, world!"。 puts函数是标准库函数,它将字符串参数写入stdout(通常代表控制台或终端窗口),并在输出中附加换行符。如果不需要换行可以使用fputs。

return语句退出程序,向主机环境或调用脚本返回一个整数值。EXIT_SUCCESS是类似对象的宏,通常扩展为0,通常定义为:#define EXIT_SUCCESS 0。

检查函数的返回值

函数通常会返回一个计算结果的值,或者表示函数是否成功完成了它的任务。例如,我们在 "Hello, world!"程序中使用的puts函数需要打印字符串并返回int类型的值。如果发生写入错误,puts函数返回宏EOF的值(负整数);否则,它返回非负的整数值。

尽管对于我们的简单程序来说,puts函数不太可能失败并返回EOF,但这是可能的。因为对puts的调用可能会失败并返回EOF,这意味着你的第一个C程序有bug,或者,可以按以下方法改进。

#include <stdio.h>
#include <stdlib.h>
int main(void) {
  if (puts("Hello, world!") == EOF) {
    return EXIT_FAILURE;
    // code here never executes
  }
  return EXIT_SUCCESS;
  // code here never executes
}

注意(puts("Hello, world!")一定要有括号,否则编译会报错:

c$ cc hello2.c
hello2.c: In function ‘main’:
hello2.c:5:5: error: expected ‘(’ before ‘puts’
5 | if puts("Hello, world!") == EOF {
| ^~~~
| (

格式化的输出

puts函数是一种将字符串写入stdout的简单好方法,但最终你会需要使用printf函数来打印格式化的输出--例如,打印字符串以外的参数。printf函数接收定义输出格式的格式化字符串,然后是可变数量的参数,这些参数是你想打印的实际数值。例如,如果你想用printf函数来打印Hello, world!,你可以这样写。
printf("%s\n", "Hello, world!")。

第一个参数是格式字符串"%s\n"。%s是转换规范,指示printf函数读取第二个参数(字符串字面)并将其打印到stdout。\n是一个字母转义序列,用于表示非图形字符,并告诉函数在该字符串后面包括新行。

注意不要将用户提供的数据作为第一个参数的一部分传递给printf函数,因为这样做会导致格式化输出的安全漏洞(Seacord 2013)。

编辑器和集成开发环境

可以使用各种编辑器和集成开发环境来开发你的C语言程序。图1-1显示了最常用的编辑器,根据2018年JetBrains的调查。

高效c语言1快速入门

对于Microsoft Windows,Microsoft的Visual Studio IDE(https://visualstudio.microsoft.com/)是不错的选择。Visual Studio有三个版本。社区版、专业版和企业版。社区版的优点是免费,而其他版本的功能则需要付费。

对于Linux来说,Vim、Emacs、Visual Studio Code和Eclipse都可选择。Vim是许多开发者和高级用户的首选编辑器。它是一个基于vi编辑器的文本编辑器,由Bill Joy在1970年代为Unix的一个版本编写。它继承了vi的按键绑定,但也增加了原vi所缺少的功能和可扩展性。你可以选择安装Vim插件,如YouCompleteMe(https://github.com/Valloric/YouCompleteMe/)或deoplete(https://github.com/Shougo/deoplete.nvim/),为C语言编程提供本地语义完成。

GNU Emacs是可扩展的、可定制的、免费的文本编辑器。它的核心是Emacs Lisp的解释器,这是一种Lisp编程语言的方言,具有支持文本编辑的扩展功能--尽管我从未发现这是个问题。

Visual Studio Code(VS Code)是精简的代码编辑器,支持开发操作,如调试、任务运行和版本控制。它提供了开发人员所需的工具,以实现快速的代码构建--调试循环。VS Code可以在macOS、Linux和Windows上运行,对私人或商业使用都是免费的。

高效c语言1快速入门

编译器

现在有很多C语言编译器,他么编译器实现了不同版本的C标准。许多用于嵌入式系统的编译器只支持C89/C90。用于Linux和Windows的流行编译器更努力地支持现代版本的C标准,直到并包括对C2x的支持。

GCC已经被采纳为Linux系统的标准编译器,尽管也有用于微软Windows、macOS和其他平台的版本。在Linux上安装GCC很容易。例如,下面的命令在Ubuntu上安装GCC 8。

$ sudo apt-get install gcc-9
$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ sudo dnf install gcc # Fedora
$ sudo apt-get install clang

你可以用下面的命令测试你所使用的Clang的版本。
% clang --version
$ clang --version
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
  • 微软Visual Studio

Windows最流行的开发环境是Microsoft Visual Studio,它包括IDE和编译器。它与Visual C++ 2019捆绑在一起,其中包括C和C++编译器。
你可以在项目属性页上为Visual Studio设置选项。在C/C++下的高级选项卡上,确保你通过使用编译为C代码(/TC)选项而不是编译为C++代码(/TP)选项来编译为C代码。默认情况下,当你命名一个以.c为扩展名的文件时,它是用/TC编译的。如果文件被命名为.cpp、.cxx或其他一些扩展名,则用/TP编译。

参考资料

https://url97.ctfile.com/f/18113597-810419181-1f9306 下载密码 订阅号pythontesting 发送 密码 。

移植性

每个C语言编译器的实现都至少有一点不同。编译器不断发展,因此,例如,像GCC这样的编译器可能提供对C17的完全支持,但正在努力实现对C2x的支持,在这种情况下,它可能有一些C2x的功能实现,但没有其他。因此,编译器支持全部的C标准版本(包括中间的版本)。C语言实现的总体发展是缓慢的,许多编译器明显落后于C标准。

如果为C语言编写的程序只使用标准中规定的语言和库的那些功能,就可以认为是严格符合标准的。这些程序的目的是为了最大限度地提高可移植性。然而,由于实现行为的范围,现实世界中没有一个C语言程序是严格符合要求的,也不会是(可能也不应该是)。相反,C标准允许你编写符合要求的程序,这些程序可能依赖于非可移植的语言和库特性。

通常的做法是为一个参考实现编写代码,或者有时为几个实现编写代码,这取决于你打算在哪个平台上部署你的代码。C标准是确保这些实现不会有太大的差异,并允许你一次针对几个实现,而不必每次都学习一种新的语言。
在C标准文件的附件J中列举了五种可移植性问题。

  • 实现定义的行为

  • 未指定的行为

  • 未定义的行为

  • 针对本地的行为

  • 常见的扩展

  • 实现定义的行为
    实现定义的行为是指C语言标准中没有规定的程序行为,它可能在不同的实现中提供不同的结果,但在一个实现中具有一致的、有记录的行为。实现定义的行为的一个例子是一个字节中的位数。

实现定义的行为大多是无害的,但在移植到不同的实现时可能会导致缺陷。在可能的情况下,避免编写依赖于实现定义的行为的代码,这些行为在你可能用来编译你的代码的C实现中是不同的。C标准的附件J.3中列举了实现定义行为的完整列表。你可以通过使用static_assert声明来记录你对这些实现定义的行为的依赖。

  • 未指定的行为

未指定的行为是指标准提供了两个或多个选项的程序行为。该标准对在任何情况下选择哪个选项没有要求。每次执行一个给定的表达式可能会有不同的结果,或者产生与之前执行相同表达式不同的值。未指定行为的一个例子是函数参数存储布局,它在同一程序中的不同函数调用中可能会有所不同。避免编写依赖于C标准附件J.1中列举的非指定行为的代码。

  • 未定义的行为
    未定义的行为是指C标准没有定义的行为,或者说是 "在使用不可移植的或错误的程序结构或错误的数据时,标准没有规定的行为"。未定义行为的例子包括有符号的整数溢出和解读一个无效的指针值。具有未定义行为的代码往往是错误的,但比这更有细微差别。标准中对未定义行为的识别如下。

  • 当违反了 "应当 "或 "不应当 "的要求,并且该要求出现在约束条件之外时,该行为是未定义的

  • 当行为被明确规定为 "未定义行为 "时

  • 通过省略任何明确的行为定义
    前两种未定义行为经常被称为显式未定义行为,而第三种则被称为隐式未定义行为。这三者之间的重点没有区别,它们都描述了未定义的行为。C语言标准附件J.2 "未定义行为 "包含了C语言中显式未定义行为的列表。

开发者经常误认为未定义的行为是C标准中的错误或遗漏,但将行为归为未定义的决定是有意的,也是经过考虑的。C标准委员会将行为归类为未定义的行为是为了做到以下几点。

  • 给予实现者许可,使其不去捕捉难以诊断的程序错误
  • 避免定义晦涩难懂的案例,使之有利于一种实现策略而不是另一种策略
  • 识别可能的符合要求的语言扩展领域,在这些领域中,实现者可以通过提供官方未定义行为的定义来增强语言。
    这三个原因实际上是完全不同的,但都被认为是可移植性问题。编译器(实现)有做以下事情的余地。
  • 完全忽略未定义的行为,产生不可预测的结果
  • 以环境特征的文件方式行事(有或没有发出诊断书)。
  • 终止翻译或执行(发出诊断)。

这些选项都不是很好(尤其是第一个),所以最好避免未定义的行为,除非实现指定这些行为的定义是为了让你调用一个语言增强功能。

  • 特定于本地的行为和通用扩展

特定于本地的行为取决于每个实现所记录的国籍、文化和语言的本地惯例。通用扩展在许多系统中被广泛使用,但并不能移植到所有的实现中。

小结

在这章中,你学会了如何编写简单的C语言程序,编译它,并运行它。然后,我们看了几个编辑器和交互式开发环境,以及一些编译器,你可以用它们来开发Windows、Linux和macOS系统上的C语言程序。一般来说,你应该使用较新版本的编译器和其他工具,因为它们往往支持C编程语言的较新功能,并提供更好的诊断和优化。如果较新版本的编译器破坏了你现有的代码,或者你正准备部署你的代码,你可能不想使用较新版本的编译器,以避免在你已经测试过的应用程序中引入不必要的变化。在本章的最后,我们讨论了C语言程序的可移植性。

高效c语言1快速入门

原文链接:https://www.cnblogs.com/testing-/p/17387023.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:高效c语言1快速入门 - Python技术站

(0)
上一篇 2023年5月7日
下一篇 2023年5月11日

相关文章

  • QML和QT

    推荐一些学习qml教程 Qt官方的QML教程: https://doc.qt.io/qt-5/qtqml-index.html这是一个由Qt官方提供的完整的QML教程,包含了所有基本知识和高级语法。 QML中文网:http://www.qmlcn.com/这是一个非常不错的中文QML学习网站,提供了丰富的例子和教程,而且有很多QML爱好者在这里交流。 《Qt…

    C++ 2023年4月18日
    00
  • 【Visual Leak Detector】配置项 ReportTo

    说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍 VLD 配置文件中配置项 ReportTo 的使用方法。同系列文章目录可见 《内存泄漏检测工具》目录 目录 说明 1. 配置文件使用说明 2. 设置报告输出的位置 2.1 测试代码 2.2 ReportTo = debugger 时的输出 2.3 ReportTo = file 时的输出…

    C++ 2023年4月18日
    00
  • 记一次 腾讯会议 的意外崩溃分析

    一:背景 1. 讲故事 前段时间在用 腾讯会议 直播的时候,居然意外崩溃了,还好不是在训练营上课,不然又得重录了,崩完之后发现 腾讯会议 的 bugreport 组件会自动生成一个 minidump,截图如下: 作为一个.NET高级调试的技术博主,非 .NET 的程序也得要研究研究哈???,有了这个好奇心,也有了这个 dump,接下来用 windbg 看一看…

    C++ 2023年4月22日
    00
  • 驱动开发:通过MDL映射实现多次通信

    在前几篇文章中LyShark通过多种方式实现了驱动程序与应用层之间的通信,这其中就包括了通过运用SystemBuf缓冲区通信,运用ReadFile读写通信,运用PIPE管道通信,以及运用ASYNC反向通信,这些通信方式在应对一收一发模式的时候效率极高,但往往我们需要实现一次性吐出多种数据,例如ARK工具中当我们枚举内核模块时,往往应用层例程中可以返回几条甚至…

    C++ 2023年4月30日
    00
  • 【Visual Leak Detector】库的 22 个 API 使用说明

    说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇主要介绍 VLD 库提供的 22 个外部接口。同系列文章目录可见 《内存泄漏检测工具》目录 目录 说明 1. 头文件简介 2. 文件 vld_def.h 简介 3. 文件 vld.h 简介 3.1 接口 VLDDisable 3.2 接口 VLDEnable 3.3 接口 VLDRestore…

    C++ 2023年4月17日
    00
  • C++基础1: 命名空间

    0. 前言 C++是在C语言基础之上的一门语言, 所以学习C++的第一步是思考C++是如何优化C语言设计中的一些不足, 如作用域, IO , 函数, 指针, 宏等 这些内容同时也是为之后学习C++类和对象打基础, 下面说一下C++是如何优化C语言中的作用域 1. 命名空间 在说明命名空间的概念和如何优化C作用域之前, 首先来看一个例子 如图, 编译器报ran…

    C++ 2023年4月19日
    00
  • 2023.5.5 面向对象程序设计实验报告

    实验项目名称:模板 一、实验目的 1、熟练掌握函数模板和类模板的定义格式。 2、熟练运用函数模板和类模板解决实际问题。 二、实验内容 1、复数类Complex有两个数据成员:a和b, 分别代表复数的实部和虚部,并有若干构造函数和一个重载-(减号,用于计算两个复数的距离)的成员函数。 要求设计一个函数模板 template < class T > …

    C++ 2023年5月5日
    00
  • 最少步数

    在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就想试一试,在一个(100*100)的围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一…

    C++ 2023年4月25日
    00
合作推广
合作推广
分享本页
返回顶部