首页 > 代码库 > 《C与指针》第十章练习

《C与指针》第十章练习

本章问题

1.成员和数组元素有什么区别?

answer:Structure members can be all different types;they are accessed by name;and unused memory may be between adjacent(邻近的) members to enforce(强制) boundary alignment requirements.Array elements must all be the same type;they are accessed with a subscript;and no space is ever lost between elements for boundary alignment.

(结构成员可能是完全不同的类型,它们通过名字访问并且在相邻的两个成员之间不使用内存而强制执行边界对齐的要求,数组元素必须是相同类型,它们通过下标访问,并且在任意两个边界对齐元素之间都没有内存空隙)

 

2.结构名和数组名有什么不同?

answer:A Structure is a scalar(标量).Like any other scalar,when the name of a structure is used as an R_value in an expression it refers to the values stored in the structure.when used as an L_value,the name refers to the place in which die structure is stored.when an array name is used as an R_value in an expression,however,its value is a pointer to the first element in the array,because its value is a constant pointer,an array name cannot be used as an L_value.

(结构是一个标量,像其他任何标量一样,当结构的名字在表达式中作为一个左值时它代表把值存储到结构中,当它作为一个右值使用时,它是指存储在芯片结构中的地方,当一个数组名在表达式中作为一个右值使用时,然而,它的值实际是一个指针,这个指针指向数组的第一个元素,因为它的值是一个常量指针,一个数组名不能被作为左值使用)

 

3.结构声明的语法有几个可选部分?请列出所有合法的结构声明形式,并解释每一个是如果实现的。

answer:

First,a declaration where all components are given:(首先,给出一个声明的所有组成成分)

技术分享

This declares x to be a stucture having two members,a and b,In addition,the structure tag S is created for use in future declarations.

(声明了x这个结构有两个成员a和b,除此之外,结构标签S在以后的声明中用来创建这个结构)

Omitting(省略) the tag field gives:(省略标签)

技术分享

which has the same effect as before,except that no tag is created.while other declarations may created more structure variables with indentical(相同的) members,it is possible to create any more variable with the samp type as z.

(这跟前面那个产生的结果相同,除了没有标签,然而其他声明使用相同的成员创建更多的结构时,不可能创建一个和z相同类型的变量)

Omitting the member list gives:(省略成员列表)

技术分享

which declares another structure variable y with the same type as x.

(声明了另一个结构变量y与x的类型相同)

Omitting the variable list gives:(省略变量列表)

技术分享

which simply defines the tag S for use in later declarations.

(简单定义一个标签S用于以后的声明)

Finally,there is the incomplete declaration

(最后,这是一个不完整声明)

技术分享

which informs the compiler that S is a sturcture tag to be defined later.

(告诉编译器S是一个结构标签并且它将在后面定义的信息)

 

4.下面的程序段有没有错误?如果有,错误在哪里?

struct abc{
        int a;
        int b;
        int c;
};
...
abc.a = 25;
abc.b = 15;
abc.c = -1;

answer: abc is the structure tag,not the name of a variable,so the assignment statement are illegal.

(abc是一个结构标签而不是一个变量的名字,所以赋值语句是非法的)

 

5.下面的程序段有没有错误?如果有,错误在哪里?

typedef struct{
        int a;
        int b;
        int c;
}abc;
...
abc.a = 25;
abc.b = 15;
abc.c = -1;

answer:abc is a type name,not the name of a variable,so the assignment statements are illegal.

(abc是一个类型名而不是一个变量的名字,所以赋值语句非法)

 

6.完成下面声明中对x的初始化,使成员a为3,b为字符串"hello",c为0.你可以假设x存储于静态内存中。

struct {
        int a;
        char b[10];
        float c;
} x = 

answer:

struct {
        int a;
        char b[10];
        float c;
} x = {
        3,"hello"
};

 

7.考虑下面这些声明和数据。

struct NODE{
    int a;
    struct NODE *b;
    struct NODE *c;
};

struct NODE nodes[5] = {
    {5, nodes + 3, NULL},
    {15, nodes + 4, nodes + 3},
    {22, NULL, nodes + 4},
    {12, nodes + 1, nodes},
    {18, nodes + 2, nodes + 1}
};
(other declarations...)
struct NODE *np = nodes + 2;
struct NODE **npp = &nodes[1].b;

 对下面的表达式求值,并写出它的值,同时,写明任何表达式求值过程中可能出现的副作用,你应该用最初显示的值对每个表达式求值(也就是说,不要使用某个表达式的结果来对下一个表达式求值)。假定nodes数组在内存中的起始位置为200,并且在这台机器上整数和指针的长度都是4个字节。

技术分享

answer:

 

 

expression value expression value
nodes 200 &node[3].c->a 200
nodes.a illegal &nodes->a 200
nodes[3].a 12 np nodes[2]
nodes[3].c 200 np->a 22
nodes[3].c->a 5 np->c->c->a 15
*nodes nodes[0] npp 216
*nodes.a illegal npp->a illegal
(*nodes).a 5 *npp 248
nodes->a 5 **npp nodes[4]
nodes[3].b->b 248 *npp->a illegal
*nodes[3].b->b nodes[4] (*npp)->a 18
&nodes 200 &np --
&nodes[3].a 236 &np->a 224
&nodes[3].c 244 &np->c->c->a 212

 

 

 

 

 

 

 

 

 

 

 

 

8.在一个16位的机器上,下面这个结构由于边界对齐浪费了多少空间?在一个32位机器上又是如何?

struct{
        char a;
        int b;
        char c;
};

answer:With 16 bit integers,two bytes are wasted,one after each character,with 32 bit integers,six are wasted,Note that sapce is lost after c in order to guarantee that the structure ends at the most stringent(严格的) boundary,if this were not done,the next variable allocated(分配) might not begin at the proper boundary.

(在16位机器上浪费2个字节,在每个字符后面浪费一个字节,在32位机器上浪费6个字节,注意c后面的空间被浪费是为了确保结构末尾的严格边界对齐,如果没有对齐,下一个变量分配时可能不是从一个合适的边界开始的)

 

9.至少说出两个位段为什么不可移植的理由?

answer:

a  whether the field are allocated right to left or left to right

(分配内存是从左向右还是从右向左)

b  whether field too large to fit in the remaining bits of a word begin there anyway and cross the boundary to the next word or begin in the next word;

(字段是否太大而无法放入剩余的位中,可能穿单元边界也可能从下一个单元开始)

c  whether signed or unsigned arithmetic is used for fields declared signed;

(声明类型是为signed还是unsigned)

d the maxinum size of an individual field.

(单个区域的最大值不同)

 

10.编写一个声明,允许根据下面的格式方便的访问一个浮点值的单独部分。

技术分享

 answer:

struct FLOAT{
        unsigned fraction    : 24;
        unsgined exponent    : 7;
        unsgined sign        :1;
};
//or
struct FLOAT{
        unsgined sign        :1;
        unsgined exponent    : 7;
        unsigned fraction    : 24;
};

 

11.如果不使用位段,你怎样实现下面这段代码的功能?假定你使用的是一台16位的机器,它从左向右为位段分配内存。

技术分享

answer:

x &= 0x0fff;
x |= (aaa & 0xf) << 12;
x &= 0xf00f;
x |= (bbb & 0xff) << 4;
x &= 0xfff1;
x |= (ccc & 0x7) <<1;
x &= 0xfffe;
x |= (ddd & 0x1);
//or
x = (aaa & 0xf) << 12 | (bbb & 0xff) << 4 | (ccc & 0x7) << 1 | (ddd & 0x1);
//or
x = aaa & 0xf;
x <<= 8;
x = bbb & 0xff;
x <<= 3;
x = ccc & 0x7;
x <<= 1;
x = ddd & 0x1;

 

12,下面这个代码段将打印出什么?

struct {
        int a    :2;
}x;
...
x.a = 1;
x.a += 1;
printf("%d\n",x.a);

answer:

It can either be 2 or -2,depending on whether the compiler uses signed or unsigned arithmetic.

(可能是2或者-2,依赖于编译器使用的是有符号运算还是无符号运算)

 

13.下面这个代码段有没有错误?如果有?错误在哪里?

union{
        int a;
        float b;
        char c;
}x;
...
x.a = 25;
x.b = 3.14;
x.c = x;
printf("%d %g %c\n",x,a, x.b, x.c);

answer: A union is being used as if it were a structure,On a machine with 32 bit integers and floats,the second assignment will completely replace the value stored by the first,and the last assignment will replace the first eight bits of the value stored by the second,the integer and floating-point members therefore print as garbage,but the character prints correctly.

(一个联合被当作结构使用,在一台32位机器上,第二个赋值表达式将会覆盖第一个表达式,最后一个赋值表达式将会取代第二个表达式存储的前八个位,所以整型和浮点型的成员将会打印一个垃圾值,不过字符的打印值是对的)

 

14.假定有些信息已经赋值给一个联合变量 ,我们该如何正确的提取这个信息呢?

answer:The same member that was used to store the data must also be used to read it.

(用于读取它的成员必须要跟用于存储它的成员相同)

 

15.下面的结构可以被一个BASIC解释器使用,用于记住变量的类型和值:

struct VARIABLE{
    enum {INT,FLOAT,STRING} type;
    union{
        int i;
        float f;
        char *s;
    }value;
};

如果结构改写成下面这种形式,会有什么不同呢?

struct VARIABLE{
    enum {INT,FLOAT,STRING} type;
    union{
        int i;
        float f;
        char s[MAX_STRING_LENGTH];
    }value;
};

answer:

First,the member s would store the actual value of the string rather than a pointer to the value,this means that the value would not have to be allocated elsewhere,which is an advantage,but this entails a terrible disadvantage:the structure now contain enough space to store the largest possible string,and nearly all of this space is wasted when integer and floating-point values are sotred,the original stucture did not have this problem because it only contained a pointer to the string value,not the value itself.

(首先,成员s将存储为一个实际的字符串值而不是一个指针,这意味着字符串的值将不会被分配到其他地方去,这是一个优点,不过这也带来了一个缺点,这个结构体现在包含了一个足够大的空间可以存储可能最大的字符串,当使用整型和浮点型存储的时候几乎全部的空间都被浪费,原来的结构体则不会有这个问题,因为它仅仅存储的是一个字符指针,而不是字符串本身)

 

本章练习

1.当你拨打一个长途电话的时候,电话公司所保存的信息包括你拨打电话的时间和日期。它还包括三个号码,你使用的那个号码,你呼叫的那个号码,以及你付账的那个号码,这些号码的每一个都由三个部分组成:区号,交换台和站号码,请为这些记帐信息编写一个结构声明。

answer:

struct PHONE_NUMBER{
    short area;
    short exchange;
    short station;
};

struct LONG_DISTANCE_BILL{
    short month;
    short day;
    short year;
    int time;
    struct PHONE_NUMBER called;
    struct PHONE_NUMBER calling;
    struct PHONE_NUMBER billed;
}

 

2.为一个信息系统编写一个声明,它用于记录每个汽车零售商的销售情况。每份销售记录必须包括下列数据。字符串值的最大长度不包括其结尾的NUL字节。

技术分享

销售时可能出现三种不同类型的交易:全额现金销售,贷款销售和租赁.对于全额现金销售,你还必须保存下面这些附加信息:

技术分享

对于租赁,你必须保存下面这些附件信息:

技术分享

对于贷款销售,你必须保存下面这些附件信息:

技术分享

answer:

struct INFO1{
    char cust_name[21];
    char cust_addr[41];
    char model[21];
    enum {PURE_CASH, CASH_LOAN, LEASE} type;
    union{
        struct{
            float msrp;
            float sales_price;
            float sales_tax;
            float licensing_fee;
        }pure_cash;
        struct{
            float msrp;
            float sales_price;
            float sales_tax;
            float licensing_fee;
            float down_payment;
            int loan_duration;
            float interest_rate;
            float monthly_payment;
            char bank[21];
        }cash_loan;
        struct{
            float msrp;
            float sales_price;
            float down_payment;
            float security_deposit;
            float monthly_payment;
            float lease_term;
        }lease;
    }info;
};
//or
struct INFO2{
    char cust_name[21];
    char cust_addr[41];
    char model[21];
    float msrp;
    float sales_price;
    enum {PURE_CASH, CASH_LOAN, LEASE} type;
    union{
        struct{
            float sales_tax;
            float licensing_fee;
        }pure_cast;
        struct{
            float sales_tax;
            float licensing_fee;
            float down_payment;
            int loan_duration;
            float interest_rate;
            float monthly_payment;
            char bank[21];
        }cash_loan;
        struct{
            float down_payment;
            float security_deposit;
            float monthly_payment;
            float lease_term;
        }lease;
    }info;
};

 

3.计算机的任务之一就是对程序的指令进行解码,确定采取何种操作.在许多机器中,由于不同的指令具有不同的格式,解码过程被复杂化了,在某个特定的机器上,每个指令的长度都是16位,并实现了下列各种不同的指令格式.位是从右向左进行标记的.

技术分享

你的任务是编写一个声明,允许程序用这些格式中的任何一种形式对指令进行解释.你的声明同时必须有一个名叫addr的unsigned short类型字段,可以访问所有的16位值,在你的声明中使用typedef来创建一个新类型,称为machine_inst.给定下面的声明:

machine_inst x;

下面的表达式应该访问它所指定的位.

技术分享

answer: 

typedef union{
    unsigned short addr;
    struct{
        unsigned opcode : 10;
        unsigned dst_mode : 3;
        unsigned dst_reg : 3;
    }sql_op;
    struct{
        unsigned opcode : 4;
        unsigned src_mode : 3;
        unsigned src_reg : 3;
        unsigned dst_mode : 3;
        unsigned dst_reg : 3;
    }dbl_op;
    struct{
        unsigned opcode : 7;
        unsigned src_reg : 3;
        unsigned dst_mode : 3;
        unsigned dst_reg : 3;
    }reg_src;
    struct{
        unsigned opcode : 8;
        unsigned offset : 8;
    }branch;
    struct{
        unsigned opcode : 16;
    }misc;
}machine_inst;

《C与指针》第十章练习