MediaWiki API result
This is the HTML representation of the JSON format. HTML is good for debugging, but is unsuitable for application use.
Specify the format parameter to change the output format. To see the non-HTML representation of the JSON format, set format=json.
See the complete documentation, or the API help for more information.
{ "batchcomplete": "", "continue": { "gapcontinue": "Standard_Library_Functions", "continue": "gapcontinue||" }, "query": { "pages": { "10": { "pageid": 10, "ns": 0, "title": "Specific Features", "revisions": [ { "contentformat": "text/x-wiki", "contentmodel": "wikitext", "*": "The HI-TECH C compiler has a number of features, which while largely compatible with other C compilers, contribute to more reliable programming methods.\n\n== ANSI C Standard Compatibility ==\n\nAt the time of writing the Draft ANSI Standard for the C Language was at an advanced stage, though not yet an official standard. Accordingly it is not possible to claim compliance with that standard, however HI-TECH C includes the\nmajority of the new and altered features in the draft ANSI standard. Thus it is in the sense that most people understand it \"ANSI compatible\".\n\n== Type Checking ==\n\nPrevious C compilers have adopted a lax approach to type checking. This is typified by the Unix C compiler, which allows almost arbritary mixing of types in expressions. The HI-TECH C compiler performs much more strict type\nchecking, although in most cases only warning messages are issued, allowing compilation to proceed if the user knows that the errors are harmless. This would occur, for example, when an integer value was assigned to a pointer variable. The generated code would almost certainly be what the user intended, however if in fact it represented an error in the source code, the user is prompted to check and correct it where necessary.\n\n== Member Names ==\n\nIn early C compilers member names in different structures were required to be distinct except under certain circumstances. HI-TECH C, like most recent implementations of C, allows member names in different structures and unions to\noverlap. A member name is recognized only in the context of an expression whose type is that of the structure in which the member is defined. In practice this means that a member name will be recognized only to the right of a '.' or '->'operator, where the expression to the left of the operator is of type structure or pointer to structure the same as that in which the member name was declared. This not only allows structure names to be re-used without conflict in more than one structure, it permits strict checking of the\nusage of members; a common error with other C compilers is the use of a member name with a structure pointer of the wrong type, or worse with a variable which is a pointer to a simple type.\n\nThere is however an escape from this, where the user desires to use as a structure pointer something which is not declared as such. This is via the use of a typecast. For example, suppose it is desired to access a memory-mapped i/o\ndevice, consisting of several registers. The declarations and use may look something like the code fragment in fig. 2.\n\n struct io_dev\n {\n short io_status; /* status */\n char io_rxdata; /* rx data */\n char io_txdata; /* tx data */\n };\n \n #define RXRDY 01 /* rx ready */\n #define TXRDY 02 /* tx ready */\n \n /* define the (absolute) device address */\n \n #define DEVICE ((struct io_dev *)0xFF00)\n \n send_byte(c)\n char c;\n {\n /* wait till transmitter ready */\n while(!(DEVICE->io_status & TXRDY))\n continue;\n /* send the data byte */\n DEVICE->io_txdata = c;\n }\n\n;Fig. 2. Use of Typecast on an Absolute Address\n\n\nIn this example, the device in question has a 16 bit status port, and two 8 bit data ports. The address of the device (i.e. the address of its status port) is given as (hex)0FF00. This address is typecast to the required struc-\nture pointer type to enable use of the structure member names. The code generated by this will use absolute memory references to access the device, as required.\n\nSome examples of right and wrong usage of member names are shown in fig. 3.\n\n== Unsigned Types ==\n\nHI-TECH C implements unsigned versions of all integral types; i.e. unsigned char, short, int and long. If an unsigned quantity is shifted right, the shift will be performed as a logical shift, i.e. bringing zeros into the\nrightmost bits. Similarly right shifts of a signed quantity will sign extend the rightmost bits.\n\n== Arithmetic Operations ==\n\nOn machines where arithmetic operations may be performed more efficiently in lengths shorter than int, operands shorter than int will not be extended to int length unless necessary.\n\nFor example, if two characters are added and the result stored into another character, it is only necessary to\n\n struct fred\n {\n char a;\n int b;\n } s1, * s2;\n \n struct bill\n {\n float c;\n long b;\n } x1, * x2;\n \n main()\n {\n /* wrong - c is not a member of fred */\n s1.c = 2;\n \n /* correct */\n s1.a = 2;\n \n /* wrong - s2 is a pointer */\n s2.a = 2;\n \n /* correct */\n x2->b = 24L;\n \n /* right, but note type conversion\n from long to int */\n s2->b = x2->b;\n }\n\n;Fig. 3. Examples of Member Usage\n\nperform arithmetic in 8 bits, since any overflow into the top 8 bits will be lost. However, if the sum of two characters is stored into an int, the addition should be done in 16 bits to ensure the correct result.\n\nIn accordance with the draft ANSI standard, operations on float rather than double quantities will be performed in the shorter precision rather than being converted to double precision then back again.\n\n== Structure Operations ==\n\nHI-TECH C implements structure assignments, structure arguments and structure-valued functions in their full generality. The example in fig. 4 is a function returning a structure. Some legal (and illegal) uses of the function are\nalso shown.\n\n struct bill\n {\n char a;\n int b;\n }\n afunc()\n {\n struct bill x;\n \n return x;\n }\n \n main()\n {\n struct bill a;\n \n a = afunc(); /* ok */\n pf(\"%d\", afunc().a); /* ok */\n \n /* illegal, afunc() cannot be assigned\n to, therefore neither can\n afunc().a */\n afunc().a = 1;\n \n /* illegal, same reason */\n afunc().a++;\n }\n\n;Fig. 4. Example of a Function Returning a Structure\n\n== Enumerated Types ==\n\nHI-TECH C supports enumerated types; these provide a structured way of defining named constants.\n\nThe uses of enumerated types are more restricted than that allowed by the Unix C compiler, yet more flexible than permitted by LINT. In particular, an expression of enumerated type may be used to dimension arrays, as an array\nindex or as the operand of a switch statement. Arithmetic may be performed on enumerated types, and enumerated type expressions may be compared, both for equality and with the relation operators. An example of the use of an enumerated type is given in fig. 5.\n\n== Initialization Syntax ==\n\nKernighan and Ritchie in \"The C Programming Language\" state that pairs of braces may be omitted from an initializer in certain contexts; the draft ANSI standard provides that a conforming C program must either include all braces\nin an initializer, or leave them all out. HI-TECH C allows any pairs of braces to be omitted providing that the front end of the compiler can determine the size of any arrays being initialized, and providing that there is no ambiguity as to which braces have been omitted. To avoid ambiguity if any pairs of braces are present then any braces which would\n\n /* a represents 0, b -> 1 */\n enum fred { a, b, c = 4 };\n \n main()\n {\n enum fred x, y, z;\n \n x = z;\n if(x < z)\n func();\n x = (enum fred)3;\n switch(z) {\n case a:\n case b:\n default:\n }\n }\n\n;Fig. 5. Use of an Enumerated Type\n\nenclose those braces must also be present. The compiler will complain (\"initialization syntax\") if any ambiguity is present.\n\n== Function Prototypes ==\n\nA new feature of C included in the proposed ANSI for C, known as \"function prototypes\", provides C with an argument checking facility, i.e. it allows the compiler to check at compile time that actual arguments supplied to a function\ninvocation are consistent with the formal parameters expected by the function. The feature allows the programmer to include in a function declaration (either an external declaration or an actual definition) the types of the parameters to that function. For example, the code fragment shown in fig. 6 shows two function prototypes.\n\n void fred(int, long, char *);\n \n char *\n bill(int a, short b, ...)\n {\n return a;\n }\n\n;Fig. 6. Function Prototypes\n\n\nThe first prototype is an external declaration of the function <strong>fred()</strong>, which accepts one integer argument, one long argument, and one argument which is a pointer to char. Any usage of <strong>fred()</strong> while the prototype declaration is in scope will cause the actual parameters to be checked for number and type against the prototype, e.g. if only two arguments were supplied or an integral value was supplied for the third argument the compiler would report an error.\n\n\nIn the second example, the function <strong>bill()</strong> expects two or more arguments. The first and second will be converted to int and short respectively, while the remainder (if present) may be of any type. The ellipsis symbol (...) indicates to the compiler that zero or more arguments of any type may follow the other arguments. The ellipsis symbol must be last in the argument list, and may not appear as the only argument in a prototype.\n\nAll prototypes for a function must agree exactly, however it is legal for a definition of a function in the old style, i.e. with just the parameter names inside the parentheses, to follow a prototype declaration provided the number and type of the arguments agree. In this case it is essential that the function definition is in scope of the prototype declaration.\n\nAccess to unspecified arguments (i.e. arguments supplied where an ellipsis appeared in a prototype) must be via the macros defined in the header file <stdarg.h>. This defines the macros <strong>va_start, va_arg</strong> and <strong>va_end.</strong> See <strong>va_start</strong> in the library function listing for more information.\n\nNOTE that is is a grave error to use a function which has an associated prototype unless that prototype is in scope, i.e. the prototype MUST be declared (possibly in a header file) before the function is invoked. Failure to comply with this rule may result in strange behaviour of the program. HI-TECH C will issue a warning message (\"func() declared implicit int\") whenever a function is called without an explicit declaration. It is good practice to declare all functions and global variables in one or more header files which are included wherever the functions are defined or referenced.\n\n== Void and Pointer to Void ==\n\nThe <strong>void</strong> type may be used to indicate to the compiler that a function does not return a value. Any usage of the return value from a void function will be flagged as an error.\n\nThe type <strong>void</strong> *, i.e. pointer to void, may be used as a \"universal\" pointer type. This is intended to assist in the writing of general purpose storage allocators and the like, where a pointer is returned which may be assigned to another variable of some other pointer type. The compiler permits without typecasting and without reporting an error the conversion of <strong>void</strong> * to any other pointer type and vice versa. The programmer is advised to use this facility carefully and ensure that any <strong>void</strong> * value is usable as a pointer to any other type, e.g. the alignment of any such pointer should be suitable for storage of any object.\n\n== Type qualifiers ==\n\nThe ANSI C standard introduced the concept of <strong>typequalifiers</strong> to C; these are keywords that qualify the type to which they are applied. The type qualifiers defined by ANSI C are const and volatile. HI-TECH C also implements several other type qualifiers. The extra qualifiers include:\n\n:far\n:near\n:interrupt\n:fast interrupt\n:port\n\nNot all versions of the compilers implement all of the extra qualifiers. See the machine dependent section for further information.\n\nWhen constructing declarations using type qualifiers, it is very easy to be confused as to the exact semantics of the declaration. A couple of rules-of-thumb will make this easier. Firstly, where a type qualifier appears at the left of a declaration it may appear with any storage class specifier and the basic type in any order, e.g.\n\n static void interrupt func();\n\nis semantically the same as\n\n interrupt static void func();\n\n\nWhere a qualifier appears in this context, it applies to the basic type of the declaration. Where a qualifier appears to the right of one or more '*' (<strong>star</strong>) pointer modifiers, then you should read the declaration from right to left, e.g.\n\n char * far fred;\n\nshould be read as \"fred is a far pointer to char\". This means that fred is qualified by <strong>far</strong>, not the char to which it points. On the other hand,\n\nchar far * bill;\n\nshould be read as \"bill is a pointer to a far char\", i.e. the char to which bill points is located in the far address space. In the context of the 8086 compiler this will mean that bill is a 32 bit pointer while fred is a 16 bit pointer. You will hear bill referred to as a \"far pointer\",however the terminology \"pointer to far\" is preferred.\n\n\n== 5.12.==\n\nThere are two methods provided for in-line assembler code in C programs. The first allows several lines of assembler anywhere in a program. This is via the #asm and #endasm preprocessor directives. Any lines between these\ntwo directives will be copied straight through to the assembler file produced by the compiler. Alternatively you can use the asm(\"<strong>string</strong>\"); construct anywhere a C statement is expected. The <strong>string</strong> will be copied through to the assembler file. Care should be taken with using in-line assembler since it may interact with compiler generated code.\n\n== Pragma Directives ==\n\nThe draft ANSI C standard provides for a #pragma preprocessor directive that allows compiler implementations to control various aspects of the compilation process. Currently HI-TECH C only supports one pragma, the <strong>pack</strong> directive. This allows control over the manner in which members are allocated inside a structure. By default, some of the compilers (especially the 8086 and 68000 compilers) will align structure members onto even boundaries to optimize machine accesses. It is sometimes desired to override this to achieve a particular layout inside a structure. The <strong>pack</strong> pragma allows specification of a maximum packing factor. For example, #pragma pack1(1) will instruct the compiler that no additional padding be inserted between struc\nture members, i.e. that all members should be aligned on boundaries divisible by 1. Similarly #pragma pack(2) will allow alignment on boundaries divisible by 2. In no case will use of the <strong>pack</strong> pragma force a greater alignment than would have been used for that data type anyway.\n\nMore that one <strong>pack</strong> pragma may be used in a program. Any use will remain in force until changed by another <strong>pack</strong> or until the end of the file. Do not use a <strong>pack</strong> pragma before include files such as <<strong>stdio.h</strong>> as this will cause incorrect declarations of run-time library data structures." } ] }, "13": { "pageid": 13, "ns": 0, "title": "Standard Libraries", "revisions": [ { "contentformat": "text/x-wiki", "contentmodel": "wikitext", "*": "== Standard I/O ==\n\nC is a language which does not specify the I/O facilites in the language itself; rather all I/O is performed via library routines. In practice this results in I/O handling which is no less convenient than any other language, with\nthe added possibility of customising the I/O for a specific application. For example it is possible to provide a routine to replace the standard getchar() (which gets one character from the standard input) with a special getchar(). This is particulary useful when writing code which is to run on a special hardware configuration, while maintaining a high level of compatibility with \"standard\" C I/O.\n\nThere is in fact a Standard I/O library (STDIO) which defines a portable set of I/O routines. These are the routines which are normally used by any C application program. These routines, along with other non-I/O library routines,\nare listed in detail in a subsequent section of the manual.\n\n== Compatibility ==\n\nThe libraries supplied with HI-TECH C are highly compatible with the ANSI libraries, as well as the V7 UNIX libraries, both at the Standard I/O level and the UNIX system call level. The Standard I/O library is complete, and\nconforms in all respects with the UNIX Standard I/O library. The library routines implementing UNIX system call like functions are as close as possible to those system calls, however there are some UNIX system calls that cannot be simulated on other systems, e.g. the link() operation. However the basic low level I/O routines, i.e. open, close, read, write and lseek are identical to the UNIX equivalents. This means that many programs written to run on UNIX, even if they do not use Standard I/O, will run with little modification when compiled with HI-TECH C.\n\n== Libraries for Embedded Systems ==\n\nThe cross compilers, designed to produce code for target systems without operating systems, are supplied with libraries implementing a subset of the STDIO functions. Not provided are those functions dealing with files. Included\nare <strong>printf(), scanf()</strong> etc. These operate by calling two low level functions <strong>putch</strong> and <strong>getch()</strong> which typically send and receive characters via a serial port. Where the compiler is aimed at a single-chip micro with on-board UART this is used. The source code for all these functions is supplied enabling the user to modify it to address a different serial port.\n\n== Binary I/O ==\n\nOn some operating systems, notably CP/M, files are treated differently according to whether they contain ASCII (i.e. printable) or binary data. MD-DOS also suffers from this problem, not due to any lack in the operating system\nitself, but rather because of the hangover from CP/M which results in many programs putting a redundant ctrl-Z at the end of files. Unfortunately there is no way to determine which type of data a file contains (except perhaps by the name or type of the file, and this is not reliable). To overcome this difficulty, there is an extra character which may be included in the MODE string to a fopen() call. To open a file for ASCII I/O, the form of the fopen() call is:\n\n fopen(\"filename.ext\", \"r\") /* for reading */\n fopen(\"filename.ext\", \"w\") /* for writing */\n\nTo open a file for binary I/O, the character 'b' may be\nappended to the\n\n fopen(\"filename.ext\", \"rb\")\n fopen(\"filename.ext\", \"wb\")\n\n\nThe additional character instructs the STDIO library that this file is to be handled in a strict binary fashion. On CP/M or MS-DOS, a file opened in ASCII mode will have the following special character handling performed by the STDIO\nroutines:\n\n;newline\n:('\\n') converted to carriage return/newline on output.\n\n;return\n:('\\r') ignored on input\n\n;Ctrl-Z\n:interpreted as End-Of-File on input and, for CP/M only, appended when closing the file.\n\nThe special actions performed on ASCII files ensure that the file is written in a format compatible with other programs handling text files, while eliminating the requirement for any special handling by the user program - the file\nappears to the user program as though it were a UNIX-like text file.\n\nNone of these special actions are performed on a file opened in binary mode. This is required when handling any kind of binary data, to ensure that spurious bytes are not inserted, and premature EOF's are not seen.\n\nSince the binary mode character is additional to the normal mode character, this usage is quite compatible with UNIX C. When compiled on UNIX, the additional character will be ignored.\n\nA mention here of the term `stream' is appropriate; stream is used in relation to the STDIO library routines to mean the source or sink of bytes (characters) manipulated by those routines. Thus the FILE pointer supplied as an argu-\nment to the STDIO routines may be regarded as a handle on the corresponding stream. A stream may be viewed as a featureless sequence of bytes, originating from or being sent to a device or file or even some other indeterminate source. A FILE pointer should not be confused with the 'file descriptors' used with the low-level I/O functions <strong>open(), close(), read()</strong> and <strong>write()</strong>. These form an independent group of I/O functions which perform unbuffered reads and writes to files.\n\n== Floating Point Library ==\n\nHI-TECH C supports floating point as part of the language, however the Z80 implementation provides single precision only; double floats are permitted but are no different to floats. In addition, the standard library,\nLIBC.LIB, does not contain any floating point routines. These have been separated out into another library, LIBF.LIB. This means that if this library is not searched no floating point support routines will be linked in, thus avoiding any size penalty for the floating point support if it is not used. This is particulary important for printf and scanf, and thus LIBF.LIB contains versions of printf and scanf that do support floating point formats.\n\nThus, if floating point is used, a -LF option should be used AFTER the source and/or object files to the C command. E.g.:\n\n C -V -O x.c y.c z.obj -LF" } ] } } } }