C language programming. from Operating Systems - Three Easy Pieces. Intro - Virtualization the CPU

本文从《Operating Systems - Three Easy Pieces》出发,探讨C语言编程中头文件的使用,包括尖括号和双引号的区别,以及如何理解和使用`stdio.h`等标准库。文章详细解析了`main()`函数的参数`argc`和`argv`,并介绍了`fprintf`、`printf`和`sprintf`的区别。此外,还提到了`common.h`文件中的条件编译宏的用途。
摘要由CSDN通过智能技术生成

前言

最近在看《Operating Systems - Three Easy Pieces》
发现自己C编程能力是真的弱啊,甚至读不懂。

一 代码段内容:

cpu.c文件

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

int main(int argc, char *argv[])
{
    if (argc != 2) {
	fprintf(stderr, "usage: cpu <string>\n");
	exit(1);
    }
    char *str = argv[1];

    while (1) {
	printf("%s\n", str);
	Spin(1);
    }
    return 0;
}

一开始报错 #include "common.h" 行。

  1. 系统自带的头文件用尖括号括起来,这样编译器会在系统文件目录下查找。
    #include <xxx.h>
  2. 用户自定义的文件用双引号括起来,编译器首先会在用户目录下查找,然后在到C++安装目录(比如VC中可以指定和修改库文件查找路径,Unix和Linux中可以通过环境变量来设定)中查找,最后在系统文件中查找。

在本书的github厂库中找到了官方给出的代码,里面有common.h文件。

#ifndef __common_h__
#define __common_h__

#include <sys/time.h>
#include <sys/stat.h>
#include <assert.h>

double GetTime() {
    struct timeval t;
    int rc = gettimeofday(&t, NULL);
    assert(rc == 0);
    return (double) t.tv_sec + (double) t.tv_usec/1e6;
}

void Spin(int howlong) {
    double t = GetTime();
    while ((GetTime() - t) < (double) howlong)
	; // do nothing in loop
}

#endif // __common_h__

Makefile中命令如下:

all: cpu mem threads io

clean:
	rm -f cpu mem threads io

cpu: cpu.c common.h
	gcc -o cpu cpu.c -Wall

mem: mem.c common.h
	gcc -o mem mem.c -Wall

threads: threads.c common.h common_threads.h
	gcc -o threads threads.c -Wall -pthread

io: io.c common.h
	gcc -o io io.c -Wall

二 代码段理解

2.1 cpu.c文件

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

#include "common.h"

stdio.h是标准io库
stdlib.h是标准库文件,包含了常用的系统函数。比如内存申请malloc()
用引号标识的common.h是用户自定义的头文件

common.h的文件内容定义如下:

#ifndef __common_h__
#define __common_h__

#include <sys/time.h>
#include <sys/stat.h>
#include <assert.h>

double GetTime() {
    struct timeval t;
    int rc = gettimeofday(&t, NULL);
    assert(rc == 0);
    return (double) t.tv_sec + (double) t.tv_usec/1e6;
}

void Spin(int howlong) {
    double t = GetTime();
    while ((GetTime() - t) < (double) howlong)
	; // do nothing in loop
}

#endif // __common_h__

可以看到在这个文件中,定义了Spin函数。就是不断的循环,直到发现距离调用该函数的过去了1秒。
具体的在下一部分对common.h的分析中解释

int main(int argc, char *argv[])
{
    if (argc != 2) {
	fprintf(stderr, "usage: cpu <string>\n");
	exit(1);
    }
    char *str = argv[1];

    while (1) {
	printf("%s\n", str);
	Spin(1);
    }
    return 0;
}

这一部分中关注了从来没注意过的main()函数参数问题。参考资料

通常我们在写主函数时都是void main()或int main() {…return 0;},但ANSI-C(美国国家标准协会,C的第一个标准ANSI发布)在C89/C99中main()函数主要形式为:

  1. int main(void)
  2. int main(int argc,char *argv[]) = int main(int argc,char **argv).

其参数argc和argv用于运行时,把命令行参数传入主程序.其中ARG是指arguments,即参数.具体含义如下:
(参照Arguments to main和C++ Primer7.2.6节)

  1. int argc:英文名为arguments count(参数计数)
    count of cmd line args,运行程序传送给main函数的命令行参数总个数,包括可执行程序名,其中当argc=1时表示只有一个程序名称,此时存储在argv[0]中.
  2. char **argv:英文名为arguments value/vector(参数值)
    pointer to table of cmd line args,字符串数组,用来存放指向字符串参数的指针数组,每个元素指向一个参数,空格分隔参数,其长度为argc.数组下标从0开始,argv[argc]=NULL.
    argv[0] 指向程序运行时的全路径名
    argv[1] 指向程序在DOS命令中执行程序名后的第一个字符串
    argv[2] 指向执行程序名后的第二个字符串
int main(int argc, char *argv[])
{
    if (argc != 2) {
	fprintf(stderr, "usage: cpu <string>\n");
	exit(1);
    }

为什么判断条件是 argc!=2呢?
因为main函数有一个默认参数:程序运行时的全路径名
然后是运行时后面跟的字符串
如果跟了两个参数,那么argc实际上是3

wby@ubuntu:~/Documents/ostep-code-master/intro$ ./cpu a b
usage: cpu <string>

下半段代码中,我们发现使用了printf函数,但是上一段中使用的是fprintf函数,它们的区别在哪里呢?

    char *str = argv[1];

    while (1) {
	printf("%s\n", str);
	Spin(1);
    }
    return 0;

Difference between fprintf, printf and sprintf? ——Stack Overflow

fprintf writes formatted text to the output stream you specify.
fprintf将文本输出到用户指定的输出流中

printf is equivalent to writing fprintf(stdout, …) and writes formatted text to wherever the standard output stream is currently pointing.
(相当于使用fprintf将文本输出到标准输出流中)

sprintf writes formatted text to an array of char, as opposed to a stream.
将文本输出到指定字符串中,可以用来将大量数字数据转为字符串

stdin is a pointer to the standard input stream, stdout is a pointer to the standard output stream, and stderr is a pointer to the standard error output stream. In an interactive session, the three usually refer to your console, although you can redirect them to point to other files or devices:
一般而言,标准输入流,标准输出流,标准错误输出流都会指定到你的命令台中。但你也可以重新指定他们指向不同的文件或设备

$ myprog < inputfile.dat > output.txt 2> errors.txt

In this example, stdin now points to inputfile.dat, stdout points to output.txt, and stderr points to errors.txt.
通过上述的代码,标准输入流现在指向inputfile.dat文件…
实际使用如下:

./cpu a 2>errors.txt

errors.txt中内容为:

usage: cpu <string>

但是在我用./cpu a b >output.txt的时候有问题,控制台中不显示输出,output.txt中也没有任何内容。为什么呢?是因为输出流不断刷新,所以给弄没了吗?

2.2 common.h文件

#ifndef __common_h__
#define __common_h__

#include <sys/time.h>
#include <sys/stat.h>
#include <assert.h>

double GetTime() {
    struct timeval t;
    int rc = gettimeofday(&t, NULL);
    assert(rc == 0);
    return (double) t.tv_sec + (double) t.tv_usec/1e6;
}

void Spin(int howlong) {
    double t = GetTime();
    while ((GetTime() - t) < (double) howlong)
	; // do nothing in loop
}

#endif // __common_h__

这些条件编译用的宏,指在如果没有__common_h__这个标识符的时候,才进行编译。
参考:Why are #ifndef and #define used in C++ header files?

#ifndef __common_h__
#define __common_h__
....
#endif // __common_h__
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
The C programming Language 第二版英文版 內容列表 Table of Contents Preface.......................................................... Preface to the first edition..................................... Introduction..................................................... Chapter 1 - A Tutorial Introduction.............................. 1.1 Getting Started................................ 1.2 Variables and Arithmetic Expressions........... 1.3 The for statement.............................. 1.4 Symbolic Constants............................. 1.5 Character Input and Output..................... 1.5.1 File Copying.......................... 1.5.2 Character Counting.................... 1.5.3 Line Counting......................... 1.5.4 Word Counting......................... 1.6 Arrays......................................... 1.7 Functions...................................... 1.8 Arguments - Call by Value...................... 1.9 Character Arrays............................... 1.10 External Variables and Scope.................. Chapter 2 - Types, Operators and Expressions..................... 2.1 Variable Names................................. 2.2 Data Types and Sizes........................... 2.3 Constants...................................... 2.4 Declarations................................... 2.5 Arithmetic Operators........................... 2.6 Relational and Logical Operators............... 2.7 Type Conversions............................... 2.8 Increment and Decrement Operators.............. 2.9 Bitwise Operators.............................. 2.10 Assignment Operators and Expressions.......... 2.11 Conditional Expressions....................... 2.12 Precedence and Order of Evaluation............ Chapter 3 - Control Flow......................................... 3.1 Statements and Blocks.......................... 3.2 If-Else........................................ 3.3 Else-If........................................ 3.4 Switch......................................... 3.5 Loops - While and For.......................... 3.6 Loops - Do-While............................... 3.7 Break and Continue............................. 3.8 Goto and labels................................ Chapter 4 - Functions and Program Structure...................... 4.1 Basics of Functions............................ 4.2 Functions Returning Non-integers............... 4.3 External Variables............................. 4.4 Scope Rules.................................... 4.5 Header Files................................... 4.6 Static Variables................................ 4.7 Register Variables.............................. 4.8 Block Structure................................. 4.9 Initialization.................................. 4.10 Recursion...................................... 4.11 The C Preprocessor............................. 4.11.1 File Inclusion........................ 4.11.2 Macro Substitution.................... 4.11.3 Conditional Inclusion................. Chapter 5 - Pointers and Arrays.................................. 5.1 Pointers and Addresses......................... 5.2 Pointers and Function Arguments................ 5.3 Pointers and Arrays............................ 5.4 Address Arithmetic............................. 5.5 Character Pointers and Functions............... 5.6 Pointer Arrays; Pointers to Pointers........... 5.7 Multi-dimensional Arrays....................... 5.8 Initialization of Pointer Arrays............... 5.9 Pointers vs. Multi-dimensional Arrays.......... 5.10 Command-line Arguments........................ 5.11 Pointers to Functions......................... 5.12 Complicated Declarations...................... Chapter 6 - Structures........................................... 6.1 Basics of Structures........................... 6.2 Structures and Functions....................... 6.3 Arrays of Structures........................... 6.4 Pointers to Structures......................... 6.5 Self-referential Structures.................... 6.6 Table Lookup................................... 6.7 Typedef........................................ 6.8 Unions......................................... 6.9 Bit-fields..................................... Chapter 7 - Input and Output..................................... 7.1 Standard Input and Output....................... 7.2 Formatted Output - printf....................... 7.3 Variable-length Argument Lists.................. 7.4 Formatted Input - Scanf......................... 7.5 File Access..................................... 7.6 Error Handling - Stderr and Exit................ 7.7 Line Input and Output........................... 7.8 Miscellaneous Functions......................... 7.8.1 String Operations...................... 7.8.2 Character Class Testing and Conversion. 7.8.3 Ungetc................................. 7.8.4 Command Execution...................... 7.8.5 Storage Management..................... 7.8.6 Mathematical Functions................. 7.8.7 Random Number generation............... Chapter 8 - The UNIX System Interface............................ 8.1 File Descriptors............................... 8.2 Low Level I/O - Read and Write................. 8.3 Open, Creat, Close, Unlink..................... 8.4 Random Access - Lseek.......................... 8.5 Example - An implementation of Fopen and Getc.. 8.6 Example - Listing Directories.................. 8.7 Example - A Storage Allocator.................. Appendix A - Reference Manual.................................... A.1 Introduction................................... A.2 Lexical Conventions............................ A.2.1 Tokens................................ A.2.2 Comments.............................. A.2.3 Identifiers........................... A.2.4 Keywords.............................. A.2.5 Constants............................. A.2.6 String Literals....................... A.3 Syntax Notation................................ A.4 Meaning of Identifiers......................... A.4.1 Storage Class......................... A.4.2 Basic Types........................... A.4.3 Derived types......................... A.4.4 Type Qualifiers....................... A.5 Objects and Lvalues............................ A.6 Conversions.................................... A.6.1 Integral Promotion.................... A.6.2 Integral Conversions.................. A.6.3 Integer and Floating.................. A.6.4 Floating Types........................ A.6.5 Arithmetic Conversions................ A.6.6 Pointers and Integers................. A.6.7 Void.................................. A.6.8 Pointers to Void...................... A.7 Expressions.................................... A.7.1 Pointer Conversion.................... A.7.2 Primary Expressions................... A.7.3 Postfix Expressions................... A.7.4 Unary Operators....................... A.7.5 Casts................................. A.7.6 Multiplicative Operators.............. A.7.7 Additive Operators.................... A.7.8 Shift Operators....................... A.7.9 Relational Operators.................. A.7.10 Equality Operators................... A.7.11 Bitwise AND Operator................. A.7.12 Bitwise Exclusive OR Operator........ A.7.13 Bitwise Inclusive OR Operator........ A.7.14 Logical AND Operator................. A.7.15 Logical OR Operator.................. A.7.16 Conditional Operator................. A.7.17 Assignment Expressions............... A.7.18 Comma Operator.......................... A.7.19 Constant Expressions.................... A.8 Declarations..................................... A.8.1 Storage Class Specifiers................. A.8.2 Type Specifiers.......................... A.8.3 Structure and Union Declarations......... A.8.4 Enumerations............................. A.8.5 Declarators.............................. A.8.6 Meaning of Declarators................... A.8.7 Initialization........................... A.8.8 Type names............................... A.8.9 Typedef.................................. A.8.10 Type Equivalence........................ A.9 Statements....................................... A.9.1 Labeled Statements....................... A.9.2 Expression Statement..................... A.9.3 Compound Statement....................... A.9.4 Selection Statements..................... A.9.5 Iteration Statements..................... A.9.6 Jump statements.......................... A.10 External Declarations........................... A.10.1 Function Definitions.................... A.10.2 External Declarations................... A.11 Scope and Linkage............................... A.11.1 Lexical Scope........................... A.11.2 Linkage................................. A.12 Preprocessing................................... A.12.1 Trigraph Sequences...................... A.12.2 Line Splicing........................... A.12.3 Macro Definition and Expansion.......... A.12.4 File Inclusion.......................... A.12.5 Conditional Compilation................. A.12.6 Line Control............................ A.12.7 Error Generation........................ A.12.8 Pragmas................................. A.12.9 Null directive.......................... A.12.10 Predefined names....................... A.13 Grammar......................................... Appendix B - Standard Library.................................... B.1.1 File Operations................................ B.1.2 Formatted Output......................... B.1.3 Formatted Input.......................... B.1.4 Character Input and Output Functions..... B.1.5 Direct Input and Output Functions........ B.1.6 File Positioning Functions............... B.1.7 Error Functions.......................... B.2 Character Class Tests: ................. B.3 String Functions: ..................... B.4 Mathematical Functions: ................. B.5 Utility Functions: ....................
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值