《C Primer Plus》学习笔记—第15章

《C Primer Plus》学习笔记

第15章 位操作

在C语言中,可以单独操控变量中的位。有时必须单独操控位,例如,通常向硬件设备发送一两个字节来控制这些设备,其中每个位(bit)都有特定的含义。另外,与文件相关的操作系统信息经常被储存,通过使用特定位表明特定项。许多压缩和加密操作都是直接处理单独的位。C在提供高级语言便利的同时,还能在为汇编语言所保留的级别上工作,这使其成为编写设备驱动程序和嵌入式代码的首选语言。

1.二进制数、位和字节

通常都是基于数字10来书写数字。例如2157的千位是2,百位是1,十位是5,个位是7,可以写成:
2x1000 + 1x100 + 5x10 + 7x1
注意,1000是10的立方(即3次幂),100是10的平方(即2次幂),10是10的1次幂,而且10(以及任意正数)的0次幂是1。因此,2157也可以写成:
2x10³ + 1x10² + 5x10¹ + 7x10º
因为这种书写数字的方法是基于10的幂,所以称以10为基底书写2157。
从某种意义上看,计算机的位只有2根手指,因为它只能被设置为0或1,关闭或打开。因此,计算机适用基底为2的数制系统。它用2的幂而不是10的幂。以2为基底表示的数字被称为二进制数(binary mumber)。二进制中的2和十进制中的10作用相同。例如,二进制数1101可表示为:
1x2³ + 1x2² + 0x2¹ + 1x2°
以十进制数表示为:
1x8 +1x4+0x2+1x1= 13
用二进制系统可以把任意整数(如果有足够的位)表示为0和1的组合。由于数字计算机通过关闭和打开状态的组合来表示信息,这两种状态分别用0和1来表示。

1.二进制整数

通常,1字节包含8位。C语言用字节(byte)表示储存系统字符集所需的大小,所以C字节可能是8位、9位、16位或其他值。不过,描述存储器芯片和数据传输率中所用的字节指的是8位字节。假设1字节是8位(计算机界通常用八位组(octet) 这个术语特指8位字节)。可以从左往右给这8位分别编号为7~0。在1字节中,编号是7的位被称为高阶位(high-order bit),编号是0的位被称为低阶位(low-order bit)。每1位的编号对应2的相应指数。因此,可以根据图15.1所示的例子理解字节。

位编号和位置

这里,128是2的7次幂,以此类推。该字节能表示的最大数字是把所有位都设置为1: 11111111这个二进制数的值是:
128+64+32+16+8+4+2+1=255
而该字节最小的二进制数是00000000,其值为0。因此, 1字节可储存0~255范围内的数字,总共256个值。或者,通过不同的方式解释位组合(bit pattern),程序可以用1字节储存-128~+127范围内的整数,总共还是256个值。例如,通常unsigned char用1字节表示的范围是0~255,而signed char用1字节表示的范围是-128~+127。

2.有符号整数

如何表示有符号整数取决于硬件,而不是C语言。也许表示有符号数最简单的方式是用1位(如,高阶位)储存符号,只剩下7位表示数字本身(假设储存在1字节中)。用这种符号量(sign-magniude) 表示法,00000001表示-1, 10000001表示1。因此,其表示范围是-127~+127。
这种方法的缺点是有两个0: +0和-0。这很容易混淆,而且用两个位组合来表示一个值也有些浪费。

二进制补码(two s-complement)方法避免了这个问题,是当今最常用的系统。以1字节为例,讨论这种方法。二进制补码用1字节中的后7位表示0~127,高阶位设置为0。目前,这种方法和符号量的方法相同。另外,如果高阶位是1,表示的值为负。这两种方法的区别在于如何确定负值。从一个9位组合100000000(256 的二进制形式)减去一个负数的位组合,结果是该负值的量。例如,假设一个负值的位组合是10000000,作为一个无符号字节,该组合为表示128; 作为一个有符号值,该组合表示负值(编码是7的位为1),而且值为100000000-10000000,即10000000(128)。因此,该数是-128(在符号量表示法中,该位组合表示-0)。类似地,10000001是-127,11111111是-1。该方法可以表示-128~+127范围内的数。
要得到一个二进制补码数的相反数,最简单的方法是反转每一位(即0变为1,1变为0),然后加1。因为1是00000001,那么-1则是11111110+1,或11111111。这与上面的介绍一致。

二进制反码(one s-complement)方法通过反转位组合中的每一位形成一个负数。例如,00000001是1,那么11111110是-1。这种方法也有一个-0: 11111111该方法能表示-127~+127之间的数。

3.二进制浮点数

浮点数分两部分储存:二进制小数和二进制指数。

1.二进制小数

一个普通的浮点数0.527,表示如下:
5/10 + 2/100 + 7/1000
从左往右,各分母都是10的递增次幂。在二进制小数中,使用2的幂作为分母,所以二进制小数.101表示为:
1/2+0/4+1/8
用十进制表示法为:
0.50 + 0.00 + 0.125
即是0.625。
许多分数(如,1/3) 不能用十进制表示法精确地表示。与此类似,许多分数也不能用二进制表示法准确地表示。实际上,二进制表示法只能精确地表示多个1/2的幂的和。因此,3/4和7/8可以精确地表示为二进制小数,但是1/3和2/5却不能。

2.浮点数表示法

为了在计算机中表示一个浮点数,要留出若干位(因系统而异)储存二进制分数,其他位储存指数。
一般而言,数字的实际值是由二进制小数乘以2的指定次幂组成。例如,一个浮点数乘以4,那么二进制小数不变,其指数乘以2,二进制分数不变。如果一份浮点数乘以一个不是2的幂的数,会改变二进制小数部分,如有必要,也会改变指数部分。

2.其他进制数

计算机界通常使用八进制记数系统和十六进制记数系统。因为8和16都是2的幂,这些系统比十进制系统更接近计算机的二进制系统。

1.八进制

八进制(octal)是指八进制记数系统。该系统基于8的幂,用07表示数字(正如十进制用09表示数字一样)。例如,八进制数451(在C中写作0451)表示为:
4x8²+5x8¹+1x8°=297(十进制).
了解八进制的一个简单的方法是,每个八进制位对应3个二进制位。表15.1列出了这种对应关系。这种关系使得八进制与二进制之间的转换很容易。例如,八进制数0377的二进制形式是11111111。即,用111代替0377中的最后一个7,再用111代替倒数第2个7,最后用011代替3,并舍去第1位的0。这表明比0377大的八进制要用多个字节表示。这是八进制唯一不方便的地方:一个3位的八进制数可能要用9位二进制数来表示。注意,将八进制数转换为二进制形式时,不能去掉中间的0。例如,八进制数0173的二进制形式是01111011,不是0111111。

八进制与二进制

2.十六进制

十六进制(hexadecimal或hex)是指十六进制记数系统。该系统基于16的幂,用015表示数字。但是,由于没有单独的数(digit,即09这样单独一位的数)表示1015,所以用字母AF来表示。例如,十六进制数A3F(在C中写作0xA3F)表示为:
10x162 +3x16’+ 15x16° = 2623(十进制)
由于A表示10, F表示15。在C语言中,A~F既可用小写也可用大写。因此,2623也可写作0xa3f。
每个十六进制位都对应一个4位的二进制数(即4个二进制位),那么两个十六进制位恰好对应一个8位字节。第1个十六进制表示前4位,第2个十六进制位表示后4位。因此,十六进制很适合表示字节值。
表15.2列出了各进制之间的对应关系。例如,十六进制值0xC2可转换为11000010。相反,二进制值11010101可以看作是1101 0101,可转换为0xD5。

十进制、十六进制、二进制

C有两个操控位的工具。第1个工具是一套(6个)作用于位的按位运算符第2个工具是字段(field)数据形式,用于访问int中的位。

3.C按位运算符

C提供按位逻辑运算符和移位运算符。在下面的例子中,为了方便读者了解位的操作,我们用二进制记数法写出值。但是在实际的程序中不必这样,用一般形式的整型变量或常量即可。例如,在程序中用25或031或0x19, 而不是00011001。另外,下面的例子均使用8位二进制数,从左往右每位的编号为7~0。

1.按位逻辑运算符

4个按位逻辑运算符都用于整型数据,包括char之所以叫作按位(binwvise)运算,是因为这些操作都是针对每一个位进行,不影响它左右两边的位。不要把这些运算符与常规的逻辑运算符(&&、||和!)混淆,常规的逻辑运算符操作的是整个值。

1.二进制反码或按位取反: ~

一元运算符~1变为0,把0变为1。如下例子所示:

~(10011010) // 表达式
(01100101)//结果值

假设val的类型是unsigned char,已被赋值为2。在二进制中,00000010表示2。那么,~val的值是1111101,即253。注意,该运算符不会改变val的值,就像3 * val不会改变val的值一样,val仍然是2。但是,该运算符确实创建了一个可以使用或赋值的新值:

newval = ~val;
printf("%d", ~val);

如果要把val的值改为~val,使用下面这条语句:

val = ~val;
2.按位与: &

二元运算符&通过逐位比较两个运算对象,生成一个新值。 对于每个位,只有两个运算对象中相应的位都为1时,结果才为1(从真/假方面看,只有当两个位都为真时,结果才为真)。因此,对下面的表达式
求值:

(10010011) & (00111101)//表达式

由于两个运算对象中编号为4和0的位都为1,得:

(00010001) //结果值

C有一个按位与和赋值结合的运算符:&=。下面两条语句产生的最终结果相同:

val &= 0377;
val = val & 0377;
3.按位或: |

二元运算符|,通过逐位比较两个运算对象,生成一个新值。对于每个位,如果两个运算对象中相应的位为1,结果就为1(从真/假方面看,如果两个运算对象中相应的一个位为真或两个位都为真,那么结果为真)。因此,对下面的表达式求值:

(10010011) | (00111101) // 表达式

除了编号为6的位,这两个运算对象的其他位至少有一个位为1,得:

(10111111) // 结果值

C有一个按位或和赋值结合的运算符:|=。下面两条语产生的最终作用相同:

val |= 0377;
val = val| 0377;
4.按位异或: ^

二元运算符^逐位比较两个运算对象。对于每个位,如果两个运算对象中相应的位一个为1(但不是两个为1),结果为1(从真/假方面看,如果两个运算对象中相应的一个位为真且不是两个为同为1,那么结果为真)。因此,对下面表达式求值:

(10010011) ^ (00111101) // 表达式

编号为0的位都是1,所以结果为0,得:

(10101110) // 结果值

C有一个按位异或和赋值结合的运算符:^=。下面两条语句产生的最终作用相同:

val ^= 0377;
val = val ^ 0377;
2.用法:掩码

按位与运算符常用于掩码(mask)。所谓掩码指的是一些设置为开(1)或关(0)的位组合。假设定义符号常量MASK为2(即,二进制形式为00000010),只有1号位是1,其他位都是0。下面的语句:

flags = flags & MASK;

把flags中除1号位以外的所有位都设置为0,因为使用按位与运算符(&)任何位与0组合都得0。1号位的值不变(如果1号位是1,那么1&1得1;如果1号位是0,那么0&1也得0)。这个过程叫作“使用掩码”,因为掩码中的0隐藏了flags中相应的位。
可以这样类比:把掩码中的0看作不透明,1看作透明。表达式flags & MASK相当于用掩码覆盖在flags的位组合上,只有MASK为1的位才可见(见图15.2)。

掩码

用&=运算符可以简化前面的代码,如下所示:

flags &= MASK;

下面这条语句是按位与的一种常见用法:

ch &= 0xff;//或者ch&=0377;

前面介绍过oxff的二进制形式是11111111,八进制形式是0377。这个掩码保持ch中最后8位不变,其他位都设置为0。无论ch原来是8位、16 位或是其他更多位,最终的值都被修改为1个8位字节。在该例中,掩码的宽度为8位。.

3.用法:打开位(设置位)

有时,需要打开一个值中的特定位,同时保持其他位不变。例如,一台IBM PC通过向端口发送值来控制硬件。例如,为了打开内置扬声器,必须打开1号位,同时保持其他位不变。这种情况可以使用按位或运算符(|)
以上一节的flags和MASK (只有1号位为1)为例。下面的语句:

flags = flags | MASK;

把flags的1号位设置为1,且其他位不变。因为使用|运算符,任何位与0组合,结果都为本身;任何位与1组合,结果都为1。例如,假设flags是00001111,MASK是10110110。下面的表达式:

flags| MASK

即是:

(00001111) | (10110110)//表达式

其结果为:

(10111111)//结果值

MASK中为1的位,flags 与其对应的位也为1。MASK 中为0的位,flags与其对应的位不变。
用|=运算符可以简化上面的代码,如下所示:

flags |= MASK;

同样,这种方法根据MASK中为1的位,把flags中对应的位设置为1,其他位不变。

4.用法:关闭位(清空位)

和打开特定的位类似,有时也需要在不影响其他位的情况下关闭指定的位。假设要关闭变量flags中的1号位。同样,MASK只有1号位为1 (即,打开)。可以这样做:

flags = flags & ~MASK;

由于MASK除1号位为1以外,其他位全为0,所以~MASK除1号位为0以外,其他位全为1。使用&,任何位与1组合都得本身,所以这条语句保持1号位不变,改变其他各位。另外,使用&,任何位与0组合都的0。所以无论1号位的初始值是什么,都将其设置为0。
例如,假设flags是00001111,MASK是10110110。下面的表达式:

flags & ~MASK

即是:

(00001111) & ~(10110110) //表达式

其结果为:

(00001001)//结果值

MASK中为1的位在结果中都被设置(清空)为0。flags中与MASK为0的位相应的位在结果中都未改变。
可以使用下面的简化形式:

flags &= ~MASK; 
5.用法:切换位

切换位指的是打开已关闭的位,或关闭已打开的位。可以使用**按位异或运算符()切换位**。也就是说,假设b是一个位(1或0),如果为1,则1b为0;如果b为0,则1b为1。另外,无论b为1还是0,0b均为b。因此,如果使用^组合一个值和一个掩码,将切换该值与MASK为1的位相对应的位,该值与MASK为0的位相对应的位不变。要切换flags中的1号位,可以使用下面两种方法:

flags = flags ^ MASK;
flags ^= MASK;

例如,假设flags是00001111,MASK是10110110,表达式:

flags ^ MASK

即是:

(00001111) ^ (10110110)//表达式

其结果为:

(10111001)//结果值

flags中与MASK为1的位相对应的位都被切换了,MASK为0的位相对应的位不变。

6.用法:检查位的值

有时,需要检查某位的值。例如,flags中1号位是否被设置为1?不能这样直接比较flags和MASK:

if (flags == MASK)
puts("wow!"); //不能正常工作

这样做即使flags的1号位为1,其他位的值会导致比较结果为假。因此,必须覆盖flags中的其他位,只用1号位和MASK比较:

if ((flags & MASK) == MASK)
puts("Wow!");

由于按位运算符的优先级比==低,所以必须在flags & MASK周围加上圆括号。为了避免信息漏过边界,掩码至少要与其覆盖的值宽度相同。

7.移位运算符

下面介绍C的移位运算符。移位运算符向左或向右移动位。在示例中仍然使用二进制数,有助于理解其工作原理。

1.左移:<<

左移运算符(<<)将其左侧运算对象每一位的值向左移动其右侧运算对象指定的位数。左侧运算对象移出左末端位的值丢失,用0填充空出的位置。下面的例子中,每一位都向左移动两个位置:

(10001010) << 2 //表达式
(00101000)//结果值

该操作产生了一个新的位值,但是不改变其运算对象。例如,假设stonk为1,那么stonk << 2为4,但是stonk本身不变,仍为1。可以使用左移赋值运算符(<<=)来更改变量的值。该运算符将变量中的位向左移动其右侧运算对象给定值的位数。如下例:

int stonk = 1;
int onkoo;
onkoo = stonk << 2;//把4赋给onkoo
stonk <<= 2;//把stonk的值改为4
2.右移:>>

右移运算符(>>)将其左侧运算对象每一位的值向右移动其右侧运算对象指定的位数。左侧运算对象移出右末端位的值丢。对于无符号类型,用0填充空出的位置;对于有符号类型,其结果取决于机器。空出的位置可用0填充,或者用符号位(即,最左端的位)的副本填充:

(10001010) >> 2//表达式,有符号值
(00100010)//在某些系统中的结果值
(10001010) >> 2//表达式,有符号值
(11100010)//在另一些系统上的结果值

下面是无符号值的例子:

(10001010) >> 2//表达式,无符号值
(00100010)//所有系统都得到该结果值

每个位向右移动两个位置,空出的位用0填充。
**右移赋值运算符(>>=)**将其左侧的变量向右移动指定数量的位数。如下所示:

int sweet = 16;
int ooosw;
ooosw = sweet >> 3;//ooosw = 2,sweet的值仍然为16
sweet >>= 3;// sweet的值为2
3.用法:移位运算符

移位运算符针对2的幂提供快速有效的乘法和除法:
number << n number乘以2的n次幂
number >> n 如果number为非负,则用number除以2的n次幂
这些移位运算符类似于在十进制中移动小数点来乘以或除以10。

移位运算符还可用于从较大单元中提取一些位。 例如,假设用一个unsigned long类型的值表示颜色值,低阶位字节储存红色的强度,下一个字节储存绿色的强度,第3个字节储存蓝色的强度。随后你希望把每种颜色的强度分别储存在3个不同的unsigned char类型的变量中。那么,可以使用下面的语句:

#define BYTE MASK 0xff
unsigned long color = 0x002a162f;
unsigned char blue, green, red;
red = color & BYTE_MASK;
green = (color >> 8) & BYTE_MASK;
blue = (color >> 16) & BYTE_MASK;

以上代码中,使用右移运算符将8位颜色值移动至低阶字节,然后使用掩码技术把低阶字节赋给指定的变量。

8.编程示例

在第9章中,用递归的方法编写了一个程序,把数字转换为二进制形式(程序binary.c)。现在,要用移位运算符来解决相同的问题。程序binbit.c中的程序,读取用户从键盘输入的整数,将该整数和一个字符串地址传递给itobs()函數(itobs表示interger to binary string,即整数转换成:二进制字符串)。然后,该函数使用移位运算符计算出正确的1和0的组合,并将其放入字符串中。

/* binbit.c -- 使用位操作显示二进制 */
#include <stdio.h>
#include <limits.h>  // 提供CHAR_BIT的定义,CHAR_BIT表示每字节的位数 
char * itobs(int, char *);
void show_bstr(const char *);

int main(void)
{
   
    char bin_str[CHAR_BIT * sizeof(int) + 1];// 8 * 4 + 1
    int number;
    
    puts("Enter integers and see them in binary.");
    puts("Non-numeric input terminates program.");
    while (scanf("%d", &number) == 1)
    {
   
        itobs(number,bin_str);//假设输入3 
        printf("%d is ", number);
        show_bstr(bin_str);
        putchar('\n');
    }
    puts("Bye!");
    
    return 0;
}

char * itobs(int n, char * ps)// 3的二进制:00000000 00000000 00000000 00000011
{
   
    int i; 
    const static int size = CHAR_BIT * sizeof(int);// size = 32 
    
    for (i = size - 1; i >= 0; i--, n >>= 1)//i = 31开始
	{
   
		ps[i] = (01 & n) + '0';
		//01在这是掩码,八进制形式,表示十进制1,二进制是00000000 00000000 00000000 00000001
		//'0'在ascll中表示48,(01 & n)的值为1,那么1+48=49,是字符'1',存入字符数组中
		//char grade='A';与char grade=65;等效(前提是系统能使用ASCLL码) 
	}        
    ps[size] = '\0';
    
    return ps;
}

/* 4位一组显示二进制字符串 */
void show_bstr(const char * str)
{
   
    int i = 0;
    
    while (str[i])  /* 不是一个空字符 */
    {
   
        putchar(str[i]);
        if(++i % 4 == 0 && str[i])
            putchar(' ');
    }
}

输出示例:

Enter integers and see them in binary.
Non-numeric input terminates program.
3
3 is 0000 0000 0000 0000 0000 0000 0000 0011
2013
2013 is 0000 0000 0000 0000 0000 0111 1101 1101
-1
-1 is 1111 1111 1111 1111 1111 1111 1111 1111
q
Bye!

程序binbit.c使用limits.h中的CHAR_ BIT宏,该宏表示char中的位数。sizeof运算符返回char的大小,所以表达式CHAE_BIT * sizeof(int)表示int类型的位数。bin_str数组的元素个数是CHAE_BIT * sizeof(int) + 1, 留出一个位置给末尾的空字符。

itobs()函数返回的地址与传入的地址相同,可以把该函数作为printf()的参数。在该函数中,首次执行for循环时,对01 & n求值。01是一个八进制形式的掩码,该掩码除0号位是1之外,其他所有位都为0。因此,01 & n就是n最后一位的值。该值为0或1。但是对数组而言,需要的是字符’0’或字符’1’。该值加上’0’即可完成这种转换(假设按顺序编码的数字,如ASCII)。 其结果存放在数组中倒数第2个元素中(最后一个元素用来存放空字符)。

顺带一提,用1 & n或01 & n都可以。用八进制1而不是十进制1,只是为了更接近计算机的表达方式。

然后,循环执行i–和n >>= 1。i–移动到数组的前一个元素,n >>= 1使n中的所有位向右移动一个位置。进入下一轮迭代时,循环中处理的是n中新的最右端的值。然后,把该值储存在倒数第3个元素中,以此类推。itobs ()函数用这种方式从右往左填充数组。
可以使用printf()或puts()函数显示最终的字符串,但是程序binbit.c中定义了show_bstr()函数,以4位一组打印字符串,方便阅读。

9.另一个例子

这次要编写的函数用于切换一个值中的后n位,待处理值和n都是函数的参数。
~运算符切换一个字节的所有位,而不是选定的少数位。但是,**运算符(按位异或)可用于切换单个位**。假设创建了一个掩码,把后n位设置为1,其余位设置为0。然后使用组合掩码和待切换的值便可切换该值的最后n位,而且其他位不变。方法如下:

cint invert end(int num,int bits)
{
	int mask = 0;
    int bitval = 1;
    while (bits-- > 0)
    {
    	mask |= bitval; 
    	bitval <<= 1;
    }
    return num ^ mask;
}

while循环用于创建所需的掩码。最初,mask的所有位都为0。第1轮循环将mask的0号位设置为1。然后第2轮循环将mask的1号位设置为1,以此类推。循环bits次,mask的后bits位就都被设置为1。最后,num ^ mask运算即得所需的结果。
把这个函数放入前面的程序中,测试该函数。如程序invert4.c所示。

1.程序invert4.c
/* invert4.c -- 使用位操作显示二进制 */
#include <stdio.h>
#include <limits.h>
char * itobs(int, char *);
void show_bstr(const char *);
int invert_end(int num, int bits);

int main(void)
{
   
    char bin_str[CHAR_BIT * sizeof(int) + 1];
    
    int number;
    
    puts("Enter integers and see them in binary.");
    puts("Non-numeric input terminates program.");
    while (scanf("%d", &number) == 1)
    {
   
        itobs(number,bin_str);
        printf("%d is\n", number);
        show_bstr(bin_str);
        putchar('\n');
        number = invert_end(number, 2);
        printf("Inverting the last 2 bits gives\n");
        show_bstr(itobs(number,bin_str));
        putchar('\n');
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 第七主要介绍了C语言中的函数,包括函数的定义、调用、参数传递、返回值等方面的内容。具体内容包括: 1. 函数的定义和调用:介绍了如何定义函数以及如何调用函数,包括函数的返回类型、函数名、参数列表和函数体等。 2. 函数的参数传递:介绍了C语言中的参数传递方式,包括值传递和地址传递,以及如何在函数中使用参数。 3. 函数的返回值:介绍了函数的返回值类型和返回值的作用,以及如何在函数中使用返回值。 4. 函数的声明和定义:介绍了函数的声明和定义的区别,以及如何在不同的文件中使用函数。 5. 函数的递归:介绍了递归函数的概念和使用方法,以及递归函数的优缺点。 6. 函数指针:介绍了函数指针的概念和使用方法,以及如何在程序中使用函数指针。 总的来说,第七C语言中非常重要的一,对于理解和使用函数有很大的帮助。 ### 回答2: 《C Primer Plus》第六版第七主要介绍了C语言中的输入和输出函数。这的内容包括标准I/O库、`printf()`、`scanf()`等函数以及文件输入输出等。 在这一中,首先讲解了如何使用标准I/O库进行输入输出。标准I/O库提供了一组函数,可以用于从键盘读取输入,或将结果输出到屏幕上。`printf()`函数可以用于格式化输出,可以控制输出的格式,比如输出特定长度的整数、浮点数等。`scanf()`函数可以用于从键盘读取输入,并将其存储到变量中,也可以使用特定的格式来读取特定类型的数据。 接下来,讲解了如何使用`getchar()`和`putchar()`函数。`getchar()`函数用于从键盘读取单个字符,`putchar()`函数用于向屏幕输出单个字符。 此外,还介绍了文件的输入输出。通过使用`fopen()`函数打开文件,可以读取或写入文件的内容。使用`fprintf()`函数可以将数据写入文件中,使用`fscanf()`函数可以从文件中读取数据并存储到变量中。同时还介绍了如何使用`fclose()`函数关闭文件。 最后,本还讲解了格式化输出的一些高级特性,比如控制字段宽度、对齐方式以及使用转换说明符等。 通过学习《C Primer Plus》第六版第七,我们能够了解C语言中输入输出的基本概念和原理,掌握使用输入输出库函数进行读写操作的方法,以及如何进行文件的读写操作。这对于日后编写C语言程序以及处理文件输入输出都有着重要的作用。 ### 回答3: C Primer Plus第六版第七主要介绍了C语言中的函数。函数是一段完成特定任务的可重复使用的代码块,它可以接收输入参数并返回一个值。 在这一中,我们学习了如何定义函数并明确函数的返回类型、函数名和参数列表。通过使用函数,我们可以将程序中的代码划分为更小、更可管理的部分。函数的主要好处之一是提高了代码的可读性和可维护性。 我们还学习了传递参数的不同方式,包括按值传递、按地址传递以及传递指针。这些方法允许我们在函数之间传递数据,并在函数内部对数据进行修改。 此外,我们还研究了递归函数的概念。递归函数是指可以调用自身的函数。使用递归可以通过将问题划分为更小的子问题来解决复杂的问题。 在这一中,我们还学习了函数的作用域和生命周期。函数的作用域定义了函数内部和外部变量的可见性。函数的生命周期指的是函数在程序运行期间的保持状态的时间。 最后,我们还讨论了函数的多文件组织和调用。通过将函数定义和函数声明分离到不同的文件中,我们可以更好地组织和管理大型项目的代码。 通过学习C Primer Plus第六版第七,我们可以更好地理解和应用函数在C语言中的重要性。掌握函数的知识将有助于我们编写更模块化、可读性更强、可维护性更高的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值