[ Pobierz całość w formacie PDF ]
.A declaration involving a pointer and a const has several possible orderings:const int * grape;int const * grape;int * const grape_jelly;The last of these cases makes the pointer read-only, whereas the other two make the object that itpoints at read-only; and of course, both the object and what it points at might be constant.Either of thefollowing equivalent declarations will accomplish this:const int * const grape_jam;int const * const grape_jam;The ANSI standard implicitly acknowledges other problems when it mentions that the typedefspecifier is called a "storage-class specifier" for syntactic convenience only.It's an area that evenexperienced C programmers find troublesome.If declaration syntax looks bad for something asstraightforward as an array of pointers, consider how it looks for something even slightly complicated.What exactly, for example, does the following declaration (adapted from the telnet program)declare?char* const *(*next)();We'll answer the question by using this declaration as an example later in the chapter.Over the years,programmers, students, and teachers have struggled to find simple mnemonics and algorithms to helpthem make some sense of the horrible C syntax.This chapter presents an algorithm that gives a step-by-step approach to solving the problem.Work through it with a couple of examples, and you'll neverhave to worry about C declarations again!How a Declaration Is FormedLet's first take a look at some C terminology, and the individual pieces that can make up a declaration.An important building block is a declarator the heart of any declaration; roughly, a declarator is theidentifier and any pointers, function brackets, or array indica-tions that go along with it, as shown inFigure 3-1.We also group any initializer here for convenience.Figure 3-1.The Declarator in CA declaration is made up of the parts shown in Figure 3-2 Figure 3-2(not all combinations are valid,but this table gives us the vocabulary for further discussion).A declaration gives the basic underlyingtype of the variable and any initial value.Figure 3-2.The Declaration in CWe begin to see how complicated a declaration can become once you start combining types together.Also, remember there are restrictions on legal declarations.You can't have any of these:" a function can't return a function, so you'll never see foo()()" a function can't return an array, so you'll never see foo()[]" an array can't hold a function, so you'll never see foo[]()You can have any of these:" a function returning a pointer to a function is allowed: int (* fun())();" a function returning a pointer to an array is allowed: int (* foo())[]" an array holding pointers to functions is allowed: int (*foo[])()" an array can hold other arrays, so you'll frequently see int foo[][]Before dealing with combining types, we'll refresh our memories by reviewing how to combinevariables in structs and unions, and also look at enums.A Word About structsStructs are just a bunch of data items grouped together.Other languages call this a "record".Thesyntax for structs is easy to remember: the usual way to group stuff together in C is to put it in braces:{ stuff.} The keyword struct goes at the front so the compiler can distinguish it from a block:struct {stuff.}The stuff in a struct can be any other data declarations: individual data items, arrays, other structs,pointers, and so on.We can follow a struct definition by some variable names, declaring variables ofthis struct type, for example:struct {stuff.} plum, pomegranate, pear;The only other point to watch is that we can write an optional "structure tag" after the keyword"struct":struct fruit_tag {stuff.} plum, pomegranate, pear;The words struct fruit_tag can now be used as a shorthand forstruct {stuff.}in future declarations.A struct thus has the general form:struct optional_tag {type_1 identifier_1;type_2 identifier_2;.type_N identifier_N;} optional_variable_definitions;So with the declarationsstruct date_tag { short dd,mm,yy; } my_birthday, xmas;struct date_tag easter, groundhog_day;variables my_birthday, xmas, easter, and groundhog_day all have theidentical type.Structs can also have bit fields, unnamed fields, and word-aligned fields.These are obtained by following the field declaration with a colon and a numberrepresenting the field length in bits./* process ID info */struct pid_tag {unsigned int inactive :1;unsigned int :1; /* 1 bit of padding */unsigned int refcount :6;unsigned int :0; /* pad to next word boundary*/short pid_id;struct pid_tag *link;};This is commonly used for "programming right down to the silicon," and you'll see it in systemsprograms.It can also be used for storing a Boolean flag in a bit rather than a char.A bit field musthave a type of int, unsigned int, or signed int (or a qualified version of one of these).It'simplementation-dependent whether bit fields that are int's can be negative.Our preference is not to mix a struct declaration with definitions of variables.We preferstruct veg { int weight, price_per_lb; };struct veg onion, radish, turnip;tostruct veg { int weight, price_per_lb; } onion, radish, turnip;Sure, the second version saves you typing a few characters of code, but we should be much moreconcerned with how easy the code is to read, not to write.We write code once, but it is read manytimes during subsequent program maintenance.It's just a little simpler to read a line that only does onething.For this reason, variable declarations should be separate from the type declaration.Finally there are two parameter passing issues associated with structs.Some C books make statementslike "parameters are passed to a called function by pushing them on the stack from right to left." Thisis oversimplification if you own such a book, tear out that page and burn it.If you own such acompiler, tear out those bytes.Parameters are passed in registers (for speed) where possible.Be awarethat an int "i" may well be passed in a completely different manner to a struct "s" whose only memberis an int [ Pobierz całość w formacie PDF ]
zanotowane.pl doc.pisz.pl pdf.pisz.pl milosnikstop.keep.pl
.A declaration involving a pointer and a const has several possible orderings:const int * grape;int const * grape;int * const grape_jelly;The last of these cases makes the pointer read-only, whereas the other two make the object that itpoints at read-only; and of course, both the object and what it points at might be constant.Either of thefollowing equivalent declarations will accomplish this:const int * const grape_jam;int const * const grape_jam;The ANSI standard implicitly acknowledges other problems when it mentions that the typedefspecifier is called a "storage-class specifier" for syntactic convenience only.It's an area that evenexperienced C programmers find troublesome.If declaration syntax looks bad for something asstraightforward as an array of pointers, consider how it looks for something even slightly complicated.What exactly, for example, does the following declaration (adapted from the telnet program)declare?char* const *(*next)();We'll answer the question by using this declaration as an example later in the chapter.Over the years,programmers, students, and teachers have struggled to find simple mnemonics and algorithms to helpthem make some sense of the horrible C syntax.This chapter presents an algorithm that gives a step-by-step approach to solving the problem.Work through it with a couple of examples, and you'll neverhave to worry about C declarations again!How a Declaration Is FormedLet's first take a look at some C terminology, and the individual pieces that can make up a declaration.An important building block is a declarator the heart of any declaration; roughly, a declarator is theidentifier and any pointers, function brackets, or array indica-tions that go along with it, as shown inFigure 3-1.We also group any initializer here for convenience.Figure 3-1.The Declarator in CA declaration is made up of the parts shown in Figure 3-2 Figure 3-2(not all combinations are valid,but this table gives us the vocabulary for further discussion).A declaration gives the basic underlyingtype of the variable and any initial value.Figure 3-2.The Declaration in CWe begin to see how complicated a declaration can become once you start combining types together.Also, remember there are restrictions on legal declarations.You can't have any of these:" a function can't return a function, so you'll never see foo()()" a function can't return an array, so you'll never see foo()[]" an array can't hold a function, so you'll never see foo[]()You can have any of these:" a function returning a pointer to a function is allowed: int (* fun())();" a function returning a pointer to an array is allowed: int (* foo())[]" an array holding pointers to functions is allowed: int (*foo[])()" an array can hold other arrays, so you'll frequently see int foo[][]Before dealing with combining types, we'll refresh our memories by reviewing how to combinevariables in structs and unions, and also look at enums.A Word About structsStructs are just a bunch of data items grouped together.Other languages call this a "record".Thesyntax for structs is easy to remember: the usual way to group stuff together in C is to put it in braces:{ stuff.} The keyword struct goes at the front so the compiler can distinguish it from a block:struct {stuff.}The stuff in a struct can be any other data declarations: individual data items, arrays, other structs,pointers, and so on.We can follow a struct definition by some variable names, declaring variables ofthis struct type, for example:struct {stuff.} plum, pomegranate, pear;The only other point to watch is that we can write an optional "structure tag" after the keyword"struct":struct fruit_tag {stuff.} plum, pomegranate, pear;The words struct fruit_tag can now be used as a shorthand forstruct {stuff.}in future declarations.A struct thus has the general form:struct optional_tag {type_1 identifier_1;type_2 identifier_2;.type_N identifier_N;} optional_variable_definitions;So with the declarationsstruct date_tag { short dd,mm,yy; } my_birthday, xmas;struct date_tag easter, groundhog_day;variables my_birthday, xmas, easter, and groundhog_day all have theidentical type.Structs can also have bit fields, unnamed fields, and word-aligned fields.These are obtained by following the field declaration with a colon and a numberrepresenting the field length in bits./* process ID info */struct pid_tag {unsigned int inactive :1;unsigned int :1; /* 1 bit of padding */unsigned int refcount :6;unsigned int :0; /* pad to next word boundary*/short pid_id;struct pid_tag *link;};This is commonly used for "programming right down to the silicon," and you'll see it in systemsprograms.It can also be used for storing a Boolean flag in a bit rather than a char.A bit field musthave a type of int, unsigned int, or signed int (or a qualified version of one of these).It'simplementation-dependent whether bit fields that are int's can be negative.Our preference is not to mix a struct declaration with definitions of variables.We preferstruct veg { int weight, price_per_lb; };struct veg onion, radish, turnip;tostruct veg { int weight, price_per_lb; } onion, radish, turnip;Sure, the second version saves you typing a few characters of code, but we should be much moreconcerned with how easy the code is to read, not to write.We write code once, but it is read manytimes during subsequent program maintenance.It's just a little simpler to read a line that only does onething.For this reason, variable declarations should be separate from the type declaration.Finally there are two parameter passing issues associated with structs.Some C books make statementslike "parameters are passed to a called function by pushing them on the stack from right to left." Thisis oversimplification if you own such a book, tear out that page and burn it.If you own such acompiler, tear out those bytes.Parameters are passed in registers (for speed) where possible.Be awarethat an int "i" may well be passed in a completely different manner to a struct "s" whose only memberis an int [ Pobierz całość w formacie PDF ]