• Aucun résultat trouvé

Arrays of Zero Length

Dans le document For Mary (Page 103-111)

char outstr[strlen(str1) + strlen(str2) + 2];

strcpy(outstr,str1);

strcat(outstr," “);

strcat(outstr,str2);

printf(”%s\n",outstr);

}

An array of variable length can be passed in as an argument, as in the following example:

void fillarray(int length,char letters[length]) {

int i;

char character = ‘A’;

for(i=0; i<length; i++) letters[i] = character++;

}

The order of the arguments can be reversed by making a forward declaration so that the type oflengthis known at the time thelettersarray is read, as in the following:

void fillarray(int length; char letters[length], int length) You can have as many of these forward declarations as you need (separated by commas or semicolons), as long as the last one is followed by a semicolon.

Arrays of Zero Length

GNU C allows the declaration of arrays of zero length to facilitate the creation of variable-length structures. This only makes sense if the zero-length array is the last member of astruct. The size of the array can be specified by simply being allocated the amount of space necessary. The following program demonstrates the technique:

USINGTHECOMPILERCOLLECTION /* zarray.c */

#include <stdio.h>

typedef struct { int size;

char string[0];

} vlen;

int main(int argc,char *argv[]) {

int i;

int count = 22;

char letter = ‘a’;

vlen *line = (vlen *)malloc(sizeof(vlen) + count);

line->size = count;

for(i=0; i<count; i++)

line->string[i] = letter++;

printf(“sizeof(vlen)=%d\n”,sizeof(vlen));

for(i=0; i<line->size; i++)

printf(“%c ”,line->string[i]);

printf(“\n”);

return(0);

}

Theprintf()statement in this example prints the value 4 because thesizeof operator can only detect the size of theintvalue in the struct. The output from the zarrayprogram looks like the following:

sizeof(vlen)=4

a b c d e f g h i j k l m n o p q r s t u v

The same thing can be achieved by defining the array as an incomplete type. This approach not only has the advantage being standard C, but can also be used in exactly the same way as the previous example. As an added benefit the size of the array can be specified in the initializers, as in the following example where the size of the array is set to four characters:

/* incarray.c */

#include <stdio.h>

typedef struct {

int size;

char string[];

} vlen;

vlen initvlen = { 4, { ‘a’, ‘b’, ‘c’, ‘d’ } };

int main(int argc,char *argv[]) {

int i;

printf(“sizeof(vlen)=%d\n”,sizeof(vlen));

printf(“sizeof(initvlen)=%d\n”,sizeof(initvlen));

for(i=0; i<initvlen.size; i++)

printf(“%c ”,initvlen.string[i]);

printf(“\n”);

return(0);

}

The output from this example is as follows:

sizeof(vlen)=4 sizeof(initvlen)=4 a b c d

Attributes

The__attribute__keyword can be used to assign an attribute to a function or data declaration. The primary purpose of assigning an attribute to a function is to make it possible for the compiler to perform optimization. The attribute is assigned to a function in the declaration of the function prototype, as in the following example:

void fatal_error() __attribute__ ((noreturn));

. . .

void fatal_error(char *message) {

fprintf(stderr,"FATAL ERROR: %s\n",message);

exit(1);

}

In this example, thenoreturnattribute tells the compiler that this function does not return to its caller, so any code that would normally be executed on the function’s return can be omitted by the optimizer.

USINGTHECOMPILERCOLLECTION Multiple attributes can be assigned in the same declaration by including them in a

comma-separated list. For example, the following declaration assigns attributes to assure the compiler that it does not modify global variables and that the function must never be expanded inline:

int getlim() __attribute__ ((pure,noinline));

Attributes can be assigned to variables and to members of structs. For example, to guarantee that a field has a specific alignment within a struct, it could be declared as follows:

struct mong { char id;

int code __attribute__ ((align(4)));

};

Table 4-3 lists the set of function attributes, Table 4-4 lists the attributes available for data declarations, and Table 4-5 lists the attributes that can be assigned to data type declarations.

Attribute Description

alias A function definition with this attribute causes the definition to become a weak alias of another function. It can be used in combination with theweakattribute to define a weak alias, as in the following example, wherecenton()is created as a weak alias for__centon():

int __centon() { return(100); } void centon() __attribute__

((weak,alias(“__centon”)));

In C++ the mangled name of the target must be specified. This attribute is not supported on all machines.

always_inline A function that’s declared as being inline, and has this attribute, will always be expanded as inline code, even when no optimization has been specified. Normally functions are only inlined during optimization. The following is an example of the prototype of a function that will always be expanded inline:

inline void infn() __attribute__ ((always_inline));

Table 4-3. Attributes That Can Be Used in Function Declarations

Attribute Description

const A function with this attribute is the same aspure, but it also does not read any values from global memory. This gives the optimizer more freedom thanpurebecause there is no need to make certain that all global values are updated before the function is called.

constructor A function with this attribute is called automatically before the call is made tomain(). Also see thedestructorattribute.

deprecated A function with this attribute will cause the compiler to issue a warning message whenever it is called. The warning message includes the location of the deprecated function to guide the user to more information about it.

destructor A function with this attribute is called automatically aftermain() has returned orexit()has been called. Also see the

constructorattribute.

format A function with this attribute has one argument that is a format string and a variable number of arguments for the values to be formatted. This makes it possible for the compiler to check the format content against the list of arguments to verify that the types match the formatting. There are different types of formatting, so it is also necessary to specify whether validation is to be for theprintf, scanf,strftime, orstrfmonstyle. For example, the following attribute specifies that the second argument passed to the function is the formatting string, the formatting string is expected to be of the printftype, and the variable-length argument list begins with the third argument:

int logprintf(void *log, char *fmt, ...) __attribute__ ((format(printf,2,3)));

Warning messages are issued when a format string is found to be invalid only if the-Wformatoption is specified.

format_arg A function with this attribute accepts a formatting string as one of its arguments and makes a modification to the string so that the result can be passed on to aprintf(),scanf(),strftime(), orstrfmon()type function. This attribute will suppress warning messages issued when the option-Wformat-nonliteralis set to detect nonconstant formatting strings. The following example demonstrates the setting of this attribute for a function that has such a format string as its second argument:

void fedit(int ndx,const char *fmt) __attribute__ ((format_arg(2)));

Table 4-3. Attributes That Can Be Used in Function Declarations (continued)

USINGTHECOMPILERCOLLECTION Attribute Description

malloc A function with this attribute informs the compiler that it can be treated as if it were themalloc()function. For purposes of optimization, the compiler is to assume the returned pointer cannot alias anything.

no_instrument_

function

A function with this attribute will not be instrumented and will not have profiling code inserted into it by the compiler, even if the-finstrument-functionsoption is set.

noinline A function with this attribute will never be expanded as inline code.

noreturn A function with this attribute does not return to its caller.

pure A function with this attribute has no side effects whatsoever, except with respect to its return value. That is, there will be no changes to global values, locations addressed by arguments, or the contents of files. Unlike theconstattribute, this function may read global values. This makes it possible for the compiler to perform common subexpression optimization because all the values are guaranteed to be stable.

section A function with this attribute will have its assembly language code placed into the named section instead of the defaulttext section. The following is an example of a function being put into a section namedspecials:

void mspec(void) __attribute__((section(“specials”)));

This attribute will be ignored on systems that do not support sectioning. Also see-ffunction-sectionsin Appendix D.

used A function with this attribute causes the compiler to generate code for the function body, even if the compiler determines the function is not being used. This can be useful for functions that are called only from inline assembly.

weak A function with this attribute has its name emitted as a weak symbol instead of a global name. This is primarily for the naming of library routines that can be overridden by user code.

Table 4-3. Attributes That Can Be Used in Function Declarations (continued)

Attribute Description

aligned A variable with this attribute is aligned on a memory address that is an even multiple of the number specified for the alignment. For example, the following declaration will alignalivalueat a 32-bit address:

int alivalue __attribute__ ((aligned(32)));

Alignment can be convenient on some systems to accommodate certain assembly language instructions. It can also be useful with fields in a struct that need to accommodate the data format found in a file.

If no alignment number is specified, the compiler will align the item to the largest alignment used for any data item for the hardware, as in the following example:

short shlist[312] __attribute__ ((align));

deprecated A variable with this attribute will cause the compiler to issue a warning every place it is referenced.

mode A variable with this attribute is sized to match the size of the specified mode. The mode can be set to byte, word, or pointer. The mode attribute determines the data type. For example, the following creates an int that is the size of a single byte:

int x __attribute__ ((mode(byte)));

nocommon A variable with this attribute is not allocated as common but is instead allocated its own space. The variable is provided with an initial value of all zeroes. Specifying the command-line option-fno-commonwill cause this attribute to be applied to all variables.

packed A variable with this attribute has the smallest possible alignment. A variable will be separated no more than one byte from its predecessor field. In a struct, a field with this attribute will be allocated with no space between it and the field before it. For example, in the following struct, the start of the array namedzaris aligned exactly one byte from the top of the struct:

struct zrecord { char id;

int zar[32] __attribute__ ((packed));

};

Also see the options-fpack-structand-Wpackedin Appendix D.

section A variable with this attribute will be placed into the named section instead of the defaultdataorbsssection. The following is an example of a function being put into a section nameddomx:

struct domx __attribute__ ((section(“domx”))) = { 0 };

int trigger __attribute__ ((section(“MONLOG”))) = 0;

Because of the way the linker handles data, data declared in its own section must have initial values. This attribute will be ignored on systems that do not support sectioning. Variable initialization can be forced by the command-line option-fno-common.

Table 4-4. Attributes That Can Be Used in Data Declarations

USINGTHECOMPILERCOLLECTION Attribute Description

unused A variable with this attribute tells the compiler that the variable may not be used, and no warning should be issued.

vector_size A variable with this attribute is allocated the total amount of space specified as the size of the vector. For example, the following declares a vector of float data types:

float fvec __attribute__ ((vector_size(32));

Assuming a float data type is 4 bytes long, this declaration creates a block containing 8 float variables for a total size of 32 bytes.

This attribute is only valid for integer and real scalars.

weak A variable with this attribute has its name emitted as a weak symbol instead of as a global name. This is primarily for the naming of library variables that can be overridden by user code.

Table 4-4. Attributes That Can Be Used in Data Declarations (continued)

Attribute Description

aligned A type declared with this attribute is aligned on a memory address that is an even multiple of the number specified for the alignment. For example, instances of the following struct will be aligned at a 32-bit address boundary:

struct blockm { char j[3];

} __attribute__ ((aligned(32)));

It is possible to affect this same alignment by applying thealignedattribute to the first member of the struct. Thealignedattribute can only be used to increase the alignment, not reduce it. Some linkers may force the compiler to limit the maximum alignment value.

This attribute can also be applied to types created bytypedef:

typedef int alint __attribute__ ((aligned(8));

If no alignment number is specified, the compiler will align the item to the largest alignment that is used for any data item for the hardware, as in the following example:

typedef short alshort __attribute__ ((align));

deprecated A type declared with this attribute causes a warning message to be issued each time the type is used in a declaration. The message includes location information for the type declaration.

packed A struct or union declared with this attribute will take up the minimum amount of space possible. This is equivalent to specifying thepackedattribute for each member of the struct or union.

This attribute can be specified following the closing brace on anenumdeclaration.

The command-line option-fshort-enumis the same as using thepacked attribute on allenumdeclarations.

Table 4-5. Attributes That Can Be Used in Data Type Definitions

Dans le document For Mary (Page 103-111)