home *** CD-ROM | disk | FTP | other *** search
Text File | 2013-11-08 | 3.0 MB | 87,182 lines |
Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
- Microsoft `C' Professional Development Environment
- =============================================================================
-
-
- 1. C_FILE_INFO in Environment of Child Process
-
- Product Version(s): 3.00 4.00 5.00
- Operating System: MS-DOS
- Flags: ENDUSER | TAR55563
- Last Modified: 25-AUG-1989 ArticleIdent: Q11867
-
- When you shell from a C program (spawn a process), the environment
- will appear to become corrupted with a ;C_FILE_INFO (or _C_FILE_INFO)
- string. (Version 5.10 uses an underscore rather than a semicolon.)
-
- When a process is spawned, the C run time passes information about
- open files to the child by inserting the identifier ";C_FILE_INFO" (or
- "_C_FILE_INFO" -- no quotation marks in either case), followed by up
- to 20 bytes, into the environment. During start-up, the C run time
- reads the identifier, uses the information passed, and removes it from
- the environment.
-
- System() is implemented by spawning COMMAND.COM, and since COMMAND.COM
- is not a C program, ";C_FILE_INFO" (or "_C_FILE_INFO") gets left in
- the environment.
-
- This behavior is harmless. The leading ";" (or "_") prevents any
- collision with user-entered environment variables.
-
-
- 2. matherr and Trapping Floating-Point Errors
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 15-JAN-1990 ArticleIdent: Q22317
-
- Question:
-
- matherr is not trapping my floating point errors. Could you give me
- some advice on what I could be doing wrong?
-
- Response:
-
- matherr (Page 274 in the "Microsoft C Run-Time Library Reference"
- manual) does not trap in-line floating-point errors. matherr only
- traps floating-point errors generated by functions in our math
- libraries. For example, the following program returns control to our
- matherr routine, not yours:
-
- #include <math.h>
-
- matherr(x)
- struct exception *x;
- {
- x->retval=2;
- return(1);
- }
-
- main()
- {
- double f;
- f=2.0;
- while (1)
- f*=f;
- }
-
- To trap in-line floating-point errors such as the one above, we
- recommend that you use signal with SIGFPE (see the run-time reference
- manual).
-
-
- 3. C 5.10 Prototypes Differ Between \INCLUDE and \INCLUDE\MT
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 1-FEB-1991 ArticleIdent: Q58069
-
- Multithreaded programs are linked with LLIBCMT.LIB and include header
- files from the \INCLUDE\MT directory. If you link with LLIBCMT, but
- include header files from the \INCLUDE directory, you may get the
- linker message "L2029, unresolved external" on one or more of the C
- run-time routines. You can resolve the problem by including the
- multithreaded header files.
-
- The linker must resolve external references based on the names written
- to the object file. The explicit format of these names is directly
- affected by the prototypes you use in your program, and when you
- include the header files, you are specifying function prototypes. The
- prototypes for some functions are different between the single and
- multithreaded header files. For example, atof() is defined in the
- double _CDECL atof(const char *);
-
- and in \INCLUDE\MT\STDLIB.H as follows:
-
- double far pascal atof(const char far *);
-
- The keyword _CDECL means to use C language conventions (that is,
- preserve case and prepend a leading underscore). The keyword pascal
- means to use Pascal language conventions (that is, promote to
- uppercase and do not add a leading underscore). When the linker is
- looking for _atof, it does not consider ATOF a match.
-
- You can find complete compile and link instructions for multithreaded
- programming in MTDYNA.DOC, which is on the C version 5.10 disks.
-
-
- 4. _remappalette(8,_GRAY) Does Not Work Correctly
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | bug
- Last Modified: 12-OCT-1988 ArticleIdent: Q34623
-
- _remappalette(pixel,color) maps the number "pixel" to the value
- "color" and is suppose to return the previous color value. However,
- when this function is invoked as _remappalette(8,_GRAY), the value
- associated with _WHITE is returned.
-
- Microsoft is researching this problem and will post new information as
- it becomes available.
-
- To demonstrate this problem, do the following:
-
- 1. cl the following source-code chunklet with /Od /Zi
- switches.
-
- 2. Go into CodeView.
-
- 3. Set N16 to look at the value err returned by _remappalette() in hex,
- then compare the value with values for the colors in graph.h. You
- may want to make a hardcopy of these values prior to cving. The
- correct value is returned on the zeroth pass, but then erroneous
- values are returned. This has been raided.
-
- 4. Use cv /S, where the S is for switching screen modes.
-
- The following sample code demonstrates the problem:
-
- #include <stdio.h>
- #include <graph,h>
- main()
- {
- int i;
- long err;
- _setvideomode(_HRES16COLOR);
- for (i=0;i<16;i++)
- {
- err=_remappalette(8,_GRAY);
- printf("%x\n",err);
- }
- _setvideomode(_DEFAULTMODE);
- }
-
-
- 5. Warning C4040: near/far/huge Ignored
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 26-SEP-1988 ArticleIdent: Q23978
-
- Question:
-
- I am trying to declare some far data in small model, but I keep
- getting "Warning 40: near/far/huge ignored" with C Version 4.00, or
- the same warning with the number C4040 using C Versions 5.x. Does this
- mean I cannot declare far data in the small model?
-
- Response:
-
- The far data can be declared in the small-memory model. This warning
- means that the far descriptor is improper and/or unnecessary in the
- context in which it is being used. Far or huge arrays should be
- defined outside of functions, or with the static storage class if
- defined within functions.
-
- It also may mean you are trying to make the type of pointer definition
- "char * far pvar;" within the body of a function. This definition
- attempts to define a pointer to data (either near or far, depending on
- the memory model) and place it in a far data segment outside the
- default data segment. This process only will work properly if it is a
- global definition, or if it is defined as static within the body of
- the function.
-
- Please note the difference between the above definition and defining a
- pointer to far data, which is "char far *pvar;". The latter definition
- declares a pointer that can point to data outside the default data
- segment, but the pointer itself is within the default data segment.
- This declaration is quite acceptable within the body of a function.
-
-
- 6. Initial Memory Allocation of C Programs
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | DGROUP 64K
- Last Modified: 15-JAN-1990 ArticleIdent: Q23905
-
- Question:
-
- I want to make a program "terminate and stay resident." It is a very
- short program with only 4K of data and about 2K of code. However, when
- I execute the program to make it resident and do a CHKDSK, it seems to
- occupy about 70K. Why does it take up so much space?
-
- Response:
-
- The linker normally allocates all of memory to a program. You can use
- the /CP switch to adjust the allocation down. If you specify an amount
- less than the minimum allocation, the maximum allocation will default
- to that minimum, so link with /CP:1.
-
- You can also use the /max <MinimumAllocationInHexParagraphs> option of
- the EXEMOD.EXE utility to adjust the maximum allocation of a program.
-
- Microsoft C was not designed for writing memory resident software.
- Although it is possible, you also may need to make modifications to
- the start-up code. Be cautious about what functions you use and what
- DOS functions are called.
-
-
- 7. Changing STDIN Translation Mode from Text to Binary
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 7-MAR-1990 ArticleIdent: Q58427
-
- Question:
-
- Why is it that when I enter a ^Z (CTRL+Z) for a string input in
- response to gets() or scanf(), the next line does not prompt me for an
- input?
-
- Response:
-
- Since STDIN is a predefined file pointer opened in text mode, and a ^Z
- character is an end-of-file marker in DOS, the ^Z character
- automatically closes the file pointer. The gets() or scanf() functions
- do not stop to accept input from STDIN following the previous input
- containing a ^Z character.
-
- To work around this problem, change the translation mode of STDIN from
- text mode to binary mode. Since the ^Z character is not translated as
- an end-of-file character in binary mode, the gets() from the following
- example only accepts input following a ^Z from STDIN after the
- translation.
-
- To change STDIN from text mode to binary mode, use the setmode()
- run-time function to change the translation mode. The following code
- demonstrates this behavior, and includes the setmode() function to
- show how to change STDIN from text mode to binary mode. Remove the
- comment delimiters to observe the difference in the program's behavior
- after adding the setmode() function.
-
- Code Example
- ------------
-
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
-
- void main (void)
- {
- char str1[20];
-
- /* if( setmode ( fileno ( stdin ), O_BINARY ) == -1 )
- perror ( "Cannot set stdin to binary mode" );
- else
- printf ( "stdin mode successfully set to binary\n" );
- */
- do {
- printf ( "Enter a string : " );
- gets ( str1 );
- } while ( strcmp( str1,"n" ) );
-
- }
-
- Compile the above code and run the program. If you enter a string
- and then press the ENTER key, the program will loop and prompt for
- another string. However, if at the prompt you enter a ^Z or a string
- followed by a ^Z, the program will loop indefinitely. It does not pause
- at the gets() statement and wait for your input.
-
- Now, uncomment the if-else clause. Recompile the program and run it.
- Input that includes a ^Z character is now accepted without infinite
- looping.
-
-
- 8. Evaluation Order of Expression and Function Args Undefined
-
- Product Version(s): 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC S_QUICKASM
- Last Modified: 30-NOV-1989 ArticleIdent: Q50694
-
- Side effect operators (++, --, =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=,
- and >>=) may cause unexpected results if they are used on the same
- variable or memory location more than once in the same expression. The
- order in which side effects occur within an expression is not
- specified.
-
- Do NOT expect any specific order of evaluation to take place. The
- discretion is left to the compiler on how it implements the evaluation
- order. The evaluation order could be affected by machine architecture
- and code optimization. Although such code may work sometimes, it is
- not guaranteed to work, and is therefore unsafe.
-
- Note: Kernighan and Ritchie do an excellent job explaining the ANSI C
- Standard for the evaluation order of expressions in Section 2.12 of
- "The C Programming Language - 2nd Edition" by Kernighan and Ritchie.
-
- It is very easy to accidentally write nonportable code with the C
- language. Below are some other common examples of statements that can
- cause side effects during run time:
-
- printf("%d %d \n", ++n, power(2, n)); /* WRONG */
-
- The above statement can produce different results with different
- compilers, depending on whether "n" is incremented before "power" is
- called. The correct code would look like the following:
-
- n++; /* CORRECT */
- printf("%d %d \n", n, power(2, n));
-
- Another common pitfall is the following:
-
- a[i] = i++; /* WRONG */
-
- The question is whether the subscript of "a" is the old value of "i"
- or the new value. Again the correct code would be the following:
-
- a[i] = a[i+1]; /* CORRECT */
- i++;
-
- Another example is as follows:
-
- int x[10], *p = x;
-
- *p++ = *p++ = 0; /* WRONG */
-
- The compiler is allowed to "p" twice at the end after doing the two
- assignments, if it so chooses. To ensure correct code generation, you
- must code as follows:
-
- *p++ = 0; *p++ = 0; /* CORRECT */
-
- In general, any object may have its stored value modified at most once
- in a single expression; in addition, the prior value shall be accessed
- only to determine the value to be stored. Therefore,
-
- i = i + 1; /* OK */
-
- is allowed because "i" is modified only once, and "i" is accessed only
- to determine what to store in "i", but
-
- i = ++i + 1; /* UNDEFINED */
-
- is undefined because "i" is modified more than once in the course of
- the evaluation of the expression.
-
- Instead, the following pair of statements is correct:
-
- ++i;
- i = i + 1; /* OK */
-
- The statement
-
- a[i] = i++; /* UNDEFINED */
-
- is undefined, because, although "i" is only modified once, it is
- accessed both to determine the value to be stored in "i" by the ++
- operator and as a subscript.
-
-
- 9. Memory Not Freed by DOS 2.x for exec or spawn with P_OVERLAY
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | tar57672
- Last Modified: 21-SEP-1988 ArticleIdent: Q24910
-
- Within DOS Versions 2.x only, recurrent use of an exec function or a
- spawn function with P_OVERLAY eventually causes a return indicating
- that there is no more available RAM memory.
-
- This is a DOS Versions 2.x problem, whose exact nature is unknown.
- Microsoft has traced the problem to the point where DOS corrupted
- memory, and memory is not being freed back to DOS Versions 2.x.
-
- If you encounter this problem, upgrade to DOS Versions 3.x, which
- do not have this problem.
-
- It appears that only the exec() family (or spawn() with P_OVERLAY
- specified) is affected by this DOS problem. The spawn() family (except
- when P_OVERLAY is specified) seems to work correctly.
-
-
- 10. Variables in C 5.00/5.10 splitpath() Example Declared Wrong
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 11-FEB-1991 ArticleIdent: Q26589
-
- On page 560 of the "Microsoft C Optimizing Compiler: Run-Time Library
- Reference" that shipped with C versions 5.00 and 5.10, the example for
- the _splitpath() function declares its variables incorrectly. It
- declares arrays of pointers, rather than arrays of characters, as
- follows:
-
- char * drive [3];
- char * dir [30];
- char * fname [9];
- char * ext [4];
-
- The correct declaration should be as follows:
-
- char drive [3];
- char dir [30];
- char fname [9];
- char ext [4];
-
- Both declarations work correctly, but unpredictable results may occur
- with the original form of the array declarations.
-
-
- 11. _amblksiz Not Declared
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 26-SEP-1988 ArticleIdent: Q26778
-
- Page 33 of the "Microsoft C Compiler Run-Time Library Reference
- Manual" (Page 31 for Version 4.00) incorrectly states that _amblksiz
- "is declared in the include file malloc.h". It is not there.
-
- You can use the variable in your program by declaring the variable as
- follows:
-
- extern unsigned int _amblksiz;
-
-
- 12. _remapallpalette Example Causes C4049 Warning
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 26-SEP-1988 ArticleIdent: Q27803
-
- Problem:
-
- I get a warning C4049 when I run the example on Page 489 of the C
- Versions 5.00 and 5.10 "Run-Time Library Reference," in the section on
- _remapallpalette and _remappalette.
-
- Response:
-
- There is an error in the example program. The following line:
-
- _remapallpalette((char *)(&(colorsarray[0])));
-
- should read as follows to avoid the warning message:
-
- _remapallpalette((long far *)(&(colorsarray[0])));
-
-
- 13. The struct videoconfig Declaration
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 26-SEP-1988 ArticleIdent: Q27804
-
- Page 342 of the "Microsoft C Run-Time Library Reference" manual for
- Version 5.00 has an omission. The struct videoconfig declaration
- member list leaves out the following four lines: mode, adaptor,
- monitor, and memory.
-
- The following is the structure as shown in the manual (incorrect):
-
- struct videoconfig {
- short numxpixels; /* number of pixels on X axis */
- short numypixels; /* number of pixels on Y axis */
- short numtextcols; /* number of text columns available */
- short numtextrows; /* number of text rows available */
- short numcolors; /* number of actual colors */
- short bitsperpixel; /* number of bits per pixel */
- short numvideopages;/* number of available video pages */
- }
-
- The following is the structure as defined in GRAPH.H (correct):
-
- struct videoconfig {
- short numxpixels; /* number of pixels on X axis */
- short numypixels; /* number of pixels on Y axis */
- short numtextcols; /* number of text columns available */
- short numtextrows; /* number of text rows available */
- short numcolors; /* number of actual colors */
- short bitsperpixel; /* number of bits per pixel */
- short numvideopages;/* number of available video pages */
- short mode; /* current video mode */
- short adapter; /* active display adapter */
- short monitor; /* active display monitor */
- short memory; /* adapter video memory in K bytes */
- }
-
-
- 14. Beginner's Concerns for Writing Non-PM Graphic Applications
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | TAR73919
- Last Modified: 12-OCT-1988 ArticleIdent: Q28141
-
- Question:
- I have an OS/2 application (an analog simulator with postprocessor)
- that is ready to go, with the exception of the GRAPHICS output. I have
- been having difficulties getting graphics to work under OS/2. Can you
- give me any suggestions on how to use graphics?
-
- Response:
- The first problem is to get "addressability" to the video RAM. This
- is accomplished by using the VioGetPhysBuf API. For an EGA monitor the
- calling sequence would be as follows:
-
- struct PhysBufData physbuf;
- char far *base1, far *base2;
-
- physbuf.buf_start = 0xa0000;
- physbuf.buf_length = 0x20000;
- rcode = VIOGETPHYSBUF (&physbuf, 0);
- FP_SEG (base1) = physbuf.selectors[0];
- FP_OFF (base1) = 0;
- FP_SEG (base2) = physbuf.selectors[1];
- FP_OFF (base2) = 0;
-
- where base1 is the first 64K of memory on the EGA card, and base2
- would be the next 64K of memory. If you wanted to access more than
- 128K you would have to increase the length and allocate space for more
- physbuf.selectors. (Look up this API.)
- Once you have valid pointers to the video memory, you still have
- more limitations. You can (should) not use these pointers unless your
- application is in the foreground. You must (should) inform the
- operating system before using the pointers. You use the API VioScrLock
- to lock your process into the foreground while you are writing to
- video memory. Once you are done writing to the video memory you must
- call VioScrUnLock, to re-enable screen switching. You should not keep
- the screen locked on any more time then absolutely necessary. (See
- this API for restrictions.) If your application attempts to write to
- the video memory when it is not in the foreground, it will gp_fault.
- Since your application is putting the monitor into graphics mode,
- it is its responsibility to save and restore the monitor's contents
- and mode. The application will have to use the API's VioSavRedrawWait
- and VioModeWait. VioSavRedrawWait is for the notification of when you
- should save or restore your screen image. VioModeWait is notified when
- you should save and restore video modes.
- Finally, if you plan to use I/O ports with your program you will
- have to "flag" it as needing IOPL (input/output privilege level). You
- do this by putting "CODE IOPL" in the program's definition file, and
- in config.os2 "IOPL=YES".
-
- API's to review:
- VioGetPhysBuf
- VioScrLock
- VioScrUnLock
- VioModeWait
- VioRedrawWait
-
-
- 15. Include Directories Not Searched as Expected
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 5-DEC-1988 ArticleIdent: Q38383
-
- Question:
-
- It appears that the C compiler searches the INCLUDE list in the wrong
- order. Our INCLUDE=OS2\INC;\INC, but the compiler seemed to get an old
- version of the .h file from \INC. Deleting the old versions from \INC
- corrected the problem.
-
- Response:
-
- While the search order for a file enclosed in <>'s is simple, the
- order for a file enclosed in ""'s is different and more complicated.
-
- You are probably using ""'s rather than <>'s around the filename, and
- you've accidentally set up \INC as a "parent" or "grandparent"
- directory. (See below for more information.) To correct the problem,
- either use <>'s around the filename or reorganize your header files so
- that the search order will find the right file.
-
- Note: if you use ""'s around a complete path specification, the
- standard directories will NOT be searched.
-
- As documented on Page 202 in the "Microsoft C Language Reference" and
- on Page 80 of the "Microsoft C Optimizing Compiler User's Guide," the
- search order for #include <file.h> is as follows:
-
- 1. Any directories specified using the /I switch on the cl command
- line, from left to right
-
- 2. Directories specified in the include environment variable, again
- from left to right
-
- 3. If the file is found in neither of these steps, the following
- message is issued:
-
- fatal error C1015: cannot open include file 'file.h'
-
- For the following example, only the "\path" directory on the current
- default drive is searched:
-
- #include "\path\file.h"
-
- The standard directories will not be searched. However, the search
- order for:
-
- #include "file.h"
-
- is similar to the search order for:
-
- #include <file.h>
-
- except that "parent directories" are searched before directories
- specified by the /I switch and before directories specified in the
- INCLUDE environment variable.
-
- The parent directory is the directory that contains the source
- containing the #include directive. If #include files are nested, then
- the parent directories are searched in reverse order of the nesting:
- first parents, then grandparents, and so on.
-
- For example, if source file grandma.c contains:
-
- #include <parent.h>
-
- and parent.h contains:
-
- #include "child.h"
-
- the search for child.h would take place in the following order:
-
- 1. The parent directory--in this case, the directory in which parent.h
- was previously found.
-
- 2. If child.h was not there, the directory that contains grandma.c
- would be searched next.
-
- 3. If child.h was still not found, the directories (if any) specified
- in /I switches on the CL command line would be searched in
- left-to-right order.
-
- 4. If child.h was still not found, the directories (if any) specified
- by the INCLUDE environment variable would be searched in
- left-to-right order.
-
- 5. If child.h was not found in any of these places, the compiler would
- give the following message:
-
- fatal error C1015: cannot open include file 'child.h'
-
-
- 16. Hexadecimal Unsigned Char Array Elements Missing "\"
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q28349
-
- The sample programs on Pages 325 and 521 of the "Microsoft C 5.1
- Optimizing Compiler Run-Time Library Reference" manual are incorrect.
- For the _getfillmask and _setfillmask examples, the unsigned char
- array element values should be shown with backslackes "\" preceding
- the x's to indicate that they are hexadecimal values.
-
-
- 17. Reference Page 75 Example 9 Causes Error C2147
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q28567
-
- Using example nine on Page 75 of the "Microsoft C 5.1 Optimizing
- Compiler Language Reference" manual causes the compiler error
- "C2147: array: unknown size" on the line "(int *) p++".
-
- The example is incorrect. Instead of using example nine, use one of
- the two following examples:
-
- 1. ((int*) p)++;
- 2. p = (void *) ((char *) p + sizeof(int));
-
- Note that the expression "((int *) p)++" is a non-standard extension
- to the language, and the compiler will issue a warning.
-
- See Pages 99-100 of the user's guide for a discussion of enabling
- and disabling language extensions with the /Ze and /Za switches.
- There is an example at the bottom of Page 99, which is almost
- identical.
-
- Example nine on Page 75 is as follows:
-
- int i;
- void *p;
-
- p = &i;
- (int *) p++;
-
- The expression "(int *) p++" generates the C2147 error because the
- "++" operation is preformed before the "(int *)" cast. Thus, the
- expression is trying to increment a pointer that points to a void.
- Because void has no size, the compiler does not know how many bytes
- "p" should be incremented by.
-
- By using the extra parentheses in the expression "((int *) p)++", you
- are forcing the "(int *)" to convert "p" from a pointer-to-void to a
- pointer-to-int, which can be incremented.
-
- The second workaround, "p = (void *) ((char *) p + sizeof(int))",
- works correctly because you are telling the compiler how many bytes to
- increment the pointer.
-
- The second workaround is standard ANSI C and should compile on any
- standard ANSI C compiler.
-
-
-
- 18. Example of TSR Program
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | APPNOTE
- Last Modified: 20-MAY-1988 ArticleIdent: Q28568
-
- The following article shows how to use Microsoft C to write a
- terminate-and-stay-resident (TSR) program. The article also
- illustrates the use of the following C run-time functions:
-
- _dos_setvect
- _dos_getvect
- _dos_keep
- _chain_intr
- spawnXXX
-
- The following example shows how to use Microsoft C to write a TSR
- program:
-
- /**************************************************************/
- /* */
- /* DirZap.h */
- /* */
- /* This header file defines global variables, macros, */
- /* function pointers, and function prototypes */
- /* necessary for the DirZap.c program. */
- /* */
- /**************************************************************/
-
- /* Global Variable For Macro SHIFTL(x, n)*/
- long _ADDRESS;
-
- /* Macro Definitions */
- #define INT5 0x5
- #define INT21 0x21
- #define SHIFTL(x, n) (_ADDRESS = 0L, _ADDRESS = (long) x, _ADDRESS << n)
- #define HIBYTE(x) (((unsigned) (x) >> 8) & 0xff)
- #define REGPAK unsigned es, unsigned ds, unsigned di, unsigned si,\
- unsigned bp, unsigned sp, unsigned bx, unsigned dx,\
- unsigned cx, unsigned ax, unsigned ip,unsigned cs,\
- unsigned flags
-
- /* Function Pointers */
- void (interrupt far *save_dir_adr)();
- /* Saves address of the original interrupt service routine */
-
- void (interrupt far *set_dir_adr)();
- /* This function pointer gets set to the address of the new
- interrupt service routine 'set_dir' */
-
- void (interrupt far *reset_dir_adr)();
- /* This function pointer gets set to the address of the new
- interrupt service routine 'reset_dir' */
-
- /* Function Declarations */
- void cdecl interrupt far set_dir(REGPAK);
- /* This is the new service routine whichs zaps the directory
- interrupt routines. */
-
- void interrupt far reset_dir(void);
- /* This routine toggles between setting and disabling the
- directory interrupt routines */
-
- unsigned _get_memsize(void);
- /* This function gets the number of bytes to keep resident */
-
- short _set_shell(void);
- /* Sets a DOS shell. */
-
- /**************************************************************/
- /* */
- /* DirZap.c */
- /* */
- /* This is an illustration of a TSR program. */
- /* It traps and zaps the directory interrupts for */
- /* MkDir, RmDir, and ChDir. It also illustates how */
- /* to set a DOS shell by executing a new version of */
- /* COMMAND.COM. */
- /* */
- /* Copyright (c) Microsoft Corp 1988. All rights */
- /* reserved. */
- /* */
- /* To run, do the following: */
- /* */
- /* 1. EXEPACK DirZap to save memory. */
- /* 2. Type DirZap at DOS prompt. DirZap sets a */
- /* DOS shell and is not yet active. */
- /* 3. When "exit" is typed, DirZap is invoked. */
- /* */
- /* The PRINT SCREEN key now toggles */
- /* DirZap on and off, but no memory has been */
- /* freed. */
- /* */
- /**************************************************************/
- /* */
- /* NOTE: */
- /* */
- /* THIS PROGRAM, ITS USE, OPERATION, AND SUPPORT ARE PROVIDED */
- /* "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR */
- /* IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
- /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
- /* PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE */
- /* OF THIS PROGRAM IS WITH THE USER. IN NO EVENT SHALL */
- /* MICROSOFT BE LIABLE FOR ANY DAMAGES INCLUDING, WITHOUT */
- /* LIMITATION, ANY LOST PROFITS, LOST SAVINGS OR OTHER */
- /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING FROM THE USE */
- /* OR INABILITY TO USE SUCH PROGRAM, EVEN IF MICROSOFT HAS */
- /* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES OR FOR ANY */
- /* CLAIM BY ANY OTHER PARTY. */
- /* */
- /**************************************************************/
- #include <dos.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <process.h>
- #include <dirzap.h>
-
- extern unsigned _psp;
- /* Pre-defined varible, _psp = segment address of PSP */
- unsigned far *psp_pointer;
- /* Used to retrieve the memsize to stay resident */
- short hot_key=1;
- /* Flag to toggle DirZap on and off once it is invoked */
-
- void main(void);
- void main()
- {
- if (_set_shell())
- {
- /* Set trap for directory interrupts */
- save_dir_adr = _dos_getvect(INT21);
- /* Save original routine address */
- set_dir_adr = set_dir;
- /* Get address of new (user defined) routine */
- _dos_setvect(INT21, set_dir_adr);
- /* Revector to new service routine */
-
- /* Set trap for PRINT SCREEN interrupt */
- reset_dir_adr = reset_dir;
- /* Get address of new routine */
- _dos_setvect(INT5, reset_dir_adr);
- /* Revector to new routine */
-
- /* Blast off into memory and reside until
- power down or CTRL-ALT-DEL */
-
- _dos_keep(0, _get_memsize());
- }
- else
- puts("problems running DirZap.exe, COMSPEC not found!");
- }
-
- void cdecl interrupt far set_dir(REGPAK)
- {
-
- /*
- Trap directory interrupts MkDir, RmDir, and ChDir and zap the
- string entered by the user. DS:DX points to the string, so change it
- to a string of length 0. WARNING: When compiled at high warning
- levels, several warnings are generated. This is because several
- elements of REGPAK are not referenced. These warnings should be
- ignored.
- */
- if (HIBYTE(ax) == 0x39 || HIBYTE(ax) == 0x3A || HIBYTE(ax) == 0x3B)
- dx=0;
- _chain_intr(save_dir_adr);
- }
-
- void interrupt far reset_dir()
- {
- if (hot_key)
- {
- hot_key=0;
- _dos_setvect(INT21, save_dir_adr); /* Reset initial vector */
-
- }
- else
- {
- hot_key=1;
- _dos_setvect(INT21, set_dir_adr); /* Install DirZap again */
- _chain_intr(set_dir_adr); /* Chain to the Zapper function */
- }
- }
-
- unsigned _get_memsize()
- {
- psp_pointer = (int far *) SHIFTL(_psp, 16); /* Get segment of the PSP*/
- return(psp_pointer[1] - _psp); /* Amount of memory to stay resident */
- }
-
- short _set_shell()
- {
- char *_COMSPEC_;
-
- _COMSPEC_ = getenv("COMSPEC"); /* Get value of COMSPEC */
- if (_COMSPEC_) /* If not equal to NULL */
- {
- puts("type 'EXIT' to invoke DirZapper...");
- spawnlp(P_WAIT, _COMSPEC_, NULL); /* Invoke Command.com */
- return(1);
- }
- return(0);
- }
-
-
- 19. Object Module Format Extensions
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 17-NOV-1988 ArticleIdent: Q28613
-
- The following are Microsoft extensions to the Intel object module
- format that were incorporated in Versions 5.00 and 5.10 of the C
- compiler. For a complete description of the object module format, you
- can contact Microsoft System Languages Technical Support at (206)
- 454-2030 and request the Object Module Format Application Note.
-
- Microsoft OMF Extensions
-
- Local Symbols (C 5.00) -- B4h, B6h, B7h, B8h
-
- There will be three new record types to handle local symbols:
-
- 1. LEXTDEF = 0xb4 (180)
- Format is identical to EXTDEF.
-
- 2. LPUBDEF = 0xb6 (182) or 0xb7 (183)
- Format is identical to PUBDEF.
-
- 3. LCOMDEF = 0xb8 (184)
- Format is identical to COMDEF.
-
- LEXTDEF, LPUBDEF, and LCOMDEF are to be used exactly as EXTDEF,
- PUBDEF, and COMDEF, except that the symbols are not visible outside
- the module where they are defined--for example, C statics.
-
- New OMF Comment -- Class A1h
-
- A comment record with class A1h indicates that the obsolete method of
- communal representation through TYPDEF and EXTDEF pairs is not used,
- and that COMDEF records can be interpreted. The meaning of this record
- is undergoing revision.
-
- IMPDEF (OS2, Windows) -- Comment Class A0h, Subtype 1
-
- The IMPort DEFinition (IMPDEF) record takes the form of a COMENT
- record with class 0xa0:
-
- DB 88h ; COMENT
- DW reclen ; record length
- DB 00h ; for Intel compatibility
- DB A0h ; class: OMF extension
- DB 01h ; subtype: IMPDEF
- DB fOrd ; nonzero value means import by ordinal
- ; Internal Name
- DB n ; length of name
- DB n dup(?) ; ASCII text of name
- ; Module Name
- DB n ; length of name
- DB n dup(?) ; ASCII text of name
- IF import by name (fOrd == 0)
- ; Imported Name: if length byte is 0 then imported name is
- ; identical to internal name.
- ;
- DB n ; length of name
- DB n dup(?) ; ASCII text of name
- ELSE
- DW ordno ; ordinal number
- ENDIF
-
- DB checksum
-
- EXPDEF (C 5.10) -- Comment Class A0h, Subtype 2
-
- The EXPort DEFinition record takes the form of a COMENT record with
- class 0xa0:
-
- DB 88h ; COMENT
- DW reclen ; record length
- DB 00h ; for Intel compatibility
- DB A0h ; class: OMF extension
- DB 02h ; extension type: EXPDEF
- DB flags
- ; 80h = set if ordinal number specified
- ; 40h = set if RESIDENTNAME
- ; 20h = set if NODATA
- ; 1Fh = # of parameter words
-
- ; Exported name:
- DB n ; length of name
- DB n dup(?) ; ASCII text of name
-
- ; IF internal name different from exported name:
- DB n ; length of name
- DB n dup(?) ; ASCII text of name
- ; ELSE internal name same as exported name:
- DB 00h
-
- ; IF ordinal number specified
- DW ordno ; ordinal number
-
- DB checksum
-
- LIBMOD Comment Record -- Class A3h (LIB 3.07 in MASM 5.00)
-
- DB 88h ; COMENT
- DW reclen ; record length
- DB 00h ; for Intel compatibility
- DB A3h ; class: LIBrary MODule name
- DB N ; length of module name
- DB N dup(?) ; ASCII text of module name
- DB checksum
-
- The LIBMOD comment record identifies the name of a library module.
- This record allows LIB to preserve the source file name in the THEADR
- record and still identify the module name. Since the module name is
- the base name of the .OBJ file, the two names may be completely
- different.
-
- LIB adds a LIBMOD record when an .OBJ file is added to a library and
- strips the LIBMOD record when an .OBJ file is removed from a library,
- so this record usually only exists in .LIB files.
-
-
- 20. Building C 5.10 Combined Libraries with the LIB Utility
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q28774
-
- Question:
-
- How does one go about building the combined libraries for C 5.10?
-
- Response:
-
- The preferred method for building the combined libraries is to use the
- SETUP program. To use SETUP to build libraries, you can run it with /L
- as a command-line parameter by typing the following
-
- a:setup /L
-
- at the DOS prompt with the SETUP disk in the drive A.
-
- If you have problems running the Setup program or you want to build
- the libraries manually using the LIB utility, you should build them as
- outlined in the following:
-
- 1. Copy the appropriate library files to your hard disk. The memory
- model and floating-point option that you want to build will
- determine which library files are necessary. Refer to the file
- PACKING.LST to determine where each library file is located.
-
- 2. Locate the LIB.EXE utility so that it is in your current directory
- or is located on your path.
-
- 3. The details for how each library should be built are outlined
- below. These instructions assume that you will be using the default
- names for the real-mode libraries. The instructions also assume
- that you want graphics support built into your real-mode libraries
- (the graphics routines are not supported in protect mode). If this
- is not the case, do not include that library.
-
- The library name should be the command-line parameter to LIB.EXE. The
- question mark (?) is used to represent memory model (S, M, C, L) and
- you should substitute the appropriate letter when invoking the library
- manager. If you see the following prompt
-
- Library does not exist. Create?
-
- you should respond with "y" to create the library and then provide the
- appropriate libraries at the next prompt which will be the
- "Operations:" prompt.
-
- The following is an example session:
-
- Assume that you want to build the small model emulator math library
- for real mode. This is how you would proceed from the DOS prompt
- assuming that you have already copied the correct component libraries
- to the following current directory:
-
- >lib slibce
-
- Microsoft (R) Library Manager Version 3.08
- Copyright (C) Microsoft Corp 1983-1987. All rights reserved.
-
- Library does not exist. Create?y
- Operations:slibc.lib+libh.lib+em.lib+libfp.lib+graphics.lib;
- ---------------
-
- Here are the combine instructions for all combinations of the
- libraries:
- ---------------
-
- ?LIBCE.LIB-Real Mode mode emulator (?==S,M,C or L)
-
- Operations:?libc.lib+libh.lib+em.lib+?libfp.lib+graphics.lib;
- ---------------
-
- ?LIBCA.LIB-Real mode alternate math (?==S,M,C or L)
-
- Operations:?libc.lib+libh.lib+?libfa.lib+graphics.lib;
- ---------------
-
- ?LIBC7.LIB-Real mode 8087 (?==S,M,C or L)
-
- Operations:?libc.lib+libh.lib+87.lib+?libfp.lib+graphics.lib;
- ---------------
-
- ?LIBCEP.LIB-Protect mode emulator (?==S,M,C or L)
-
- Operations:?libcp.lib+libh.lib+em.lib+?libfp.lib;
- ---------------
-
- ?LIBCAP.LIB-Protect mode alternate math (?==S,M,C or L)
-
- Operations:?libcp.lib+libh.lib+?libfa.lib;
- ---------------
-
- ?LIBC7P.LIB-Protect mode 8087 (?==S,M,C or L)
-
- Operations:?libcp.lib+libh.lib+87.lib+?libfp.lib;
-
-
- 21. Unresolved External on __Clpow with /Oi and /FPa in C 5.xx
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29188
-
- The C version 5.00 and 5.10 compilers generate an unresolved external
- reference to __CIpow when the sample program below is compiled with
- /Oi (or /Ox) and /FPa.
-
- Intrinsic optimization (/Oi) and the alternate floating-point option
- are not compatible and cannot be used together. This restriction is
- noted in the C 5.10 README.DOC. The maximum optimization that you can
- use with the alternate floating-point option is /Oalt.
-
- Sample Code
- -----------
-
- /* Compile with /Oi and /FPa */
-
- #include <math.h>
- #include <stdio.h>
-
- main()
- {
- float xx, yy;
- xx = 4.7;
- yy = 3.9;
- printf("%f", pow(xx,yy));
- }
-
-
- 22. SORTDEMO.C/ BIND Use and Misuse
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-AUG-1989 ArticleIdent: Q29196
-
- The following article discusses a C Compiler Version 5.10 program
- called SORTDEMO.C, which is similar to the program that comes with
- QuickBasic Version 4.00.
-
- SORTDEMO.C for C Version 5.10 is for OS/2. It has OS/2 VIO, KBD, and
- DOS calls. If it has been bound, it can run in DOS and real-mode OS/2,
- as well as protected-mode OS/2.
-
- The following information details the correct way to run SORTDEMO.C
- (for a system targeting DOS):
-
- cl /Lp /Zp sortdemo.c
- bind sortdemo.exe c:\c\lib\doscalls.lib c:\c\lib\api.lib apilmr.obj
-
- The following is an example of several incorrect ways, their results,
- and their problems (for a system targeting DOS):
-
- 1. Command: cl /Fb /Lp sortdemo.c (/Fb means to bind the application)
-
- Result: It links and appears to bind, but it hangs the computer
- when it runs from DOS.
-
- Problem: Apilmr.obj also needs to be bound. It must perform a
- separate bind.
-
- 2. Command: cl /Fb /Lp sortdemo.c apilmr.obj
-
- Result: It links and appears to bind, but it hangs the computer
- when it runs from DOS.
-
- Problem: Apilmr.obj needs to be bound with the application because
- the application makes VIO calls and it accesses the near heap.
-
- Perform a separate bind (there is no way to bind in apilmr.obj from
- the cl compile line).
-
- 3. Command: cl /Lp sortdemo.c /link doscalls.lib api.lib
-
- Result: The linker gives the error: __acrtused multiply defined
- error.
-
- Problem: You should only link DOSCALLS.LIB. Bind it if it will be
- used under DOS.
-
- 4. Command: cl sortdemo.c
-
- Result: The linker gives 13 unresolved externals, such as
- KBDCHARIN, VIO* and DOS*.
-
- Problem: SORTDEMO.C is an OS/2 application. The program must be
- compiled using the /Lp switch, and then bound if it will be used
- under DOS.
-
- 5. Command: cl /Lp sortdemo.c or cl /Lp /Zp sortdemo.c
-
- Result: It worked correctly for running under OS/2. To run under
- DOS, you must Bind it using the following:
-
- bind sortdemo.exe c:\c\lib\doscalls.lib c:\c\lib\api.lib apilmr.obj
-
-
- 23. Why Pointer Subtraction Gives Signed Results
-
- Product Version(s): 3.00 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 14-MAR-1990 ArticleIdent: Q29197
-
- Pointer subtraction is performed in signed arithmetic. This can
- become confusing when the pointers being subtracted are more than 32K
- apart, because the result becomes a negative number.
- This is correct behavior for the C language as documented in the
- "Microsoft C Language Reference Manual" and the ANSI C Draft Proposed
- Standard.
-
- Consider the following code fragment:
-
- long size;
- char *ptr1, *ptr2;
- if (size < (ptr2 - ptr1))
- ...
- If the size is 32000, ptr1 is 0, and ptr2 is 33000, then ptr2 minus
- ptr1 exceeds the range of a signed value and is therefore negative.
- The comparison size (ptr2 - ptr1) is false, even though ptr1 and ptr2
- are 33000 elements apart.
- This situation is documented on Page 124 of the "Microsoft C
- Language Reference Manual," (Version 5.00 and Version 5.10) which says
- the following:
-
- "When two pointers are subtracted, the difference is converted to a
- signed integral value by dividing the difference by the size of a
- value of the type that the pointers address. The size of the integral
- value is defined by the type ptrdiff_t in the standard include file
- stddef.h."
-
- This also is documented on Page 3.3.6 of the November 9, 1987,
- edition of the Draft Proposed ANSI C Standard, which states the
- following:
-
- "The size of the result is implementation-defined, and its type (a
- signed integral type) is ptrdiff_t defined in the <stddef.h> header.
- As with any other arithmetic overflow, if the result does not fit in
- the space provided, the behavior is undefined."
-
- If you want to think of these pointers as unsigned quantities, you
- can typecast them as follows:
-
- long size;
- char *ptr1, *ptr2;
- if (size < ((unsigned) ptr2 - (unsigned) ptr1))
- ...
-
-
- 24. Incorrect Interface Statement
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q29589
-
- The last example on Page 48 of the "Microsoft C 5.1 Optimizing
- Compiler Mixed-Language Programming Guide" reads as follows:
-
- INTERFACE TO FUNCTION REAL*8 CFUN [C] (I,J)
-
- This is incorrect. It should read as follows:
-
- INTERFACE TO REAL*8 FUNCTION CFUN [C] (I,J)
-
-
- 25. Structure Packing: /Zp4 or #pragma pack(4), and /Zp2
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q29825
-
- The /Zp4 compiler option or #pragma pack(4) results in a more
- efficient use of space than indicated on Pages 100 to 102 in both the
- "Microsoft C 5.00 Optimizing Compiler User's Guide" and the "Microsoft
- C 5.10 Optimizing Compiler User's Guide." When the C compiler aligns
- structure members, it uses the /Zp4 or #pragma pack(4) (or /Zp2 or
- #pragma pack(2) values) as the maximum number of bytes for alignment,
- but will word (even-byte) align individual struct members whose size
- is one or two bytes. Contiguous char or array of char members that are
- immediately preceded by char members will be byte aligned.
-
- When specifying 4-byte (or 2-byte) boundaries for aligning structure
- members, the actual alignment is dependent on the size of the structure
- member. To avoid wasting space, the compiler will word align structure
- members that are one or two bytes in size. Structure members whose size
- is four or eight bytes or greater will be aligned on 4-byte boundaries
- with the /Zp4 switch or #pragma pack(4) as documented.
-
- Char or array of char struct members will be byte aligned if they are
- preceded by a char struct member, otherwise they will be word aligned.
- (Search on "Zp" and "char" to find articles with more information on
- the alignment of char struct members.)
-
- The sizeof operator correctly indicates the actual size of the
- structure with any alignment of struct members.
-
- Note that this struct member alignment is different than that which
- occurred with previous versions of Microsoft C compilers. If using
- object files containing structures produced by C 4.00 or earlier
- compiler versions, it may be necessary to use dummy bytes to word
- align contiguous char struct members.
-
- To gain complete control over the alignment of struct members, you may
- use the /Zp or /Zp1 compiler options, or #pragma pack(1), and pad your
- struct with an appropriate number of dummy char or array of char
- members.
-
-
- 26. C 5.10 MTDYNA.DOC File: Single-Thread Dynamic-Link Libraries
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 18-AUG-1989 ArticleIdent: Q29826
-
- The following information is from "Section 5: Creating Dynamic-Link
- Libraries" of the Microsoft C Version 5.10 MTDYNA.DOC file.
-
- 5.1 Single-Thread Dynamic-Link Libraries
- The OS/2 support library, LLIBCDLL.LIB, is a large-model,
- single-thread C run-time library for creating dynamic-link
- libraries. This support library is statically linked and uses only the
- alternate math library.
- To make the dynamic-link library independent of the program that
- calls it, the dynamic-link library must preserve the floating-point
- state and the status of the 80286 CPU registers. This is not possible
- with the emulator floating-point library, since it takes over the 287
- chip. However, math done with the alternate math library is done
- entirely with the 80286 registers. Since the status of the registers
- is preserved, the alternate math package fits the requirement for the
- single-thread dynamic-link library.
- The LLIBCDLL.LIB C OS/2 support library is not reentrant, and so
- only one thread per process may be executing in it. When creating a
- single-thread dynamic-link library, you should ensure that only one
- thread per process is ever executing in the C run-time library.
- A dynamic-link library written with LLIBCDLL.LIB can handle
- multiple threads within a process only by explicit serialization using
- semaphores or some similar mechanism to ensure that only one thread
- per process is executing in the C run-time library. In all cases the C
- run-time initialization code must be executed at program startup. This
- is normally done through the per-process automatic initialization
- mechanism provided to OS/2 dynamic-link libraries.
- Dynamic-link libraries created with this library must be linked
- with LLIBCDLL.LIB and DOSCALLS.LIB only. No other libraries should be
- used when linking.
- NOTE: This restriction on library use means that the compiler
- option /Lp must not be used with LLIBCDLL.LIB. If you are building
- objects for use with LLIBCDLL.LIB, you should use compiler option /Zl
- to suppress default-library search records in the object file. If
- not, you then MUST link with /NOD so that you do not get a default
- library (such as SLIBCE.LIB) linked in as well.
- This model uses the C register convention where AX, BX, CX, DX and
- ES are scratch registers. The direction flag is always assumed to be
- cleared ("up").
- The signal function is supported only for the SIGFPE signal. This
- floating-point exception is not a true signal, but is more like an
- exception.
- The DosSetSigHandler OS/2 API call should only be used with great
- caution since it can "steal" signals from the user program thereby
- causing problems in this environment.
-
- Editor's Note: The information above applies to single-thread DLL's
- linked with LLIBCDLL.LIB only. Multi-thread .EXE's built with
- LLIBCMT.LIB, or multi-thread DLL's that dynamically link to CRTLIB.DLL
- use emulator math only, and will use a coprocessor if it is present.
-
-
-
- 27. C 5.10 MTDYNA.DOC: Threads
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29830
-
- The following information is from "Section 1: Introduction" of the
- Microsoft C version 5.10 MTDYNA.DOC file.
-
- 1.1 Threads
-
- Three types of multitasking are present in OS/2: screen groups,
- processes, and threads. A screen group, the highest-level multitasking
- element, consists of one or more processes that share a logical screen
- and keyboard. For example, a word processor and a database operating
- simultaneously under OS/2 would represent two screen groups. A process
- is the part of an executing program that is the unit of ownership for
- resources such as memory, open files, and semaphores. Finally, a
- thread is the execution path within a process, and it is the smallest
- multitasking unit managed by OS/2. A process may consist of one or
- more threads.
-
- Two sample programs supplied with this release highlight the use of
- threads. The first example program, mhello.c, is a multiple-thread
- version of the classic "Hello world" program. The second example
- program, snap.c, uses multiple threads to capture screen images to a
- file.
-
- A pictorial representation of screen groups, processes, and threads is
- shown in Figure 1 below. Each screen group consists of two processes.
- These processes are composed of several threads. In any process,
- thread 1 is the main thread. All threads in a process are independent.
-
- Figure 1. Screen Groups, Processes, and Threads
-
- +============================================================================
- |
- | OS/2
- |
- | +----------------------------------+ +----------------------------------+
- | | Screen Group 1 | | Screen Group 2 |
- | | +------------+ +------------+ | | +------------+ +------------+ |
- | | | Process 1 | | Process 2 | | | | Process 1 | | Process 2 | |
- | | | | | | | | | | | | |
- | | | *Thread 1* | | | | | | *Thread 1* | | *Thread 1*| |
- | | | | | *Thread 1* | | | | *Thread 2* | | | |
- | | | *Thread 2* | | | | | | *Thread 3* | | *Thread 2*| |
- | | | | | | | | | | | | |
- | | +------------+ +------------+ | | +------------+ +------------+ |
- | | | | |
- | +----------------------------------+ +----------------------------------+
- |
- +============================================================================
-
-
- 28. C 5.10 MTDYNA.DOC: Dynamic-Link Libraries
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29832
-
- The following information is from "Section 1: Introduction" of the
- Microsoft C version 5.10 MTDYNA.DOC file.
-
- 1.2 Dynamic-Link Libraries
-
- A dynamic-link library is a set of routines that are linked with the
- program at either load time or run time rather than at the time of
- compilation.
-
- The easiest way to understand dynamic linking is to contrast it with
- the more familiar method of static linking.
-
- Static linking involves the following steps:
-
- 1. Write and compile a program that calls routines (such as the
- printf() function) not in the source file. This produces an object
- file that contains a reference to the external printf() function.
-
- 2. Link the object file with a library file containing the external
- function. This linking step combines the two files by including the
- code for the printf() function into the final executable file. In
- other words, the reference to printf() is resolved at link time.
-
- 3. Run the executable file from step 2. This executable file is
- totally self contained (since it contains the code for the external
- function).
-
- Static linking is useful, but it has the following disadvantages:
-
- 1. The finale executable code cannot be upgraded or changed without
- relinking to the main program's object files. In the commercial
- realm this means that a new release of a program requires that the
- entire executable file be replaced with a new version.
-
- 2. Common sets of code cannot be shared. Any and all executable files
- that use the printf() function must explicitly link in this
- function. Thus, the code for printf()may be duplicated in many
- different executable files on a disk or in memory.
-
- Dynamic linking, on the other hand, involves the following general
- steps (the complete process is detailed in Section 5.0 below):
-
- 1. Write and compile a program that references an external function,
- just as you do for static linking.
-
- 2. Create a special definition file (.DEF extension) that specifies
- which functions the main program will import from the dynamic-link
- library.
-
- 3. Link the main program with the appropriate dynamic-link library
- support library to produce an executable file. This file contains a
- reference to the external function in the dynamic-link library.
- This file does NOT contain any code from the external function.
-
- 4. Create a dynamic-link library that contains the code referenced in
- the main program.
-
- 5. Execute the program created in step 3. When this executable file is
- run, OS/2 loads the code and discovers the special reference to the
- dynamic-link library. For each external dynamic-link-library
- reference, OS/2 searches the dynamic-link-library directory and
- resolves the external reference at load time.
-
- The process of dynamic linking has the following advantages:
-
- 1. An executable file is smaller since it does not contain the code
- for external functions.
-
- 2. A program can be upgraded by supplying a new version of the
- dynamic-link library without relinking the executable file.
-
- 3. Code may be shared between executable files. A common set of
- routines can be placed in a dynamic-link library and accessed by
- any number of executable files. In fact, the OS/2 operating system
- itself is a dynamic-link library. All of the OS/2 system functions
- are presented as external procedures that a user program can call.
-
- 4. Linking is faster.
-
-
- 29. C 5.10 MTDYNA.DOC: Multiple-Thread Programs
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 10-DEC-1990 ArticleIdent: Q29833
-
- The following information is from "Section 2: Multiple-Thread
- Programs" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- Multiple-Thread Programs
- ------------------------
-
- The simplest multiple-thread program is an independent self-contained
- program that is created by the static linking method.
-
- The support library LLIBCMT.LIB is a large-model library that supports
- the creation of multiple-thread programs. A multiple-thread program
- created with this library can be any memory model although all calls
- to the C run-time library must use the large-model calling interface.
- In other words, all pointers must be far.
-
- NOTE: The support library library LLIBCMT.LIB is a large model
- library. If you want to use pointers returned by the C run-time
- library, you must use the far keyword in the declaration of your
- variables. For example, if you want to call fopen(), you would need to
- say:
-
- FILE far * fp;
- fp = fopen (...);
-
- This C run-time library is used to create a program that is entirely
- self contained and that does not share C run-time code or data with
- any other programs or dynamic-link libraries.
-
- A multiple-thread program that uses this library must be linked with
- only LLIBCMT.LIB and DOSCALLS.LIB. No other C run-time libraries
- should be used in linking.
-
- NOTE: This restriction on library use means that the compiler option
- /Lp must not be used with LLIBCMT.LIB. If you are building objects for
- use with LLIBCMT.LIB, you should use compiler option /Zl to suppress
- default library search records in the object file. If not, you then
- must link with /NOD (/NODEFAULTLIBRARYSEARCH) so that you do not get a
- default library (such as SLIBCE.LIB) linked in as well.
-
- Programs created for this simple multiple-thread environment should
- use the special include files provided for this purpose. These files
- are normally stored in the MT subdirectory of your normal include
- directory and the constituent .h files have the same name as their
- regular C run-time counterparts.
-
- These special include files should only be used for creating
- multiple-thread programs. If the regular (that is, the include files
- in the \INCLUDE subdirectory) are used, multiple-thread programs will
- not work. Conversely, the multiple-thread include files should not be
- used to create nonthreaded C programs.
-
- Threads are managed in a multiple-thread program by the C functions
- _beginthread() and _endthread(). A description of these two functions
- is given below in Section 3.0. The OS/2 Applications Program Interface
- (API) call DosCreateThread should not be used. If the low-level API
- calls (DosCreateThread and DosExit) are used, the results are
- unpredictable.
-
- In a multiple-thread program, stack checking is done for each thread.
-
- Signal handling is complicated in a multiple-thread environment. In a
- multiple-thread environment, the C run-time function signal is not
- supported. Since OS/2 always gives thread 1 control when a signal is
- handled, thread 1 must not be executing in the C run-time library code
- when a signal is received. If this precaution is not followed, the
- possibility of deadlock arises. A deadlock occurs if a thread is
- waiting for a particular event that does not occur.
-
- Signal handling is managed in a multiple-thread environment by using
- the OS/2 API call DosSetSigHandler with the following restrictions:
-
- 1. Thread 1 should be dedicated to signal handling and this thread
- should not call the C run-time library. When a signal is detected
- by thread 1, some type of semaphore or flag that will be polled
- from the other threads in the program should be set.
-
- 2. The other threads check the status of semaphores set by thread 1
- and respond accordingly.
-
-
- 30. C 5.10 MTDYNA.DOC: Sample MT Program/Description of Operation
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29835
-
- The following information is from "Section 4: Sample Multiple-Thread C
- Program" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- Sample Multiple-Thread C Program
- --------------------------------
-
- The subsections below describe the creation and operation of a
- multiple-thread version of the classic "Hello world" program.
-
- 4.1 Description of operation
-
- The multiple-thread "Hello world" program brings up one thread for
- each command-line argument. Each thread will print "Hello world from
- thread <n>!" the number of times specified in the corresponding
- argument. The maximum number of threads supported in the
- multiple-thread library is 32.
-
- To use it, type
-
- mhello <arg1> <arg2> ... <up to 31 args>
-
- For example,
-
- mhello 2 4 6
-
- brings up 3 threads; the first thread says hello 2 times, the second
- thread says hello 4 times, the third thread says hello 6 times.
-
- In operation, the program works as follows:
-
- 1. Brings up the requested number of threads with _beginthread
-
- 2. Waits until all threads have been brought up
-
- 3. Begins multiple-thread execution and waits for completion
-
- The explicit synchronization (by means of the flag variable
- Synchronize) is required because of the small time spent in the child
- code. Without this synchronization, all threads would begin as thread
- 2. This occurs because the first spawned thread completes execution
- before the next request to create a thread is acted upon. The time
- slice allotted to any of the threads is much larger than the execution
- time spent in each thread. To get around this, bring up all of the
- threads and then simultaneously start them.
-
- An alternative method of synchronization between threads is to use
- semaphores. A semaphore is a software flag used to coordinate the
- activities of two or more threads. The use of semaphores for thread
- control is illustrated in the sample program, snap.c, which is
- included with this release.
-
- Using semaphores is a more elegant and efficient means of
- synchronizing threads. The DosSleep function causes threads to
- periodically wake up and check a flag, and thus, the following can
- occur:
-
- 1. The thread wakes up when it doesn't have to and performs some
- processing only to find out it has to go to sleep again.
-
- 2. The thread sleeps longer than it has to (i.e., the event it's
- waiting for has already occurred, but the thread is still sleeping
- until the sleep request expires).
-
- Programs should generally use semaphores, particularly when the wait
- time is non deterministic and potentially long (or forever).
-
- For the mhello.c example program, the use of DosSleep is appropriate
- for the following reasons:
-
- 1. DosSleep is easily understood and has self-evident functionality.
-
- 2. The program is not particularly time dependent, and the above two
- disadvantages will not hurt. Also, we know that this is a one time
- event, and that main code "quickly" wakes up the child-code portion
- of the program. That is, the DosSleep code path occurs once at
- start-up time and is never entered again during child execution.
-
- Also, the sleep time is short and deterministic. That is, we know
- the parent code sets the flag as soon as all the threads have been
- started. In other words, there is no chance for the parent code to
- do other things and leave the thread waiting for DosSleep for long
- periods of time.
-
-
- 31. C 5.10 MTDYNA.DOC: Sample MT Program/Compiling and Linking
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29836
-
- The following information is from "Section 4: Sample Multiple-Thread C
- Program" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- 4.2 Compiling and Linking a Multiple-Thread Program
-
- The program mhello.c is a statically linked multiple-thread program.
- The process of compiling and linking this program is given below:
-
- 1. Ensure that the files LLIBCMT.LIB and DOSCALLS.LIB are available.
-
- The file LLIBCMT.LIB takes the place of the regular *.LIB files
- used in linking. It is a large-model library that supports the
- creation of statically linked multiple-thread programs. A
- multiple-thread program created with this library can be any memory
- model, although all calls to the C run-time library must use the
- large-model calling interface.
-
- The file DOSCALLS.LIB provides support for any OS/2 calls made in
- the multiple-thread program. In this example, the DosSleep function
- is used.
-
- 2. Ensure that the special multiple-thread include files are used.
- These are normally stored in the MT subdirectory of the normal
- \INCLUDE directory. In this example, this is done by explicitly
- specifying them within the mhello.c program as shown below:
-
- #include <mt\malloc.h>
-
- The multiple-thread files may also be specified by using the \I
- option on the CL command line. The multiple-thread dynamic-link
- library example (Section 5.2.3) uses this method to specify an
- alternate include directory path.
-
- 3. Compile the program with the following conditions set:
-
- a. Large code-pointer size
- b. Far data-pointer size
- c. Segment setup of SS not equal to DS; DS fixed
-
- These conditions are specified by setting up a customized memory
- model using the following CL command option:
-
- /Alfw
-
- The complete CL invocation is shown below:
-
- CL /Alfw /c mhello.c
-
- 4. Link the resulting object file with LLIBCMT.LIB and DOSCALLS.LIB
- only. The default .LIB file should not be used. Specify the
- /NODEFAULTLIBRARY search option (/NOD) to ignore the default
- libraries.
-
- The complete LINK invocation is shown below:
-
- LINK /NOD thread LLIBCMT.LIB DOSCALLS.LIB;
-
- An alternative invocation that invokes both the compiler and linker
- is shown below:
-
- CL /Alfw /Zl mhello.c /link llibcmt doscalls
-
- 5. Run the program under OS/2.
-
-
- 32. C 5.10 MTDYNA.DOC: Sample MT Program/Possible Problem Areas
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29837
-
- The following information is from "Section 4: Sample Multiple-Thread C
- Program" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- 4.3 Possible Problem Areas
-
- Several possible problems may occur when creating, linking, or
- executing a multiple-thread C program. Some of the more common ones
- are listed below. The symptom is listed first, followed by the likely
- cause:
-
- 1. LINK searches for xLIByz.LIB
-
- This is caused by omitting the /NOD option from the LINK command.
- If /NOD is omitted, LINK searches for the default library. The
- default library should NOT be used with multiple-thread programs.
- The /NOD option tells the computer not to search the default
- libraries. This problem may also be avoided by compiling with the
- /Zl option which suppresses default library search records in the
- object files.
-
- 2. You get the following execution error:
-
- SYS1943: A program caused a protection violation.
-
- This is caused by failing to specify the condition "SS is not equal
- to DS" in the CL command invocation. Specify the correct conditions
- with the /Alfw customized memory-model option. Recompile the
- program with /Alfw.
-
-
- 33. C 5.10 MTDYNA.DOC: Creating Dynamic-Link Libraries
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29838
-
- The following information is from "Section 5: Creating Dynamic-Link
- Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- Creating Dynamic-Link Libraries
-
- You can create the following two types of dynamic-link libraries with
- this release of C:
-
- 1. A stand-alone, single-thread dynamic-link library
-
- 2. A C run-time dynamic-link library that supports multiple threads
- and is itself dynamically linked.
-
- The stand-alone dynamic-link library is independent of the calling
- program and is single thread only and statically linked. This isolated
- dynamic-link library is independent of the effects of other
- dynamic-link libraries and can be viewed conceptually as an extension
- of the operating system. Use the OS/2 support library, LLIBCDLL.LIB, a
- large-model, single-thread C run-time library for creating
- single-thread dynamic-link libraries. LLIBCDLL.LIB is statically
- linked and uses only the alternate math library.
-
- The dynamically-linked C run-time library may be used by a
- multiple-thread program and an optional group of dynamic-link
- libraries that are closely associated with it. Use the OS/2 support
- library, CDLLOBJS.LIB to create a C run-time library that is
- dynamically linked.
-
- Dynamic-link libraries can be debugged with the protected-mode
- CodeView debugger (CVP). For more information on this topic, see
- Section 2.2.2 "Debugging Dynamic-Link Modules" in the Microsoft
- CodeView and Utilities Update document.
-
-
- 34. C 5.10 MTDYNA.DOC: Component Files of a Single Thread DLL
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29839
-
- The following information is from "Section 5: Creating Dynamic-Link
- Libraries" of the Microsoft C Version 5.10 MTDYNA.DOC file.
-
- 5.1.1 Component Files of Single-Thread Dynamic-Link Libraries
-
- Several files are supplied for the creation of single-thread
- dynamic-link libraries. A list and brief description of the files
- supplied with this release is shown below:
-
- DOSCALLS.LIB OS/2 support library.
-
- LLIBCDLL.LIB Large-model single-thread C run-time library
- for dynamic-link library support.
-
- xLIByP.LIB Any protected-mode C run-time library; used to
- link sample main program.
-
- STMAIN.C Sample main program (single-thread version).
- STMAIN.DEF Module-definition file for main program
- (single-thread).
-
- STDLL.C Sample dynamic-link library file.
- STDLL.DEF Module-definition file for STDLL.C.
-
- MKSTDLL.CMD OS/2 batch file for creating single-thread
- dynamic-link library.
-
-
- 35. C 5.10 MTDYNA.DOC: Creating a Single Thread DLL
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29840
-
- The following information is from "Section 5: Creating Dynamic-Link
- Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- 5.1.2 Creating a Single-Thread Dynamic-Link Library
-
- The process of creating a single-thread dynamic-link library is
- outlined below:
-
- 1. Create a definition file (.DEF extension) for the main program
- (STMAIN.DEF). This definition file specifies which functions it
- will import from the dynamic-link library. In this simple example,
- the file STMAIN.DEF contains the following:
-
- NAME STMAIN
- IMPORTS STDLL._DynalibTest
-
- 2. Create a definition file for the dynamic-link library (STDLL.DEF)
- that specifies which functions it will export. In this simple
- example, the file STDLL.DEF contains the following:
-
- LIBRARY STDLL
- DESCRIPTION 'Sample Dynamic-Link Library written in Microsoft C'
- PROTMODE
- EXPORTS _DynalibTest
- DATA MULTIPLE
-
- 3. Compile the main program. The program may be compiled using any
- memory model and any math package. Since the sample single-thread
- dynamic-link library (STDLL.C) uses far data, the sample main
- program (STMAIN.C) can be compiled as either compact or large
- memory model. For a compact memory model, the C compiler is invoked
- with something like this:
-
- cl /AC /G2 /c stmain.c
-
- 4. Link the main program to produce STMAIN.EXE. The following files
- are linked together:
-
- STMAIN.OBJ Output from step 3
- DOSCALLS.LIB OS/2 support library
- CLIBCEP.LIB Any regular C run-time library (in this
- case, compact memory model, emulator math
- package)
- STMAIN.DEF Main definition-module (single thread)
- STMAIN.EXE Output from LINK (single thread)
-
- The linker is invoked with something like this:
-
- link stmain.obj/noi,,, clibcep.lib doscalls.lib/nod,stmain.def;
-
- 5. Compile the dynamic-link library module. The module should be
- compiled with the /ALfw option which specifies large-code pointer
- size, far-data pointer size and a segment setup of SS not equal to
- DS; DS fixed. Stack checking should also be turned off. The C
- compiler is invoked with something like this:
-
- cl /Alfw /G2 /Gs /c stdll.c
-
- 6. Link the dynamic-link library module to produce STDLL.DLL. The
- following files are linked together:
-
- STDLL.OBJ Output from step 5
- DOSCALLS.LIB OS/2 support library
- LLIBCDLL.LIB Single-thread dynamic-link library C
- run-time support library
- STDLL.DEF Dynamic-link library definition-module
- STDLL.DLL Output from LINK
-
- The linker is invoked with something like this:
-
- link stdll.obj,stdll.dll/noi,,llibcdll.lib doscalls.lib/nod,stdll.def;
-
- 7. Place the STDLL.DLL file (from step 6) in a directory on your
- LIBPATH so OS/2 is able to find it. Then run the program
- STMAIN.EXE. If the dynamic-link-library file is not in your
- LIBPATH, OS/2 is not be able to run STMAIN.EXE.
-
- Note: The LIBPATH is set in your CONFIG.SYS or CONFIG.OS2 file,
- depending on which version of OS/2 you are using. LIBPATH is not part
- of your environment strings like the LIB, INCLUDE and PATH variables.
-
-
- 36. C 5.10 MTDYNA.DOC: Multiple Thread Dynamic-Link libraries
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29841
-
- The following information is from "Section 5: Creating Dynamic-Link
- Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- 5.2 Multiple-Thread Dynamic-Link Libraries
-
- The CDLLOBJS.LIB OS/2 support file is an object-file library used to
- create a dynamically linked C run-time library. This library is
- provided as an object library with an associated definition file. This
- allows the programmer to choose only those run-time modules that are
- required for a particular application.
-
- The C run-time library created with this support file is dynamically
- linked and may be used by a multiple-thread program and an optional
- group of dynamic-link libraries that are closely associated with it.
-
- The "close association" of the multiple-thread program, the C run-time
- library and a group of dynamic-link libraries is shown in Figure 2.
-
- +----------------------------------------------------+
- | |
- | +----------+ +----------+ |
- | | | | | |
- | +-----------> | DLL1.DLL |<------>| DLL2.DLL |<---+
- | | | |<-+ | |<----------+
- | | +----------+ | +----------+ |
- +-------------+ | |
- | | | |
- | PROGRAM.EXE | | |
- | |<---+ | |
- +-------------+ | | |
- | | +--------------------+ |
- | | | | |
- | +-->| C Run-time DLL |<--+
- +------------------>| CRTLIB.DLL |
- +--------------------+
-
- Figure 2. Relationship between Multiple-Thread Program, C
- Run-Time Library, and Dynamic-Link Libraries
-
- The main program (PROGRAM.EXE) and the two dynamic-link libraries
- (DLL1.DLL and DLL2.DLL) share the C run-time data (in CRTLIB.DLL). The
- PROG.EXE, DLL1.DLL, and DLL2.DLL files each have their own data
- segment that is not shared. The C run-time dynamic-link library is
- closely tied to the program (PROGRAM.EXE) and the other dynamic-link
- libraries (DLL1.DLL and DLL2.DLL), since the file CRTLIB.DLL contains
- such things as shared environment strings, global C run-time data, and
- thread identification numbers.
-
- A program built using the dynamically linked multiple-thread support
- of the C run-time library may share the C run-time library with one or
- more dynamic-link libraries that are closely related to it. C run-time
- global data (such as the standard I/O package FILE, pointers of
- buffered I/O, and memory allocated with malloc functions) is shared.
- This means that the program and the associated dynamic-link libraries
- must cooperate on the usage of this data.
-
- Before compiling any programs using routines from the dynamic-link
- library's object library CDLLOBJS.LIB, ensure that the MT include
- files are being used (rather than the standard include files), and
- that the symbol DLL is defined.
-
- If the multiple-thread include files are placed in a subdirectory of
- the normal INCLUDE directory the following style of include can be
- used:
-
- #include <mt\stdio.h> /* multiple-thread version */
-
- A better approach is to specify a special search path for include
- files by using the /I option on the CL command line. In this method,
- the /I adds the specified directory to the front of the list of
- directories to be searched for include files. A typical use of the /I
- option is shown below:
-
- cl /I\include\mt /AS /Gs2 /DDLL /c mtmain.c
-
- This method has the advantage that the program can refer to <stdio.h>,
- and the appropriate version can be selected at compile time. This
- approach is used in the sample programs mtmain.c and mtdll.c. If
- multiple include paths are required, you can specify them with
- multiple /I options. The include paths are searched in the order in
- which they appear on the CL command line.
-
- The symbol DLL is used to distinguish between multiple-thread programs
- using LLIBCMT.LIB (where the symbol DLL is not defined) and programs
- using the dynamically linked C run-time library (where the symbol DLL
- is defined), which also supports multiple threads.) This ensures that
- the appropriate data references (e.g. stdout) are resolved correctly.
- The symbol DLL may be defined in one of the ways shown below:
-
- 1. Compile with the /D option on the CL command line. The use of this
- option is explained in Section 3.3.9.1 of the Microsoft C
- Optimizing Compiler User's Guide. The syntax of the /D option is
-
- CL /DDLL myprog.c
-
- 2. Explicitly define the DLL symbol prior to any other preprocessor
- directives in your source file. This option is shown below:
-
- #define DLL
- #include < ... > /* include files as needed */
-
- Threads are managed in a dynamic-link library created in this
- environment by the C functions _beginthread() and _endthread(). The
- OS/2 API call DosCreateThread should not be used. A description of
- these two functions is given in Section 3.0.
-
-
- 37. C 5.10 MTDYNA.DOC: Component Files of MTDYNA Libraries
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29842
-
- The following information is from "Section 5: Creating Dynamic-Link
- Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- 5.2.1 Component Files of Multiple-Thread Dynamic-Link Libraries
-
- A large number of files are supplied for the creation of
- multiple-thread dynamic-link libraries. A list and brief description
- of the files supplied with this release is shown below:
-
- CRTDLL.OBJ Start-up code for dynamic-link library files.
- CRTEXE.OBJ Start-up code for executable files.
- CRTLIB.OBJ Start-up code for C run-time library.
-
- CDLLOBJS.LIB C run-time library objects.
- CDLLOBJS.DEF Module-definition file that contains the entry
- points for all C functions.
- CDLLOBJS.CMD OS/2 batch file to create multiple-thread C
- run-time dynamic-link library.
-
- CDLLSUPP.LIB Supplemental file that contains C run-time
- information that cannot be dynamically linked.
-
- MTMAIN.C Sample main program (multiple thread).
- MTMAIN.DEF Module-definition file for main (multiple
- thread).
-
- MTDLL.C Sample dynamic-link library file (multiple
- thread).
- MTDLL.DEF Module-definition file for DLL.C (multiple
- thread).
-
- MKMTDLL.CMD OS/2 batch file for creating multiple-thread
- dynamic-link library.
-
-
- 38. C 5.10 MTDYNA.DOC: Creating an MTDYNA Library
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29843
-
- The following information is from "Section 5: Creating Dynamic-Link
- Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- 5.2.2 Creating a Multiple-Thread Dynamic-Link Library
-
- The process of creating a multiple-thread dynamic-link library is
- outlined below. The process of creating a multiple-thread dynamic-link
- library is also contained in the file CDLLOBJS.CMD.
-
- 1. Create a definition file that specifies the exports from the C
- run-time library for the dynamic-link library. The file
- CDLLOBJS.DEF, which is included in this release, is a sample
- definition file that includes all of the C run-time functions
- currently supported.
-
- 2. Link the special start-up file CRTLIB.OBJ with CDLLOBJS.LIB,
- DOSCALLS.LIB, and the definition file (CDLLOBJS.DEF) from step 1.
- This creates a customized C run-time dynamic-link library file
- (named CRTLIB.DLL). The following files are linked together:
-
- crtlib.obj Start-up code for library files
- cdllobjs.lib C run-time library objects
- doscalls.lib OS/2 support library
- cdllobjs.def Definition module from step 1
- crtlib.dll Output from LINK
-
- The command to accomplish this is shown below:
-
- link crtlib.obj,crtlib.dll/noi,,cdllobjs.lib doscalls.lib/nod/noe,cdllobjs.de
-
- 3. Run IMPLIB on the definition file from step 1 to create a
- customized library file (CRTLIB.LIB) containing the exported
- functions. The command is shown below:
-
- implib crtlib.lib cdllobjs.def
-
- 4. Use the Microsoft Library Manager (LIB) to append CDLLSUPP.LIB to
- the customized library created in step 3. The file CDLLSUP.LIB
- contains a few small routines that cannot be dynamically linked
- because they are called near. The LIB program automatically creates
- a back-up file (with a .BAK extension), which can be deleted. The
- command for this step is shown below:
-
- lib crtlib.lib+cdllsupp.lib;
-
-
- 39. C 5.10 MTDYNA.DOC: Using an MTDYNA Library
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29844
-
- The following information is from "Section 5: Creating Dynamic-Link
- Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
-
- 5.2.3 Using a Multiple-Thread Dynamic-Link Library
-
- Once a C run-time multiple-thread dynamic-link library has been
- created (Section 5.2.2), it can be used by a program and associated
- dynamic-link libraries. The process of using this C run-time
- dynamic-link library is shown below:
-
- 1. Compile the main program. When creating executable and dynamic-link
- library files that will use the dynamically linked C run-time
- library, the C compiler must be called with the multiple-thread
- versions of the include files. Additionally, stack checking must be
- turned off if your code is being compiled as small or compact
- models. Stack checking can only be supported in the dynamically
- linked C run-time library using far calls (medium/large memory
- models). The C compiler is invoked with something like this:
-
- cl /I\include\mt /AS /Gs2 /DDLL /c mtmain.c
-
- The /Gs option specifies no stack checking. The /DDLL option
- defines the DLL symbol. The /AS option specifies small memory
- model. The /I\include\mt option specifies that the special
- multiple-thread include files are to be used.
-
- 2. Link the main program to produce MTMAIN.EXE. The following files
- are linked together:
-
- mtmain.obj Output from step 1
- crtexe.obj Start-up code for executable files
- crtlib.lib Customized C run-time library (Section 5.2.2)
- doscalls.lib OS/2 support library
- mtmain.def Definition file for mtmain.c
- mtmain.exe Output from LINK
-
- The linker is invoked with something like this:
-
- link mtmain+crtexe,/noi,,crtlib.lib doscalls.lib/nod,mtmain.def;
-
- 3. Compile the dynamic-link-library module. When creating executable
- and dynamic-link library files that will use the dynamically linked
- C run- time library, the C compiler must be called with the
- multiple-thread versions of the include files. Additionally, stack
- checking must be turned off if your code is being compiled as small
- or compact model. Stack checking can only be supported in the
- dynamically linked C run-time library using far calls
- (medium/large memory models.) The C compiler is invoked with
- something like this:
-
- cl /I\include\mt /Alfw /G2 /DDLL /c mtdll.c
-
- The /Alfw option specifies large code-pointer size, far
- data-pointer size and a segment setup of SS not equal to DS; DS
- fixed. The /DDLL option defines the DLL symbol. The /I\include\mt
- option specifies that the special multiple-thread include files are
- to be used.
-
- 4. Link the dynamic-link-library module to produce MTDLL.DLL. The
- following files are linked together:
-
- mtdll.obj Output from step 3
- crtdll.obj Start-up code for dynamic-link library files
- crtlib.lib Customized C run-time library (Section 5.2.2)
- doscalls.lib OS/2 support library
- mtdll.def Dynamic-link library definition file
- mtdll.dll Output from LINK
-
- The linker is invoked with something like this:
-
- link mtdll+crtdll,mtdll.dll/noi,,crtlib.lib doscalls.lib/nod,mtdll.def;
-
- 5. Place the MTDLL.DLL file (from step 4) and the CRTLIB.DLL file
- (from Section 5.2.2) in a directory on your LIBPATH so OS/2 can
- find it. Then run the program MTMAIN.EXE. If either dynamic-link
- library file is not in your LIBPATH, OS/2 will not be able to run
- MTMAIN.EXE.
-
- Note: The LIBPATH is set in your CONFIG.SYS or CONFIG.OS2 file,
- depending on which version of OS/2 you are using. LIBPATH is not part
- of your environment strings like the LIB, INCLUDE and PATH variables.
-
-
- 40. C 5.10 MTDYNA.DOC: Matrix of Components
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q29845
-
- The following information is from "Section 6: Matrix of Components" of
- the Microsoft C version 5.10 MTDYNA.DOC file.
-
- Matrix of Components
- --------------------
-
- Table 1 lists the various components needed to create multiple-thread
- programs and the two types of dynamic-link libraries discussed above.
- For comparison, a single-thread executable file is also included in
- the table. (A single-thread executable file is simply a regular C
- program.)
-
- The components have the following meanings:
-
- .OBJ Object files
-
- .LIB Library files
-
- .h Location (default) of include files
-
- DLL Status of DLL symbol (either defined or not defined)
-
- xLIBCyP.LIB Regular C run-time library for protected mode
- x = memory model (S, C, M, L)
- y = math package (A, E, 7)
-
- Table 1. Output-File Type
-
- Executable Dynamic-Link Library
-
- Component Single Thread Multiple Thread Single Thread Multiple Threa
- --------- ------------- --------------- ------------- --------------
-
- .OBJ ... ... ... CRTDLL.OBJ
- CRTEXE.OBJ
- CRTLIB.OBJ
-
- .LIB xCLIBCyP.LIB LLIBCMT.LIB LLIBCDLL.LIB CDLLOBJS.LIB
- DOSCALLS.LIB DOSCALLS.LIB CDLLOBJS.DEF
- CDLLSUPP.LIB
- DOSCALLS.LIB
-
- .h \INCLUDE \INCLUDE\MT \INCLUDE \INCLUDE\MT
-
- DLL Not defined Not defined Not defined Defined
-
-
- 41. Appending to CTRL+Z Terminated File with Fopen()
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 23-SEP-1988 ArticleIdent: Q29852
-
- When appending to a stream file that is terminated with the
- end-of-file marker CTRL+Z (CONTROL+Z or the ASCII code 1A
- hexadecimal), use the "a+" type with the fopen() function. The "+" in
- the type "a+" allows for both writing and reading.
-
- If you use the "a" type with fopen() for appending in write-only mode,
- the end-of-file marker will not be removed. Subsequently using the DOS
- type command on the file will only display data up to the original
- end-of-file marker, and will not display appended data.
-
- The fopen() type "a+" will allow the removal of the end-of-file marker
- from the file before appending, so that the appended data can then be
- displayed by the DOS type command.
-
- The "a+" is required because DOS must be permitted to read the file to
- locate the end-of-file marker and overwrite it with appended data.
- Using the "a" type prohibits DOS from reading the file, so DOS is
- unable to find the end-of-file marker for overwriting and instead the
- appended data is written after the end-of-file marker.
-
-
- 42. C 5.10 UTILITY.DOC: Microsoft Pascal Programs
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr s_codeview
- Last Modified: 16-JAN-1991 ArticleIdent: Q29903
-
- The following information is from the section titled "Microsoft(R)
- CodeView(R) Debugger" of the Microsoft C Version 5.10 UTILITY.DOC
- file.
-
- Microsoft Pascal Programs
-
- In this release, Microsoft Pascal programs cannot be debugged with
- the CodeView debugger.
-
- The Pascal example on pg. 61 of the Microsoft CodeView and
- Utilities manual should read
-
- PAS1 /Zz TEST;
-
- rather than
-
- PAS1 /Zi TEST;
-
-
- 43. Wild-Card Expansion
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q29925
-
- Problem:
-
- I am attempting to insert the _setargv module into my standard C
- library to expand wild-card command line arguments as documented on
- Page 130 of the "Microsoft C 5.10 Optimizing Compiler User's Guide."
-
- When I invoke the LIB utility to remove the old _setargv module
- from the C library, I get the warning message "setargv.obj: warning
- U4151: '__setargv': symbol defined in module stdargv, redefinition
- ignored."
-
- My program is supposed to expand *.dat and print the names of all .dat
- files in the current directory. When I link my compiled code to the
- modified C library, I do not receive any errors. However, when I run
- my program, it prints out *.dat instead of expanding the wild card.
-
- Response:
-
- This is an error in documentation. The name of the module that you
- should extract from the C run-time library is stdargv. To replace this
- module with the module for expanding wild cards, use the LIB utility
- and enter the following module names after the Operations: prompt:
-
- Operations: -stdargv+setargv
-
- After performing this operation with LIB, linking the modified C
- library to your code will now permit the expansion of wild-card
- arguments by means of the argv[] array that is one of the main()
- function arguments.
-
- Note that you may link the object file setargv.obj with your code and
- an unmodified C run-time library to allow the expansion of wild cards.
- The replacement of module stdargv with setargv.obj allows wild-card
- expansion without explicitly linking in "setargv.obj" each time.
-
- C Version 4.00 and its documentation about the wild-card expansion
- library module had a similar problem.
-
- If you are using C Version 4.00, search for wild card and setargv for
- more information.
-
-
- 44. Reading F11 and F12 Keys on Extended Keyboard
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 11-AUG-1989 ArticleIdent: Q30370
-
- The following program will allow you to read the F11 and F12 keys
- on an extended keyboard. The key to this process is to call
- _bios_keybrd() with the service argument 0x10. This will allow an
- extended keyboard read. This program will sit in an infinite loop
- until F11 or F12 is pressed. Note that the C run-time library
- functions getch() or getche() will not be able to read in the extended
- function keys even after the change above has been made.
-
- #include <bios.h>
- #include <stdio.h>
- #define _EXTKEYREAD 0x10
- #define MASK 0xFF00
- #define ZMASK 0x00FF
- main()
- {
- unsigned value, nextval;
- while(1)
- {
- value = _bios_keybrd(_EXTKEYREAD);
- nextval = value;
- if ((value & ZMASK) == 0) /* check low order byte for zero*/
- /* if zero, then we have extended key*/
- {
-
- if((nextval & MASK) == 0x8500) /* buffer code = 8500h for F11 */
- printf("F11 key pushed\n");
-
- if((nextval & MASK) == 0x8600) /* buffer code = 8600 for F12 */
- printf("F12 key pushed\n");
- }
- else
- printf("not an extended key\n");
-
- }
- }
-
-
-
- 45. Trapping FP Execptions with In-Line 8087 Code
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 27-OCT-1988 ArticleIdent: Q30644
-
- Problem:
-
- I am following the instructions on Pages 167-68 of the "Microsoft C
- Optimizing Compiler User's Guide" to generate true in-line 8087 code.
- I can link a module to remove the fixups for the interrupts, but I can
- no longer handle floating-point exceptions using the signal function.
-
- Response:
-
- This is a documentation error. To trap floating-point exceptions with
- the signal function while having true in-line 8087 code, you need to
- add the following instructions to your FIXUP.ASM module:
-
- extrn __fpmath:far
- extrn __fptaskdata:far
- extrn __fpsignal:far
-
- CDATA segment word common 'DATA'
- dw 0
- dd __fpmath
- dd __fptaskdata
- dd __fpsignal
- CDATA ends
-
- Without the previous code, the start-up code will not initialize
- the emulator and the signal function returns an error when you attempt
- to use signal to trap floating-point exceptions.
-
-
- 46. Cannot Create .COM Files in C Compiler
-
- Product Version(s): 3.00 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-JUN-1988 ArticleIdent: Q30646
-
- The Microsoft C Compiler Versions 3.00, 4.00, 5.00, and 5.10 do not
- support the creation of .COM programs. This is because the smallest
- memory model that can be created is Small Model, which has one Code
- segment and one Data segment, while .COM programs can only have one
- segment.
-
- .EXE files are converted to .COM files using the MS-DOS utility
- EXE2BIN (see your MS-DOS manual and/or Page 51 of Ray Duncan's
- "Advanced MS-DOS"). The .COM programs cannot contain more than one
- declared segment; however, the Microsoft C compiler creates segments
- named _DATA, _TEXT, CONST, _BSS, etc.
- There are no compiler options to create a "Tiny model" program.
- For this reason, most .COM programs are written in assembler.
- One way to use the C Compiler in creating .COM programs is to
- compile with the /Fa option to create an assembly listing. The .ASM
- file(s) can then be modified so it only uses one segment.
-
-
-
- 47. Initialization of auto Arrays, Structs, Unions Not Allowed
-
- Product Version(s): 4.00 5.00 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-AUG-1989 ArticleIdent: Q34668
-
- Problem:
-
- Both the ANSI draft standard for C (May 1988) and "The C Programming
- Language," Second Edition (by Kernighan and Ritchie) show that
- initializing aggregate data items declared with auto storage class is
- allowed in Standard C; however, our compiler flags fatal errors when
- such attempts are made.
-
- The error message C2073 cannot initialize array if function is issued
- when attempting to compile an array initilization within a function
- such as the following:
-
- foo() {
- char array[]="intialized local array will cause an error";
- }
-
- Response:
-
- This restriction is stated in the "Microsoft C 5.1 Optimizing Compiler
- Language Reference" on Page 89.
-
- One possible workaround is to use the static storage class rather than
- auto (auto is the default for declarations inside a function). This
- process has the advantage of making only one copy of the array and
- initializing it only ONCE, conceptually at the start of program
- execution; however, this can be a problem for recursive functions that
- may need a separate copy of the array for each invocation of the
- function.
-
- Another workaround is to declare two arrays: one static and one auto.
- Initialize the static array and copy it into the auto array (e.g.
- using the fast memcpy function) at the beginning of the function. Note
- that there is no speed or space penalty for this process because the
- second workaround is basically what the compiler would have to do if
- it allowed initialization of auto arrays.
-
- The first workaround will give a savings of both time and space over
- both the second workaround and over initializing an auto aggregate.
-
-
- 48. chdir() Example Is Incorrect
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q30959
-
- The example of the chdir() function on Page 156 of the "Microsoft C
- Run-Time Library Reference" manual is incorrect. This example is
- missing double quotation marks around the path. It should read as
- follows:
-
- chdir("c:\\temp") ;
-
-
- 49. Array Index Multiplication with Integers Causes Link Error
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | TAR77788
- Last Modified: 16-JUN-1988 ArticleIdent: Q31448
-
- When the following program is compiled and linked, the linker
- generates the error "L2029 -unresolved external for the variable
- _arr." However, the array appears to be declared legally. The
- following code generates the error:
-
- char huge arr[256*512];
- main(){}
-
- The problem occurs because the multiplication for the array index is
- done with integers and the result of the multiplication is too large
- to fit in an integer. This will result in the array index being 0
- (zero). Because of this array, the following declaration
-
- char huge arr[256*512];
-
- is equivalent to the following declaration:
-
- char huge arr[0];
-
- The second declaration in turn, is equivalent to the following
- declaration:
-
- char huge arr[];
-
- This type of declaration will cause the compiler to generate an
- explicit external reference for the array arr and force the linker to
- look for the variable arr.
- To solve this problem, do the multiplication for the array index
- with long integers by declaring one or both of the integer constants
- as long. The following is a code example:
-
- char huge arr[256L*512];
-
-
-
- 50. README.DOC Refers to Undocumented "Link Options"
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 24-AUG-1988 ArticleIdent: Q31454
-
- The following statement appears in the note for Page 130 ("Part 2:
- Notes for the Microsoft C Optimizing Compiler User's Guide") of the
- README.DOC file on the C Version 5.10 Setup disk:
-
- See the description of the /NOE option under the heading "Linker
- Options" later in this document.
-
- However, there is no such heading, nor is there any linker option
- information in the UTILITY.DOC file.
- The CodeView and Utilities manual contains an inserted manual
- section labelled "Update (CV. and Util.)". In this document, the /NOE
- option and the /NON option are described in Section 4, "Using the OS/2
- Linker", subsection 4.3, "New Options for Both Modes", Page Update-28.
-
-
- 51. PATCH87 Gives "Cannot Open IO.SYS" Message
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-JUN-1988 ArticleIdent: Q31468
-
- If the instructions in the PATCH87.DOC file for using PATCH87.EXE
- are followed through Step 4 of the "Do I Need to Use This Program?"
- section, and the diagnostic test results in a "Cannot open IO.SYS"
- message, then you must contact the original equipment manufacturer
- (OEM) for more information. It is likely that the IO.SYS file has been
- renamed in the provided version of DOS.
-
-
- 52. Bitwise Complement Operator Appears to Fail on Comparison
-
- Product Version(s): 4.00 5.10 5.00
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-JUN-1988 ArticleIdent: Q31510
-
- The bitwise complement operator (~) may appear to work incorrectly
- when used to compare unsigned characters, as illustrated in the
- following example.
- However, when using the bitwise complement operator, it is
- important to note that it will perform the "usual arithmetic
- conversions" on operands. The usual arithmetic conversions are
- described in detail in Section 5.3.1 of "The Microsoft C Language
- Reference Guide."
-
- The following program prints out as "failed" even though it
- appears that the two items should compare as "equal":
-
- #include <stdio.h>
- main()
- {
- unsigned char i,j;
- unsigned char k = 4;
- i = k;
- j = ~i;
-
- if (j == ~i)
- printf("passed\n");
- else
- printf("failed\n");
-
- }
-
- The compiler takes the steps below to evaluate the following
- statement:
-
- if (j == ~i)
-
- 1. The compiler converts the operand "i" to an unsigned integer (in
- the C manual, see step 5 of the usual arithmetic conversions).
- 2. The compiler complements the bits of this unsigned integer (the
- high byte becomes 0xFF).
- 3. The compiler converts the operand "j" to an unsigned integer
- (the high byte becomes 0x00).
- 4. The compiler compares the two operands.
-
- Since the high bytes of the two operands differ, the comparison
- will fail.
- To ensure that the compiler will compare only the low bytes of the
- two operands, cast the operand that is being complemented. For
- example, you can change the comparison to the following:
-
- if (j == ~(unsigned char)i)
-
-
- 53. Linking FORTRAN and C, "L2044 _FF_MsgBanner Multiply Defined"
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | h_fortran 4.00 4.01
- Last Modified: 16-JUN-1988 ArticleIdent: Q31563
-
- Problem:
- When linking FORTRAN and C modules, I receive the error "L2044
- _FF_MsgBanner Symbol Multiply Defined." I have set up FORTRAN for C
- compatibility, and I am linking with the /NOE switch.
-
- Response:
- When using FORTRAN Versions 4.00 or 4.01 with C, you need to run
- the F4COMPAT file to make your FORTRAN libraries C compatible because
- FORTRAN Versions 4.00 and 4.01 were written in C Version 4.00.
- If the /NOD switch is used, altering the order of the libraries may
- change the error message received. When the FORTRAN library is first,
- the error may be "Floating Point Not Loaded." When the C library is
- first, the error will be "Symbol Multiply Defined."
-
-
- 54. RunTmLibRef ftime Returns millitm to 100ths
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q31611
-
- The ftime function is described in a misleading way in the
- "Microsoft C 5.1 Optimizing Compiler Run-Time Library Reference" ,
- Page 308 for C Version 5.x and Page 217 for C Version 4.00.
- The field millitm in the timeb structure that ftime returns is
- described to hold the value of the fraction of a second in
- milliseconds. The field contains three digits as described;
- however, the last digit always is zero. Thus, the function returns
- millitm incremented to the nearest one hundredth of a second.
- Note also that this function uses the system clock to determine
- the time. Since the resolution of the clock on PC's is about 1/18.2
- seconds, the time function can not be more accurate than that.
-
-
- 55. _beginthread()/_endthread() Coding Multi-Threaded Applications
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 8-JUL-1988 ArticleIdent: Q32057
-
- Question:
- What do _beginthread() and _endthread() do? Do we need to use
- these routines rather than the OS/2 API calls DosCreateThread() and
- DosExit()? Does _beginthread() affect the stack it is passed?
-
- Response:
- _beginthread() and _endthread() are discussed in MTDYNA.DOC.
- _beginthread() should be used in place of DosCreateThread() when
- coding multi-threaded applications in C Version 5.10. _endthread()
- should be used rather than DosExit() to terminate a thread before it
- runs to completion.
- _beginthread() takes care of important thread-creation tasks,
- such as the following:
-
- 1. Initializing the per-thread floating-point package
- 2. Saving/restoring the DGROUP environment
- 3. Ensuring that there are not too many threads being created
- 4. Verifying the validity of the stack generated
-
- The stack you pass to _beginthread() must meet the following
- requirements:
-
- 1. It must not have null segment.
- 2. It must not start at an odd address.
- 3. It must not have 0 length.
- 4. It must not have an odd length.
- 5. It must not extend past the end of the segment.
-
- Because of the importance of these tasks, it is important to use
- _beginthread()/_endthread() instead of DosCreateThread()/ DosExit()
- when coding multi-threaded applications in C Version 5.10. Although
- you may be able to use DosCreateThread(), consistent results are not
- guaranteed.
-
-
- 56. Compiler C2061 Syntax Error: Identifier 'dev_t' in stat.h
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1990 ArticleIdent: Q32068
-
- When compiling a file that includes stat.h or stat.h followed by an
- include of types.h, the following error is generated:
-
- C2061 syntax error: identifier 'dev_t'
-
- The error occurs because dev_t is defined in types.h and is not
- defined in stat.h.
-
- When using the include file stat.h, you must also include the file
- types.h. Specifically, the file types.h must be included before the
- file stat.h. For example:
-
- #include <sys\types.h>
- #include <sys\stat.h>
-
- The order in which these files are included must occur as shown to
- eliminate the compiler error message.
-
-
- 57. No Error Message Text
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 26-SEP-1988 ArticleIdent: Q32069
-
- You can receive compiler errors with numbers but without text when
- compiling if the error message's file is not present.
-
- To see the error-message text, the files C1.ERR and C23.ERR must be in
- your path. Generally, these two files are placed in the same directory
- as the compiler driver and compiler passes, CL.EXE, C1.EXE, C2.EXE, and
- C3.EXE.
-
-
- 58. D1001 "Could Not Execute C2.EXE" with DOS Version 2.10
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 23-SEP-1988 ArticleIdent: Q32070
-
- The compiler can generate the error D1001, "could not execute C2.EXE,"
- under the following conditions:
-
- 1. The .EXE file cannot be found. A terminate-and-stay-resident
- (TSR) program could alter the setting of the PATH environment
- variable, causing the .EXE to not be found.
-
- 2. There is not enough memory.
-
- 3. The .EXE file is corrupt, or has an illegal .EXE file format.
-
- 4. DOS and COMMAND.COM are incompatible. If their version numbers
- are different, the compiler might not be able to open the
- intermediate file in the TMP directory.
-
-
- 59. Two Syntaxes for Calling Functions with Pointers
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 26-SEP-1988 ArticleIdent: Q32109
-
- The source code below contains what appears to be an improper use of a
- pointer to a function. However, the compiler fails to flag this either
- as a warning or as an error, and the code seems to work as expected.
-
- The behavior exhibited in the sample code is expected. The proposed
- ANSI Standard (Document Number X3J11/88-002, January 11, 1988) allows
- a function to be called through a pointer with the following syntax
-
- pointer_to_function();
-
- in addition to the following traditional syntax:
-
- (*pointer_to_function)();
-
- The following is a quotation from Page 40 of "Rationale for Draft
- Proposed American National Standard for Information Systems
- Programming Language C":
-
- "The...construct, not sanctioned in the Base Document, appears in some
- present versions of C, is unambiguous, invalidates no old code, and
- can be an important shorthand."
-
- The following sample code demonstrates this problem:
-
- #include <stdio.h>
- void main()
- {
- void ftn();
- void (*ptr_to_ftn)();
- ptr_to_ftn = ftn; /* the pointer is correctly assigned to
- an address */
- printf("\nCalling all ftns\n\n");
- (ptr_to_ftn)(); /* note that the function is improperly called.
- the correct syntax is (*ptr_to_ftn)() */
- printf("back to main\n");
- }
- void ftn()
- {
- printf("inside ftnland\n\n");
- }
-
-
- 60. EXEC Problem with the Novell Network
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q32285
-
- When compiling a program under a Novell network, the following
- problems can occur:
-
- 1. A command-line error message.
- 2. A stack overflow.
- 3. The compiler hangs.
- 4. Programs created with C Version 4.00 and Link Version 3.51
- could generate Error 2003 : integer divide by zero.
-
- This is not a problem with the Microsoft C Compiler, nor is it an
- error on your part. A problem exists in the way Novell networking
- software handles the EXEC function, one of the DOS interrupt 21h
- functions used by the CL and MSC programs to start each of the
- compiler passes.
-
- Contact your Novell dealer about this problem; there should be a patch
- available. Novell has stated this problem has been corrected in
- Version 2.10 and later.
-
- Novell's network emulates DOS; the problem arises from incorrect
- emulation of the DOS int 21H function 4BH (EXEC program) call. The
- Novell network assumes the calling program will save SS:SP before the
- call. This was necessary on DOS Versions 2.x, but it is not necessary
- to save the registers on DOS Versions 3.x.
-
- The C compiler checks to see what version of DOS it is running on; if
- you are running DOS Versions 2.x, save SS:SP; if you are running DOS
- Versions 3.x (which is what Novell presents itself as) do not save
- SS:SP. The network destroys those registers on the call even though
- this behavior is unlike DOS Versions 3.x.
-
-
- 61. Assert Macro Anomaly; Generating Syntax Errors
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 5-JUL-1988 ArticleIdent: Q32303
-
- The following code demonstrates an anomaly with the C Version 5.10
- compiler when compiled with the default options. Compile-time syntax
- warnings are generated when there are no apparent syntax errors.
-
- #include <stdio.h>
- #include <assert.h>
- main()
- {
- if(1)
- assert(1+1);
- else
- assert(1+2);
- }
-
- Response:
- The syntax errors are generated because assert() is implemented as
- a macro and is expanded to the following form:
-
- if (!(1+1)) { \
- fprintf(stderr, _assertstring, #1+1, __FILE__, __LINE__); \
- fflush(stderr); \
- abort(); \
- } \
- }
-
- When this macro is placed inside an if else conditional, the
- closing brace of the macro is seen as a syntax error.
- Although the syntax for the if else conditional in the above
- example is legal, it does not make much sense for use with assert
- because assert will call the abort function if it is true. Therefore,
- you can accomplish the same results with the following program:
-
- #include <stdio.h>
- #include <assert.h>
- main()
- {
- if(1)
- assert(1+1);
- assert(1+2);
- }
-
- Microsoft is researching this problem and will post new information
- as it becomes available.
-
-
- 62. L1063 Error Not Documented in C Versions 5.00 or 5.10
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 18-AUG-1988 ArticleIdent: Q32311
-
- The link error message, "L1063 out of memory for CodeView
- information," is not documented in the manuals or in the README.DOCs
- for C Versions 5.00 and 5.10. However, it is documented in the FORTRAN
- Version 4.10 package in the CVREADME.DOC on the disk labeled
- "Microsoft CodeView for MS-DOS".
- The following information was taken from the FORTRAN Version 4.10
- CVREADME.DOC, "NOTES ON CODEVIEW AND UTILITIES," the section titled
- "Microsoft Segmented-Executable Linker (LINK)," the subsection "New
- LINK Error Messages":
-
- L1063 out of memory for CodeView information
-
- The linker was given too many object files with debug information,
- and the linker ran out of space to store it. Reduce the number of
- object files that have debug information.
-
-
- 63. C 5.00 and 5.10 putenv() Example Program Missing Backslashes
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 15-JAN-1991 ArticleIdent: Q32324
-
- The example program for the putenv() function on page 468 of the
- "Microsoft C 5.10 Optimizing Compiler Run-Time Library Reference" is
- incorrect. The C code requires double backslashes in order to work
- correctly.
-
- This is the incorrect line:
-
- if (putenv("PATH=a\bin;b:\tmp") == 1)
-
- The corrected line (with escaped backslashes) should read as follows:
-
- if (putenv("PATH=a:\\bin;b:\\tmp") == 1)
-
-
- 64. Incorrect Comment Pragma Example
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 15-JAN-1990 ArticleIdent: Q32348
-
- Page 12 (Update-12) of the Update section for the "Microsoft C
- Optimizing Compiler User's Guide and Language Reference" manual shows
- an incorrect example of the comment pragma.
-
- The second parameter of the pragma is a string literal and should be
- enclosed in double quotation marks. The example should look like the
- following:
-
- #pragma comment(lib, "mylibry")
-
- Note: If the quotation marks are missing, the compiler will issue
- error C4079.
-
-
- 65. _Heapchk() Performs Consistency Check on Heap
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-JUL-1988 ArticleIdent: Q32442
-
- The _heapchk() routine performs a consistency check on the heap by
- examining the header information of the memory blocks in the heap.
- However, it cannot detect corruption of data within the heap's nodes;
- it only can detect corruption of the heap's header information.
- The _heapchk() routine checks for the following:
-
- 1. It checks to see if any heap has been allocated at all. If not,
- _heapchk() returns _HEAPEMPTY.
- 2. It checks the beginning of the heap block to see if the first
- allocation block has been corrupted; if so, it returns _HEAPBADBEGIN.
- (Note that only the header information is checked.)
- 3. It scans through the far heap block, moving from node to node.
- For each node, it checks the header information to make sure it has
- not been corrupted; if so, _heapchk() returns _HEAPBADNODE.
- Note that the only kind of corruption _heapchk() can detect is an
- out-of-bounds value in the header; it cannot detect corrupted data
- within the heap block itself. If the fill value passed is not
- _HEAPSET_NOFILL, and the block is unallocated, _heapchk() fills
- memory with the fill value.
- 4. If _heapchk() made it all the way through the heap (i.e., it checked
- the headers for all nodes), it returns _HEAPOK.
-
-
-
- 66. How Bitfields Are Stored in Memory
-
- Product Version(s): 1.04 2.03 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 19-JUL-1988 ArticleIdent: Q32841
-
- The Microsoft C compiler stores bitfields from low memory to high
- memory. For example, if you have the following declaration:
-
- struct {
- unsigned field_one:3;
- unsigned field_two:9;
- unsigned field_three:5;
- };
-
- then "field_one" will be stored in bits 0-2 in the first word,
- "field_two" will be stored in bits 3-11 in the same word, and
- "field_three" will be stored in bits 0-4 of the second word (because
- it cannot fit in the 4 bits remaining in the current word).
-
-
-
- 67. Specifying .DEF Files on the CL Command Line
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 8-JUL-1988 ArticleIdent: Q32448
-
- You can use .DEF files when compiling and linking, using CL
- command-lines.
- List the .DEF files with the other files (.C, .OBJ, and .LIB). CL
- will compile and link them appropriately. Note that if you do not
- specify an extension, CL assumes the file is an .OBJ file and it will
- try to link it.
- The following command will build a protected-mode program called
- MYAPP.EXE by compiling myapp.c, then linking MYAPP.OBJ and MYSUB.OBJ
- with the library MYLIB.LIB, and use the MYDEF.DEF.definitions file:
-
- cl /Lp myapp.c mysub mylib.lib mydef.def
-
-
-
- 68. ANSI Constants Not in Stdio.h
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 8-JUL-1988 ArticleIdent: Q32513
-
- The ANSI C standard requires the constants FILENAME_MAX and
- FOPEN_MAX in STDIO.H and the constants EXIT_SUCCESS and EXIT_FAILURE
- in STDLIB.H.
- The include files provided with Version 5.10 of the C compiler do not
- have these constants. These constants should be defined as follows:
-
- /* in stdio.h */
-
- #define FILENAME_MAX 63
- #define FOPEN_MAX 20
-
- /* in stdlib.h */
-
- #define EXIT_SUCCESS 0
- #define EXIT_FAILURE 1
-
-
-
- 69. fclose() on Unopened Files Causes Protection Violation
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 11-AUG-1988 ArticleIdent: Q32539
-
- If you close an unopened file with the fclose() function, a
- protection violation occurs if the source is compiled in the large- or
- compact-memory model. In the small-memory model, fclose() returns an
- error as expected.
- Closing an unopened file is a user error and it is outside the
- functional realm of the C run time to check the validity of file
- handles passed to the fclose function. It is the responsibility of the
- user to ensure that only valid file handles are passed to the fclose
- function.
-
- The sample code below demonstrates this behavior. Compile this code
- with the CL /AL file.c. command line:
-
- #define INCL_BASE
- #include <os2.h>
- #include <stdio.h>
- FILE *myfile;
- int status;
-
- main()
- {
- myfile = fopen("myfile.dat","r");
- if (myfile == NULL) printf("file open error\n");
- status = fclose(myfile);
- printf("file close status = %d\n",status);
- }
-
-
- 70. Reference to Section 2.11 Should Be 2.12 in User's Guide
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 18-AUG-1988 ArticleIdent: Q32805
-
- Page 145 of the "Microsoft C 5.0 (and 5.1) Optimizing Compiler User's
- Guide" has an error in the last sentence. The reference to Section
- 2.11 is incorrect; it should read as follows:
-
- "For more information on library routines and memory models, see
- Section 2.12, `Using Huge Arrays with Library Functions,' in the
- Microsoft C Run-Time Library Reference."
-
-
-
- 71. The fopen Function Fails to Open Printer in Bound Application
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-JAN-1990 ArticleIdent: Q32813
-
- Attempting to use the C run-time function fopen() to open the printer
- will fail in real mode if the application calling the function is
- bound. The "invalid argument" error is returned.
-
- This problem is caused by the Family API DosOpen function. It will
- fail to open the printer when called with a flag that specifies
- "truncate if the file exists," which is the flag used by fopen().
-
- The following program demonstrates a work around for this problem
- using the C run-time library functions open() and fdopen():
- The program below uses open() to get a file handle for the printer.
- Note that the oflag used is O_WRONLY. ORing in O_TRUNC would fail in
- real mode. The device name "lpt1" or "lpt2" could be used instead of
- "prn", depending on how the computer is set up. The generic name for
- the printer is "prn".
-
- Then the fdopen() function is used to create a stream for the printer,
- and the printer is written to by the fprintf() function.
-
- The following is the sample program:
-
- #include <fcntl.h> /* include files for open() */
- #include <sys\types.h>
- #include <sys\stat.h>
- #include <io.h>
- #include <stdio.h> /* include file for printf() and
- fdopen() */
-
- int fh; /* file handle for printer */
- FILE *stream; /* stream for printer */
-
- main() {
- /* open file handle for printer, check for open failure */
- if ((fh = open("prn",O_WRONLY)) == -1 )
- printf("Opening file handle failed.\n");
-
- /* associate stream for fh above, check for failure */
- else {
- if((stream = fdopen(fh,"w")) == NULL)
- printf("Creation of stream from file handle
- failed.\n");
-
- /* if previous function calls succeeded, print "Hello" */
- else
- fprintf(stream,"Hello\n");
- }
- }
-
-
- 72. The Cause of Run-Time Error R6000 Stack Overflow
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q32816
-
- The run-time error R6000 Stack Overflow can be caused by two
- different problems, as follows:
-
- 1. Your program's stack is not large enough to hold all the data
- being pushed on it during execution of your program, so it
- overflowed. This problem can be caused by heavily recursive
- programs and programs that declare large amounts of data on
- the stack ("local" or "automatic" data in C jargon).
-
- In this case, you need a larger stack or less recursion and/or less
- local data.
-
- 2. The second cause for the R6000 error is somewhat counter
- intuitive; it can be caused by the C startup (initialization)
- code when it tries to allocate space for the stack and is unable
- to do so.
-
- In this case, you need to reduce the size of your stack or reduce
- the amount of data in DGROUP.
-
- The following is a description of both problems, ways to solve the
- problem, and a method for determining which problem you are
- encountering:
-
- Case 1: R6000 Occurs at Run Time
-
- The stack overflowed because too much information was pushed on it.
- This information could be either function-return addresses or local
- data. Each time a function is called, the return address in the
- calling function is pushed on the stack along with any parameters;
- then, when the called function executes, it may allocate local
- ("automatic") data for its own use. This process requires stack space.
-
- To correct this problem, do one of the following:
-
- 1. Decrease the number of local variables, perhaps by declaring
- those variables as static so they will not be pushed on the
- stack.
-
- 2. Increase the stack size by compiling with the /F x option, where
- x is a hexadecimal number representing the number of bytes
- desired in the stack size (see Page 102 of the "Microsoft C 5.1
- Optimizing Compiler User's Guide").
-
- 3. Change the stack size by linking with the /STACK switch, or using
- the EXEMOD utility. Note that increasing the stack size too much
- can cause an R6000 as described in case 2.
-
- Case 2: R6000 Occurs at Startup
-
- The startup code allocates space for the stack in the segment DGROUP.
- If DGROUP does not contain room for the specified stack size (default
- = 2K), the startup code issues the R6000 error.
-
- To correct this problem, either reduce the size of the stack or reduce
- the amount of data in DGROUP. To reduce the stack size, compile with
- the /F option, or link with the /STACK option, or use the EXEMOD
- utility. To reduce the amount of data in DGROUP, try switching from a
- small-data model (Small- or Medium-memory model) to a large-data model
- (Compact-, Large-, or Huge-memory model). If you already are in a
- large-data model, compile with the /Gt switch to move data from DGROUP
- to far data segments.
-
- To use the /Gt switch, specify /Gtx, where x is some decimal value
- representing a number of bytes. Data items larger than x bytes are
- allocated a new segment, thereby freeing up more space in DGROUP for
- the stack. For more information, see Page 156 of the "Microsoft C 5.1
- Optimizing Compiler User's Guide."
-
- How to Determine What is Causing the R6000 Error
-
- An excellent way to determine the cause of the problem is to use the
- CodeView debugger. After invoking CodeView on your program, execute to
- the beginning of function main() by doing one of the following:
-
- 1. Single-Step with F8 or T.
- 2. Enter "g main" at the CodeView prompt.
-
- When you've executed past the open curly-brace of main(), the C
- startup code has done its job by allocating space for stack and data.
- If the R6000 error does not occur at this time, you are experiencing
- Case 1, a run-time stack overflow (as opposed to Case 2, a
- startup-time stack overflow); you now can take appropriate action as
- described above.
-
-
- 73. Command Line Error D2018
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 19-JUL-1988 ArticleIdent: Q32843
-
- If you receive the D2018: "cannot open linker cmd file" error,
- check to see that the TMP environment variable is set correctly. If
- the TMP variable is not set properly, temporary files cannot be
- created and this error may occur.
-
-
-
- 74. Write Function Will Not Work Correctly with SS!=DS
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 19-JUL-1988 ArticleIdent: Q32871
-
- Problem:
- I have a program that needs to be run in an SS!=DS environment and
- I am trying to use the write function; however, it does not seem to be
- working.
-
- Response:
- The write function will not work correctly in SS!= DS in text
- mode. It should work properly in binary mode. In text mode, write()
- builds a buffer on the stack to do LF to CR/LF translation. It makes a
- call to stackavail() to make sure it does not overflow the stack; this
- call is what prevents it from working with SS!=DS.
- This is program design for this product.
-
-
- 75. Toggling the Sign Bit on a Float or Double
-
- Product Version(s): 3.00 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 20-JUL-1988 ArticleIdent: Q32889
-
- Problem:
- I want to toggle the sign bit on a float or double by either
- and'ing it with 0x7fff (make it positive) or or'ing it with 0x8000
- (make it negative). However, the compiler will not accept the
- following syntax:
-
- fl &= 0x7fff;
- fl |= 0x8000;
-
- Response:
- The bitwise operators only works correctly with integral types; you
- need to cast the float to be an integral type.
- The following are two macros that will allow you to toggle the sign
- bit on a float or a double (note that the same thing can be
- accomplished by multiplying the value by -1, but the macros are much
- faster because they do not make any calls to the floating-point
- library):
-
- /* Macro to make either a float or a double Negative by setting sign bit */
- #define NEG(arg) ((unsigned char *)&arg)[sizeof(arg)-1] |= \
- (unsigned char)0x8000
-
- /* Macro to make either a float or a double Positive by clearing sign bit */
- #define POS(arg) ((unsigned char *)&arg)[sizeof(arg)-1] &= \
- (unsigned char)0x7fff
-
-
-
- 76. extern int i = 10; Compiles without Error
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 19-JUL-1988 ArticleIdent: Q32890
-
- Page 89 of "Microsoft C Optimizing Compiler Language Reference"
- states the following:
-
- "Declarations that use the extern storage-class specifier cannot
- include initializers."
-
- However, the following example compiles without error:
-
- extern int i = 10;
-
- The documentation is incorrect. The ANSI standard makes no
- distinction between the following declarations when they have file
- scope (i.e., they are declared globally):
-
- int i = 10;
- extern int i = 10;
-
- Therefore, the compiler does not generate a warning or error for
- either of these cases.
-
-
-
- 77. __fac Unresolved at Link Time
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 19-JUL-1988 ArticleIdent: Q32891
-
- Problem:
- I am attempting to write a function to be used in a dynamic link
- library. The function returns a double. Whenever I compile and link
- with either of the multithread C run-time libraries (LLIBCMT.LIB
- or CRTLIB.LIB), I get the variable __fac unresolved.
-
- Response:
- In a single thread environment, the C run-time uses a global variable
- __fac to store the return value of a function that returns double. In
- a multithread reentrant environment, it is not possible to have a global
- variable that will potentially be modified by several threads.
- If you are writing functions that return doubles and you are using
- the multithread libraries, you need to declare the functions with the
- Pascal calling convention. Functions returning double with the Pascal
- calling convention pass the return value on the stack and allow you to
- work in a reentrant environment.
-
-
-
- 78. Compiling with /Zi Causes Code Motion Optimization Suppression
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 19-JUL-1988 ArticleIdent: Q32892
-
- Compiling with /Zi and no other switches causes certain code motion
- optimizations to be suppressed, i.e, the code generated for a program
- with the defaults and with /Zi may differ.
- You can override this default behavior by explicitly specifying the
- default optimizations on the command line. For example, you can
- compile with the following command line to get the same code with or
- without /Zi:
-
- cl /Zi /Ot file.c
-
-
-
- 79. Difference between Huge Pointers
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 19-JUL-1988 ArticleIdent: Q32893
-
- Problem:
- I have two huge pointers that are more than 32K apart. However,
- whenever I take the difference between them, I get an incorrect
- answer. I am using the following code:
-
- char huge *ptr1 = (char huge *)0xa0000000;
- char huge *ptr2 = (char huge *)0xb0000000;
- main()
- {
- long k;
- k = ptr2-ptr1;
- printf("difference is %ld\n",k);
- }
-
- Response:
- This problem occurs because the difference between two pointers is
- considered to be an integer quantity. The arithmetic that is done on
- the huge pointers is 32-bit arithmetic, but the result is truncated to
- an integer, then promoted back to a long value with a sign extension.
- To retain the original long value returned by the huge-pointer
- arithmetic, cast the result of the subtraction to a long value. For
- example, you will get the expected results with the following code:
-
- char huge *ptr1 = (char huge *)0xa0000000;
- char huge *ptr2 = (char huge *)0xb0000000;
- main()
- {
- long k;
- k = (long)(ptr2-ptr1); /* cast the integer to a long */
- printf("difference is %lp\n",k);
- }
-
-
-
- 80. malloc May Truncate Request More Than 64K
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 19-JUL-1988 ArticleIdent: Q32998
-
- When trying to allocate memory with malloc() and calloc(), the
- request for memory will be truncated if it exceeds 64K.
- The maximum number of bytes that can be allocated by malloc is less
- than 64K because the allocation routines will consume a certain number
- of bytes to track memory allocation within the segment. The maximum
- number of bytes you can allocate using malloc or calloc is
- approximately 65516.
- Requests for more than 65516 bytes and less than 64K will result in
- malloc returning NULL. Requests for more than 64K will potentially
- return a pointer but it will be a pointer to a block of a size other than
- that requested because the parameter passed to malloc is an unsigned
- integer. This integer has a maximum value of 64K; passing a number greater
- than this value will result in undefined behavior. If malloc is passed a
- parameter greater than 64K, the compiler will issue a data-conversion
- warning, which should be heeded.
- If you require more than about 65516 bytes for a single allocation,
- you should use halloc().
-
- The following program demonstrates the behavior described above:
-
- #include <stdio.h>
- #include <malloc.h>
-
- int *intarray;
-
- main()
- {
- intarray= (int *)malloc(32768*sizeof(int));
- if (intarray == NULL)
- printf("not enough memory, no allocation");
- else
- printf("memory allocated");
-
- intarray= (int *)malloc(32767*sizeof(int));
- if (intarray == NULL)
- printf("not enough memory, no allocation");
- else
- printf("memory allocated");
-
- }
-
-
-
- 81. DOS Append Interacts with /Fo /Fe
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 20-JUL-1988 ArticleIdent: Q33085
-
- When the DOS Append path is set, if an .OBJ or .EXE file of the same
- name as the file being compiled does not exist in the current
- directory or in the directory specified with the /Fo or /Fe but does
- exist in a directory in the Append path, the new .OBJ and .EXE file
- will be placed in the directory in the Append path instead of in the
- current directory or the directories specified by the /Fo and /Fe
- switches.
- Append searches the data path for all files regardless of
- extension; placing .OBJ or .EXE in the directory specified in the
- append directory is expected behavior.
- If you need to locate files in a specific directory and you are
- using Append, you should put a copy of the .OBJ and .EXE in the
- directory you wish to use as your destination.
-
- The following is a sample code:
-
- append c:\test1,c:\test2
-
- If program.obj resides in directory test1 and program.exe
- resides in test2, the following command line switches will
- not work correctly:
-
- cl /Foc:\test3\program.obj /Fec:\test3\program.exe program.c
-
- Although the .OBJ and .EXE files should be placed in the test3
- directory, they will be placed into the test1 and test2 directories,
- respectively.
-
-
-
- 82. SH_COMPAT Share Flag for SOPEN()
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 2-AUG-1988 ArticleIdent: Q33104
-
- SH_COMPAT is not a valid share flag for SOPEN() under OS/2.
- SH_COMPAT is only valid in the DOS environment. The documentation in
- the "Microsoft C 5.1 Opitimizing Compiler Run-time Library Reference,"
- Page 548, does not document this restriction on the use of SH_COMPAT.
-
-
-
- 83. Small-Memory Model and Far Routines
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | 5.10
- Flags: ENDUSER |
- Last Modified: 27-JUL-1988 ArticleIdent: Q33364
-
- Question:
- Is it incorrect to call a routine with a far call in the small
- memory model?
- When I try to call a C routine with a far call (from assembler),
- the CS register never changes and items start to be executed from the
- current CS instead of the one my routine is at. Are there any rules
- that must be followed to make a far call in the small-memory model?
-
- Response:
- In order for this to work correctly you need to be sure that the
- function is declared and defined as a far function (e.g. int far foo()).
-
-
-
- 84. How _fheapwalk() Checks the Heap
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 27-JUL-1988 ArticleIdent: Q33366
-
- The following information describes how _fheapwalk() checks the
- heap.
-
- The _fheapwalk() function traverses those parts of the far heap
- that have been allocated either by fmalloc() or by a system call. This
- process is done by covering one such allocation per call of
- _fheapwalk(), independent of the size of the block allocated.
- On each call of _fheapwalk(), a manifest-constant int is returned
- as documented on Page 357 of the "Microsoft C 5.1 Optimizing Compiler
- Run-Time Reference Library" manual.
- Also, a pointer to a structure is returned that contains
- information about the block allocated, which also is documented on
- Page 356 of the C manual.
- One undocumented feature of the function is that it does not return
- the actual memory address of an _fmalloc()ed block, only the block's
- size.
- As a result, it is incorrect to assume that the memory location of
- the beginning of a block can be determined by adding up the values of
- the blocks already allocated. The header information in each such
- block is omitted from the structure whose pointer is returned by
- _fmalloc(). In particular, the size of the header is omitted from the
- structure.
-
-
-
- 85. Description of the /Or Switch
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 16-JAN-1990 ArticleIdent: Q48089
-
- Question:
-
- When I run CL with the /HELP option to get command-line help, there is
- listed an optimization flag, /Or, that is supposed to disable in-line
- returns. I can't find information about this switch documented
- anywhere else. What does this switch really do?
-
- Response:
-
- The term "in-line return" is misleading; there is not a call to the
- return function that is eliminated. The /Or switch affects the code
- that is produced for functions lacking local variables and/or formal
- parameters.
-
- If a function takes no formal parameters and has no local variables, a
- stack frame is not necessary. /Or prevents stack frame creation and
- clean-up code from being produced when possible. The code for
- preservation and restoration of the SI and DI registers is also
- eliminated.
-
- The typical instructions that are eliminated are as follows:
-
- push bp ; This code is used on entry
- mov bp, sp ; to establish a stack frame.
- ...
- push di ; This code is used on entry
- push si ; to preserve SI and DI.
- ...
- ... ; The code to perform the function
- ... ; would be here.
- ...
- pop si ; This code is used on exit to
- pop di ; restore SI and DI, and to
- mov sp, bp ; clean up the established
- pop bp ; stack frame.
-
-
- 86. Using 43-Line Mode with Hercules Card
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G880721-1772
- Last Modified: 27-JUL-1988 ArticleIdent: Q33403
-
- Currently, only 82x55 mode is supported for the Hercules card. It
- is possible to switch to 43-line mode if you first do a
- _setvideomode(_DEFAULTMODE), then immediately do a
- _setvideomode(_ERESCOLOR).
-
-
-
- 87. Deeply Nested Blocks Cause C4073 Warning
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 2-AUG-1988 ArticleIdent: Q33526
-
- The following program produces a C4073 warning when compiled with
- the CL /Zi filename.c command line:
-
- #include <assert.h>
- #include <process.h>
- #include <stdio.h>
-
- void main(ac,av)
- int ac;
- char **av;
- { assert(av[ac] == NULL);}
-
- The warning C4073 is generated when the compiler cannot generate
- symbolic information for separate lines of code that recognize the
- distinction between different blocks. For example, you may encounter
- this error if you have many deeply nested blocks, each of which declares
- automatic variables.
- The warning means that when in CodeView, the symbolic information
- at the deeper levels will be merged and you will be able to see the
- value of variables at lower levels when normally you would not.
- In this example, the warning is encountered because you are nesting
- three levels on the same line of code. The assert function actually
- is a macro that is expanded to two nested levels.
- You can work around the warning by moving the closing brace of the
- function to the next line.
-
-
-
- 88. Glockenspiel Turbo Pascal to C Translator Source Code
-
- Product Version(s): 3.00 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q33561
-
- The Irish company Glockenspiel writes the Turbo Pascal to C
- Translator. If you are interested in obtaining the source code, please
- contact Glockenspiel. The following is the company's address and phone
- number:
-
- 19 Belvedere Place
- Dublin 1
-
- 011-353-1-364515
-
-
- 89. Multiple Calls to ctime before Printing Results
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 8-AUG-1988 ArticleIdent: Q33795
-
- The sample code below will print out the same time for the start and
- finish in the second printf statement; however, the statements should
- be printed two seconds apart. If ctime(&start) is taken out of the
- second printf statement, the finish time is later than the start time,
- as expected.
- As noted in the C Version 5.10 README.DOC, the ctime function uses
- a single static buffer to store the results of the call; i.e., when
- the second call to the function is made, the results of the first
- call are destroyed. Therefore the behavior of the example is expected.
-
- The following sample code illustrates this behavior:
-
- time_t start, finish ;
- main() {
- time(&start) ;
- printf("the time is %s\n", ctime(&start) ) ;
- for ( i =0; i<1000; i++ )
- time(&finish) ; /* start and finish should be about 2 sec apart */
- printf("ending time is %s and %s\n", ctime(&start), ctime(&finish) ) ;
- }
-
-
- 90. C Version 5.10 LINK and Windows LINK4
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G880603-1453
- Last Modified: 8-AUG-1988 ArticleIdent: Q34029
-
- If you are developing Windows applications, you can use the
- Segemented Executable Linker provided with C Version 5.10.
- If you choose to use this linker for developing Windows
- applications, you must put the EXETYPE WINDOWS statement in your .DEF
- file. If you use LINK4, you do not have to put the EXETYPE WINDOWS
- statement in your .DEF file because the use of LINK4 causes the .EXE
- file to be identified as a Windows application.
-
-
- 91. setvbuf with Buffer Greater than 32K Causes fwrite Failure
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 11-AUG-1988 ArticleIdent: Q34065
-
- The sample program below works correctly if the buffer size of the
- file is under 32K. When the buffer size of the file is set higher
- than 32K (using setvbuf), the fwrite statement will fail and write
- "fwrite failed" to the screen. This problem occurs in Microsoft C
- Versions 5.00 and 5.10.
- Page 538 of the "Microsoft C 5.1 Optimizing Compiler Run Time
- Library Reference" manual indicates that the legal values for the size
- parameter are greater than zero and less than the maximum integer
- value (which is 32K). Therefore, even though the type for the
- size parameter is of type size_t (unsigned integer) only values
- less than 32K are correct for the size parameter to setvbuf().
- However, setvbuf should return an error for invalid size values.
- Microsoft is researching this problem and will post new information
- as it becomes available.
-
- The following sample code demonstrates this behavior:
-
- #include <stdio.h>
-
- char buf[35000] ; /* size of file buffer */
- FILE *stream ;
- long result ;
- int err ;
- char i[10] = "abcdefghij" ;
-
- main() {
- stream = fopen("data1", "w+b") ;
- if ( err = setvbuf( stream, buf, _IOFBF, sizeof(buf) ) != 0)
- printf("failed to set buffer\n") ;
- else
- for ( result = 0; result < 5000; result++ )
- if (err = fwrite( i, sizeof(i), 1, stream ) != 1 ) {
- printf("fwrite failed\n" ) ;
- exit(-1) ;
- }
- }
-
-
- 92. Setting Size and Number of Internal Stacks
-
- Product Version(s): 3.x 4.x 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm s_quickpas s_pascal
- Last Modified: 9-FEB-1990 ArticleIdent: Q58436
-
- If an INTERNAL STACK OVERFLOW system error occurs, the number and/or
- size of internal stacks in DOS should be increased in the CONFIG.SYS
- file. The syntax for this is as follows
-
- STACKS=number,size
-
- where number = number of stacks (8-64, default 9) and size = size of
- the stacks (32-512,default 128).
-
- The following information was taken from the MS-DOS Encyclopedia, Page
- 805:
-
- Each time certain hardware interrupts occur, ... , MS-DOS Version
- 3.2 switches to an internal stack before transferring control to
- the handler that will service the interrupt. In the case of
- nested interrupts, MS-DOS checks to ensure that both interrupts
- do not get the same stack. After the interrupt has been processed,
- the stack is released. This protects the stacks owned by
- application programs or system device drivers from overflowing when
- several interrupts occur in rapid succession.
- .
- .
- .
- If too many interrupts occur too quickly and the pool of internal
- stack frames is exhausted, the system halts with the message
- INTERNAL STACK OVERFLOW. Increasing the number parameter in the
- stacks command usually corrects the problem.
-
-
- 93. Graphic Adapters Supported by the Graphics Routines
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 11-AUG-1988 ArticleIdent: Q34068
-
- The following graphics adapters are supported by Microsoft C
- Version 5.10 and QuickC Version 1.01:
-
- Hercules card
-
- IBM adapters
- 1. MDPA (Monochrome Display and Printer Adapter)
- 2. CGA (Color Graphics Adapter)
- 3. EGA (Enhanced Graphics Adapter)
- 4. MCGA (Multi-Color Graphics Array)
- 5. VGA (PS/2) (Video Graphics Array)
- a. Analog monitors
- 6. VGA (non-PS/2)
- a. Must be only adapter in system
- b. Use only monochrome modes with monochrome monitor
- c. Use only color modes with color monitor
-
- The Hercules card was not supported in previous versions of
- Microsoft C or QuickC.
-
-
- 94. Putting Global Variables in the Default Data Segment
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 18-AUG-1988 ArticleIdent: Q34069
-
- Question:
- How can I tell the compiler to put my global variables in the
- default data segment when I am using the large- or huge-memory models?
-
- Response:
- In any memory model, if the near keyword is applied to global
- variables, they will be put in the default data segment. This action
- ensures that the variable is referenced with a 16-bit address, as
- opposed to the far 32-bit addresses, which will make variables defined
- with the near keyword faster to access.
-
-
- 95. Converting from IEEE to MS binary format
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q34070
-
- Question:
-
- How can I convert an IEEE number into Microsoft binary format?
-
- Response:
-
- The "Microsoft Run-Time Library Reference" manual contains
- documentation of four functions that are used to convert IEEE format
- to MS binary format and MS binary format to IEEE format.
-
- The four functions are as follows:
-
- fieeetomsbin: Converts a single precision floating-point
- number in IEEE format to MS binary format
- fmsbintoieee: Converts a single precision floating-point
- number in MS binary format to IEEE format
- dieeetomsbin: Converts a double precision number in IEEE
- format to MS binary format
- dmsbintoieee: Converts a double precision number in MS binary
- format to IEEE format
-
-
- 96. Accessing Child Process Exit Code from Parent Process
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 9-FEB-1990 ArticleIdent: Q58437
-
- Question:
-
- I am using the spawn() function and I want to be able to find out
- whether or not the child program terminated normally or by entry of
- CTRL+C. Is there anyway I can get the system exit code from the child
- process?
-
- Response:
-
- There is no C run-time function that will return the system exit code
- from a child process. However, Interrupt 21h SubFunction 4Dh can be
- used to return it.
-
- Immediately after a child process terminates, the child exit code and
- the system exit code are in the AL and AH registers respectively.
-
- Example:
-
- _________________________
- | | |
- AX Register | | | | |
- | | |
- -------------------------
- AH | AL
- / \
- / \
- System Exit Code Child Exit Code
-
- When the spawn() family of functions is called with a mode flag of
- P_WAIT, only the child exit code is returned. To read the system exit
- code, a call to Interrupt 21h SubFunction 4Dh is needed.
-
- It is important to get and store the return codes immediately upon
- returning from the child process, since another function may modify
- them.
-
- The following code samples demonstrate how to get the exit code from
- the child process within the parent process with C Version 5.10 and
- QuickC Versions 2.00 and 2.01.
-
- Code Example 1
- --------------
-
- /* Call this prog1.c */
- #include <dos.h>
- #include <stdio.h>
- #include <process.h>
-
- union REGS inregs, outregs, tempreg;
- int retcode;
- unsigned char syscode;
-
- void main (void)
- {
- printf ("In program I\n");
- retcode = spawnl (P_WAIT, "sp2.exe", "sp2", NULL);
-
- /* Call int 21h function 4Dh to obtain exit codes */
-
- inregs.h.ah = 0x4d;
- intdos (&inregs, &outregs);
-
- /* System Exit Code will be in AH. */
-
- syscode = outregs.h.ah;
-
- printf ("Child exit code: %d\n", retcode);
- printf ("Child process ");
- switch (syscode)
- {
- case 0 : printf ("terminated normally\n");
- break;
- case 1 : printf ("exit with a Control-C\n");
- break;
- case 2 : printf ("exit with a hard error\n");
- break;
- case 3 : printf ("exit as a TSR program\n");
- break;
- }
- }
-
- Code Example 2
- --------------
-
- /* Call this sp2.c */
- #include <stdio.h>
-
- void main (void)
- {
- printf ("In program II\n");
- exit (77);
- }
-
- Since QuickC 2.00 and QuickAssembler 2.01 have the feature of using
- inline assembly, the AX register can be access directly without using
- any interrupts. The following line of code can be used in place of the
- interrupt call:
-
- _asm mov syscode, ah
-
-
- 97. Link Error L1073
-
- Product Version(s): 5.01.21 5.01.20
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 11-AUG-1988 ArticleIdent: Q34142
-
- The linker error L1073 is documented in the CodeView and Utilities
- update section of the manuals for MASM Version 5.10, C Version 5.10,
- FORTRAN Version 4.10, and Pascal Version 4.00. The error message is as
- follows:
-
- L1073 file-segment limit exceeded.
-
- The number of physical file segments exceeds the limit of 254
- imposed by OS/2 protected mode and by Windows for each application or
- dynamic-link library. (A file segment is created for each group
- definition, nonpacked logical segment, and set of packed segments.)
- Reduce the number of segments or group more of them, making sure
- /PACKCODE is enabled.
-
-
- 98. Clock: C Function -- Documentation Supplement
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickAsm docsup
- Last Modified: 17-JUL-1990 ArticleIdent: Q49729
-
- The clock function is documented as telling how much processor time
- has been used by the calling process. This definition is misleading.
-
- The clock function returns a clock_t (long) value, which is the
- difference between the time field (for seconds) and millitm field (for
- milliseconds) in the structure that is returned from two calls to the
- ftime function. The first call to ftime is made within the start-up
- code of the executing program, and the second call is made when the
- clock function is explicitly called in your code.
-
- This means that the value returned by clock is the number of CLK_TCKs
- (milliseconds) elapsed since the start-up code was executed, or -1 if
- the function was unsuccessful.
-
- Note: On most IBM PCs and compatibles, the clock speed is not fast
- enough to compute milliseconds, or indeed, hundredths of seconds. The
- ftime function calls interrupt 21, function 2Ch (under DOS), which
- returns, among other information, the seconds in hundredths. The
- hundredths information is an estimation from the clock speed, which is
- approximately 18.2 ticks per second on most PCs. This hundredths value
- is multiplied by 10 to get the millisecond value.
-
- Below is information on resetting the initial time value.
-
- The clock function references an external variable called _citime.
- This causes _cinitim.asm to get linked in to the .EXE, which in turn
- enters a function called _inittime into the start-up initialization
- table.
-
- The _inittime function, which is then called by the start-up code,
- simply makes a call to the ftime function, passing it a static timeb
- structure. Any further calls to the clock function subtract the values
- in this structure from the values in the structure returned by the
- ftime call in the clock function.
-
- In some cases, you might want to know the time elapsed between two or
- more internal points in a program. To reset the initial time value,
- make a call to the function _inittime, which makes a call to ftime,
- resetting the initial time structure to the current time. All
- subsequent calls to the clock function return the elapsed time since
- the last _inittime call.
-
- Other sources of information include the Version 5.10 "Microsoft C for
- the MS-DOS Operating System: Run-Time Library Reference," Page 167 and
- the clock function in the "C Run-Time Library Source Routines," which
- is available as a separate package.
-
-
- 99. C4040 Occurs on Declaration of Huge Array
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | 5.10
- Flags: ENDUSER |
- Last Modified: 17-AUG-1988 ArticleIdent: Q34170
-
- The compiler warning "C4040 near/far/huge on identifier ignored"
- occurs on the declaration of a huge array if the array is not
- declared globally or statically. A huge or far array only can be
- declared at the global (or static) level because local (auto)
- variables are allocated on the stack and cannot be far or huge.
- To ensure that your arrays are allocated as huge or far arrays,
- declare them at the global level or declare them with the static
- storage class.
-
-
- 100. Splitpath Document Error in readme.doc
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q34172
-
- The documentation in the C Version 5.10 readme.doc about the
- document error in the run-time library reference is incorrect. The
- documentation says the following:
-
- char * ext[4]
-
- should read
-
- char * ext[5]
-
- The documentation should say the following:
-
- should read
-
- char ext[5]
-
- In addition, drive, dir, fname, and ext should not have asterisks
- (stars, "*"'s) in front of them either. A proper declaration is:
-
- char path_buffer[40], drive[3], dir[30], fname[9], ext[5];
-
-
- 101. Path Strings Need Double Backslashes or fopen/open Fails
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 27-OCT-1988 ArticleIdent: Q34305
-
- Problem:
-
- According to Pages 444 and 274 of the "Microsoft C 5.10 Optimizing
- Compiler Run-Time Library Reference," I should be able to specify the
- path to the file that I want to open. However, I always receive a null
- pointer, indicating an error, when I attempt to open a file that is
- not in the current directory.
-
- I am using the following fopen statement:
-
- stream = fopen("d:\c\source\test.c", "r");
-
- Response:
-
- The following fopen statement will successfully open the file:
-
- stream = fopen("d:\\c\\source\\test.c", "r");
-
- Because the backslash has special meaning in C, it must be preceded by
- an additional backslash. In the case of the first (unsuccessful)
- example, a file named "d:csourcetest.c" actually is being searched for
- in the current directory. In the second example, the correct directory
- is searched for in the file "test.c".
-
- The following other functions are among those that use path names as
- input arguments:
-
- chdir, mkdir, rmdir, access, chmod, remove, rename, splitpath, stat,
- creat, open, sopen, freopen, tempnam, execl, execle, execlp,
- execlpe, execv, execve, execvp, execvpe, spawnl, spawnle, spawnlp,
- spawnlpe, spawnv, spawnve, spawnvp, spawnvpe, system, _dos_creat,
- _dos_creatnew, _dos_findfirst, _dos_getfileattr, _dos_open,
- _dos_setfileattr, utime, putenv, _searchenv
-
-
- 102. Manual-Setup Procedure for C
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 11-JAN-1990 ArticleIdent: Q34310
-
- The following is a manual-setup procedure for C.
-
- Manual Setup Procedure For Microsoft C (DOS only) System
- Configurations:
-
- Directory:
-
- C:\MSC\BIN Executable file (*.EXE)
- C:\MSC\LIB Library and Object modules (*.LIB, *.OBJ)
- C:\MSC\INCLUDE Include (or header) files (*.H)
- C:\MSC\SRC Sample C programs
- C:\MSC\UTILS Utilities, such as LINK.EXE, CV.EXE ect.
- C:\MSC\INIT Initialization files (*.INI)
- C:\MSC\TEMP Temporary files for the C compiler only
- No files copied into this directory
-
- Autoexec.bat:
-
- SET LIB=C:\MSC\LIB
- SET INCLUDE=C:\MSC\INCLUDE
- SET TMP=C:\MSC\TEMP
- SET INIT=C:\MSC\INIT
- SET PATH=C:\MSC\UTILS;C:\MSC\BIN;C:\MSC\SRC
-
- Config.sys:
-
- Files=20
- Buffers=20
- Shell=C:\Command.com /e: 1024 /p
-
- (Note that the above use of the Shell command is typically only
- supported for DOS Versions 3.20 and later.)
-
- Files to Copy:
-
- Copy the following files into the C:\MSC\BIN directory:
-
- C1.EXE C1L.EXE
- C2.EXE MOUSE.COM
- C3.EXE QCL.HLP
- CL.EXE C23.ERR
- QC.EXE QC.HLP
- QCL.EXE
-
- Copy all the INCLUDE files with .H extensions into the C:\MSC\INCLUDE
- directory.
-
- Copy the following files into the C:\MSC\UTILS directory:
-
- LINK.EXE
- M.EXE
- LIB.EXE
- CV.EXE
- CV.HLP
- Any other utilities, such as EXEMOD.EXE
-
- Copy the following files into the C:\MSC\INIT directory:
-
- TOOLS.INI
- Any other .INI file
-
- Copy any C sample programs provided with the compiler into the
- C:\MSC\SRC directory.
-
- Running The Library Manager -- LIB.EXE:
-
- The following section assumes that the above configurations where
- followed and the operations completed. The following section is on
- libraries.
-
- The C linker searches the C:\MSC\LIB directory to find either C
- combined libraries or explicitly named libraries. The Microsoft naming
- convention for combined libraries is xLIByz.LIB. x is either S, M, C,
- or L for Small, Medium, Compact, or Large, respectively. y is the
- language, in this case C. z is the math libraries; A, E, 7 for
- Alternate, Emulation, or 87 coprocessor, respectively.
-
- The following is an example:
-
- MLIBCE.LIB is the (M)edium model, (C) (E)mulation combined library
-
- Copy the following files into the C:\MSC\LIB directory:
-
- xLIBy.lib
- sDLIBC.LIB Depending on what is desired
- mLIBC.LIB
- cLIBC.LIB
- lLIBC.LIB
- EM.LIB or 87.LIB Depending on what is desired, none for alt. math
- xLIBFz.LIB z is A for alternate or P for other
- sLIBFz.LIB Depending on choice above
- mLIBFz.LIB
- cLIBFz.LIB
- lLIBFz.LIB
- LIBH.LIB
- GRAPHICS.LIB ( Optional )
-
- The following is an example of how to run the library manager:
-
- 1. At the operating system prompt, type LIB, then the name you
- want to call the library with the .LIB extension.
-
- 2. Press the ENTER key. The prompt will say OPERATIONS.
-
- 3. Enter the desired operations, such as appending stand alone .LIB
- or .OBJ files. If the number of modules is too many for one text
- line, the at sign, "@", can be used as a continuation character.
-
- 4. A list ( *.LST ) file is asked for, which is optional.
-
- The following example demonstrates this process:
-
- C:\> LIB name.lib
- Operations: +mod1.lib + mod2.lib + ... +modk.lib@
- Operations: +...+ modn.lib
- List File: name.lst
-
- Name.lst contains a listing of all the functions that occur in
- name.lib.
-
- The following is an example of how to build the C Medium model,
- Emulation library with graphics:
-
- C:\> LIB mlibce.lib
- Operations: +mlibc.lib +em.lib +mlibfp.lib +libh.lib +graphics.lib
- List File: <ENTER> ( pressing enter here will suppress the
- creation of a listing file. )
-
- The above example can be repeated with appropriate modifications to
- create the other C combined libraries.
-
-
- 103. Documentation Error Regarding Precedence Operators
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q34360
-
- There is a documentation error regarding C Version 5.00 and Version
- 5.10 operator precedence. Table 5.1 on Page 137 of the "Microsoft C
- Language Reference Manual" shows two curly braces. Both of these curly
- braces are over-extended in printing.
- The curly brace at the top should only extend from the second line
- to the third line; the curly brace at the bottom should start at the
- fourth-to-last line and stop at the second-to-last line.
-
-
- 104. Unresolved Externals Link Errors for OS/2 Calls
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 20-OCT-1988 ArticleIdent: Q34372
-
- Question:
-
- Why do I get unresolved externals for all of my API calls when I link
- object files produced by the C Version 5.10 compiler?
-
- Response:
-
- You can control the OS/2 files to include by defining certain symbols
- in your source code. A few of the more common ones are listed below:
-
- #define INCL_BASE /* all OS/2 base definitions */
- #define INCL_DOS /* OS/2 DOS kernel */
- #define INCL_SUB /* VIO, keyboard, mouse functions */
- #define INCL_DOSERRORS /* OS/2 errors */
-
- One or more of the above definitions should be followed by the
- following:
-
- #include <os2.h>
-
- The above #defines and #include preprocessor directives will start a
- chain reaction of #defines and #includes that will define the API
- functions in the respective categories of functions. You can follow
- this series to determine the minimum prototypes required for the API
- functions called by your application.
-
- If the proper constant is not defined in your source code above the
- line where you include OS2.H, there will be no prototypes for API
- functions.
-
- All of the API functions must be declared with the Pascal calling
- convention. If there are no prototypes to tell the compiler to use the
- Pascal calling convention, the compiler will use the default C calling
- convention. The C calling convention will place an underscore (_) in
- front of each function called; therefore, each function will be
- incorrectly named, resulting in unresolved externals at link time. The
- Pascal calling convention does not place an underscore in front of
- each function, so if the correct prototypes are given, the linker will
- resolve all of the references to the API functions in the DOSCALLS.LIB
- library.
-
- This information is documented in the README.DOC file that comes with
- Microsoft C Version 5.10.
-
-
- 105. Maximum of 40 File Handles in C 5.10 Multi-Thread Programs
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q34386
-
- Question:
- Can I increase the number of file handles to more than 40
- in a multi-threaded application produced by C Version 5.10?
-
- Response:
- The maximum number of file handles available for multiple-threaded
- applications is 40 by default; this number cannot be increased because
- the multi-threaded startup code is unavailable. Consequently, the C
- startup code constant _NFILE_, which is used to specify the number of
- available file handles, cannot be changed from its default of 40, even
- though the default number of file handles in OS/2 is 255.
-
-
-
- 106. _getimage() Buffer Format is Proprietary
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 18-DEC-1989 ArticleIdent: Q34388
-
- Question:
- What is the internal representation of the screen image saved by
- the _getimage C run-time library function for DOS?
-
- Response:
- Microsoft does not currently release information on the internal
- representation of graphic images saved by _getimage.
-
-
- 107. Far Pointer Comparisons Assume Same Segment
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q34408
-
- When comparing Far pointers with the <, >, <=, or >= operators, the
- two pointers must be in the same segment. The equality operator (==)
- tests both segment and offset to prevent two pointers that have the
- same offset but different segments from being considered equal.
-
- The <, >, <=, and >= operators assume that the pointer share the same
- segment because according to the Draft proposed ANSI C standard,
- pointers can only be compared for precedence if they point to the same
- object. In a segmented architecture such as Intel's, two pointers to
- the same object must share the same segment value (unless the
- pointers are declared to point to a huge object, in which case
- the pointers are handled using 32-bit arithmetic).
-
-
- 108. Far Pointer Comparisons Don't Account for Aliases
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q34410
-
- The code generated to compare two far pointers for equality does not
- account for the possibility of the pointers having different segments
- and offsets, yet still pointing to the same location.
-
- This is correct behavior for the compiler. Only huge pointers are
- normalized. Near and Far pointers that point into the same segment are
- assumed to have the same segment values; any differences between them
- must be in the offset.
-
- Normalizing pointers would involve a tremendous performance penalty
- under MS-DOS and would be impossible under OS/2 due to the
- protected-mode addressing scheme.
-
-
- 109. LINT_ARGS Is Predefined in C Versions 5.x
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 18-AUG-1988 ArticleIdent: Q34437
-
- The special identifier LINT_ARGS, which enables type checking, is
- predefined in Microsoft C Versions 5.00 and later. No preprocessor
- directive or compile option is needed to define this identifier.
-
- Microsoft C Version 4.00 provides the option to enable type checking
- on C run-time library function calls. To enable this option in C
- Version 4.00, define the special identifier LINT_ARGS either by
- placing a #define directive before any #include directives for include
- files that contain run-time library function declarations, or by using
- the /DLINT_ARGS (or /D LINT_ARGS) compilation option.
-
- Defining LINT_ARGS makes the function declarations available that are
- enclosed in preprocessor #ifdefined() blocks and that are included
- only if LINT_ARGS is defined.
-
-
- 110. Installing C on a Network Violates License Agreement
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q34445
-
- Installing software from the C, FORTRAN, Macro Assembler, Pascal, or
- Quick C retail packages on a network is prohibited by the Microsoft
- License Agreement.
-
- These applications are single-user products; network versions of them
- are unavailable at this time.
-
-
-
- 111. Library Reference Defines Unused result Pointer
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q34520
-
- The program example for qsort on Page 476 in the "Microsoft C
- Optimizing Compiler Run-Time Library Reference" has a documentation
- error. The following first declaration within the main function, is
- unnecessary:
-
- char **result;
-
- The result pointer is never used in the program.
-
-
- 112. "User's Guide" Index Reference for /F Is Page 122 Not Page 123
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q34567
-
- The "Microsoft C Optimizing Compiler User's Guide" index has a
- typographical error. The page reference for "/F option" is given as
- Page 123; however, it should be Page 122.
-
-
- 113. Run-Time Limits for C Version 5.10
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q34856
-
- The following is a table of run-time limits in the Microsoft C
- Compiler Version 5.10:
-
- Program Limits at Run Time
-
- Item Description Limit
-
- Files Maximum file size (2**32) - 1 bytes
- (i.e., 4 gigabytes)
- (or limit imposed by DOS, 32 megabytes
- as of DOS 3.3)
-
- Maximum number
- of open files (streams) 20
- (Five streams are opened automatically (stdin,
- stdout, stdaux, and stdprn), leaving 15 files
- available for the program to open.
- Instructions for increasing this limit up to 127 are
- included in the README.DOC of Version 5.10.)
-
- Command line Maximum number of 128
- characters(including
- program name)
-
- Environment Maximum size 32K
- table
-
- This table is listed on Page 286 of the user's guide contained
- in the "Microsoft C 5.1 Optimizing Compiler" manual.
-
-
- 114. C4047 Occurs when Function Prototype Is Omitted or Misnamed
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 26-AUG-1988 ArticleIdent: Q34859
-
- The compiler warning message
-
- "C4047 'operator' : different levels of indirection"
-
- can occur when a function prototype declaration is not specified, when
- the header file that contains the declaration is not given in a
- #include directive, when a reference to a function is misspelled,
- or when a pointer is assigned a value of a different type without
- using an appropriate type cast.
-
- When the function declaration is omitted, a default prototype is
- created with a return type of int assumed. A later use of the function
- then may cause the C4047 warning, such as assigning the return value
- of the function to a non-int variable.
-
- If the call to the function is not spelled the same as the name of the
- prototype, the prototype will not be referred to, the default
- assumption for the function return type will be int, and the warning
- may occur.
-
- More information on function prototyping can be found beginning on
- Page 169 in Chapter 7 of the "Microsoft C Optimizing Compiler Language
- Reference" manual.
-
-
- 115. Array Reference Gives "C4046 '&' on Function/Array, Ignored"
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 26-AUG-1988 ArticleIdent: Q34905
-
- The following compiler warning message occurs when an array is
- referred to incorrectly by the address-of operator (&).
-
- C4046 '&' on function/array, ignored
-
- The following program causes the warning C4046:
-
- void main(void);
- void main(void)
- {
- char array[10];
- char *ptr_to_array;
- ptr_to_array = &array;
- }
-
- To clear up the warning, make the assignment read either
-
- ptr_to_array = array;
-
- or
-
- ptr_to_array = &array[0];
-
- More information about arrays can be found in the last paragraph on
- Page 104 and in Example 1 on Page 119 of the "Microsoft C Optimizing
- Compiler Language Reference" manual.
-
-
- 116. Run-Time Library Reference _getfillmask, _setfillmask docerrs
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | 5.10
- Flags: ENDUSER | docerr
- Last Modified: 26-AUG-1988 ArticleIdent: Q34906
-
- The program examples for _getfillmask and _setfillmask, on Pages
- 325-326 and Pages 521-522 of the "Microsoft C 5.1 Optimizing Compiler
- Run-Time Library Reference" have an error. The fill mask array is
- incorrectly initialized. Back slashes are required prior to "x" for
- specifying hexadecimal constants for the char variables of the masks.
-
- The following sample code correctly initializes the char variables:
-
- #include <stdio.h>
- #include <graph.h>
-
- unsigned char *(style[6])={"\x78\x30\x30\x78\x30\x30\x78\x30",
- "\x78\x32\x30\x78\x30\x38\x78\x32",
- "\x78\x39\x38\x78\x63\x36\x78\x33",
- "\x78\x65\x36\x78\x33\x38\x78\x62",
- "\x78\x66\x63\x78\x65\x65\x78\x37",
- "\x78\x66\x65\x78\x66\x65\x78\x66"};
-
- char *oldstyle = "12345678"; /* place holder for old style */
-
- main()
- {
- int loop;
- _setvideomode(_MRES4COLOR);
- _getfillmask( oldstyle );
- _setcolor( 2 ); /* draw an ellipse under the */
- /* middle few rectangles in a different color */
- _ellipse( _GFILLINTERIOR, 120, 75, 200, 125 );
- _setcolor( 3 );
- for ( loop = 0; loop < 6; loop++ ) {
- /* make 6 rectangles, the first background color */
- _setfillmask( (char far *)(style[ loop ]) );
- _rectangle(_GFILLINTERIOR,loop*40+5,90,(loop+1)*40,110);
- }
- _setfillmask( oldstyle ); /* restore old style */
- while ( !kbhit() ); /* Strike any key to continue */
- _setvideomode (_DEFAULTMODE);
- }
-
-
- 117. Mixed Expressions Can Cause Unsigned Division
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q34920
-
- The ANSI C standard specifies that when a signed and unsigned integer
- are involved in an arithmetic expression, the signed integer is to be
- converted to the type of the unsigned before expression evaluation. If
- the signed integer is negative, the sign will be lost and the value
- will change, even though the bit pattern will remain the same.
-
- This situation is especially a problem with functions that return a
- value of type size_t, which is an alias for unsigned int in our
- implementation. Note that this is not a problem or a code generation
- error, this is the expected behavior.
-
- For example, if the statement
-
- i = (4 - strlen("1234567890")) / 2;
-
- is executed, the value of i will be 32765 rather than -3 as one might
- expect because the expression (4 - strlen("1234567890")) is an
- unsigned integer expression with the value of 65530 rather than a
- signed expression with the value of -6. If you look at the code
- generated, you'll notice that an instruction that performs unsigned
- division is generated rather than a one that performs signed division.
-
- To avoid this behavior, use a typecast on the return value
- of strlen() so that it is treated as an int. For the example
- above, the statement
-
- i = (4 - (int) strlen("1234567890")) / 2;
-
- would have generated the desired value of -3. Note that even this code
- would have failed if the length of the string was greater than 32767;
- however, the incorrect code above fails if the length of the string is
- greater than four.
-
- Runtime functions that return values of type size_t, unsigned, or
- unsigned long include the following:
-
- strtoul, _getlinestyle, fread, fwrite, _clear87, _control87,
- _status87, _fmsize, _memavl, _memmax, _msize, _nmsize,
- stackavail, strcspn, strlen, strspn, _bios_disk,
- _bios_equiplist, _bios_keybrd, _bios_memsize, _bios_printer,
- _bios_serialcom, _bios_timeofday, _dos_allocmem, _dos_close,
- _dos_creat, _dos_creatnew, _dos_findfirst, _dos_findnext,
- _dos_freemem, _dos_getdate, _dos_getdiskfree,
- _dos_getfileattr, _dos_getftime, _dos_gettime, _dos_open,
- _dos_read, _dos_setblock, _dos_setdate, _dos_setfileattr,
- _dos_setftime, _dos_settime, _dos_write, FP_OFF, FP_SEG,
- long_lrotl, long_lrotr, _rotl, and _rotr
-
-
- 118. The Proper Type for Pointer To jmp_buf Is void *
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q34921
-
- The setjmp() and longjmp() functions use a parameter of type jmp_buf.
- (The type jmp_buf is declared in setjmp.h.) Using the & operator
- ("address of") on a variable of type jmp_buf generates the following
- message:
-
- warning C4046: '&' on function/array, ignored
-
- Leaving the ampersand (&) off and assigning the value to a
- variable badptr declared, as follows
-
- set_jmp *bad_ptr;
-
- generates the following message:
-
- warning C4047: '=' : different levels of indirection
-
- To solve the problem, declare the pointer to be of type void *,
- as follows:
-
- void *goodptr;
-
- Then, assign it without using the ampersand, as follows:
-
- goodptr = buf;
-
- Because the header file setjmp.h defines a jmp_buf as an array of
- integers, using the ampersand operator generates the warning described
- above. The reason for choosing an array type rather than a structure
- has to do with common C coding practices and is described in section
- 4.6 of the Rationale for the ANSI C Standard.
-
- Basically, the setjmp() function must change the jmp_buf parameter in
- order to record where to come back to when longjmp() is executed.
- Elsewhere, the standard defines setjmp() as taking a single parameter
- of type jmp_buf, NOT of type "pointer to jmp_buf." The jmp_buf cannot
- be a structure because structures are passed by value and therefore
- could not receive changes made by setjmp(). Since arrays are passed by
- reference (i.e. by their address), setjmp() can change a parameter
- that is passed as an array.
-
- The declaration for badptr (below) declares it to be of type "pointer
- to array of integer," not "pointer to integer." Doing an assignment
- with different pointer types gives the C4047 warning error. (In order
- to do the assignment without a warning, badptr would have to be
- "pointer to integer" because that's the compatible pointer type for
- "array of integer.")
-
- Instead, using goodptr, declared "pointer to void," allows the
- assignment to be made without generating a warning. This is also
- portable code. Note that you cannot use indirection (or subscripting,
- which is a form of indirection) on void pointers.
-
- However, because you don't know what's in the jump buffer anyway, this
- should be no problem. (The contents of the jump buffer are
- implementation-dependent and could even differ from version to version
- of the same compiler. Any code that directly manipulates jump buffers
- is also implementation-dependent and non-portable.)
-
- A brief example program follows:
-
- #include <stdio.h>
- #include <setjmp.h>
-
- jmp_buf buf;
- jmp_buf *badptr;
- void *goodptr;
-
- main()
- {
- badptr = &buf;
- /* warning C4046: '&' on function/array, ignored */
- /* warning C4047: '=' : different levels of indirection */
-
- badptr = buf;
- /* warning C4047: '=' : different levels of indirection */
-
- goodptr = buf;
- /* this works and is the proper way to do this!!! */
-
- exit(0);
- }
-
-
- 119. Corrections to the _setbkcolor Example
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q34923
-
- Problem:
-
- The example program on Page 515 of the "Microsoft C 5.0 (and 5.1)
- Optimizing Compiler Run-Time Library Reference" and the "Microsoft
- QuickC Run-Time Library Reference" is supposed to run through 20
- different background colors, displaying the use of _setbkcolor. When I
- try to run the program, my screen flickers and I am returned to the
- DOS prompt.
-
- Response:
-
- The example is incorrect. The following example changes the background
- color in graphics mode (this example can be found on the Libraries 1
- disk of the QuickC Version 1.01 compiler, in PROGRAMS\SBKCOL.C):
-
- #include <stdio.h>
- #include <graph.h>
-
- long color[16] = {_BLACK,_BLUE,_GREEN,_CYAN,_RED,_MAGENTA,
- _BROWN,_WHITE,_GRAY,_LIGHTBLUE,_LIGHTGREEN,_LIGHTCYAN,
- _LIGHTRED,_LIGHTMAGENTA,_LIGHTYELLOW,_BRIGHTWHITE};
-
- main()
- {
- int loop;
- long i;
- _setvideomode(_HRES16COLOR);
- for (loop = 0; loop < 16; loop++ ) {
- _setbkcolor(color[loop]);
- for (i=0; i < 50000; i++) /* null loop */
- ;
- _setvideomode (_DEFAULTMODE);
- }
-
- The next example changes the background color in text mode:
-
- #include <stdio.h>
- #include <graph.h>
-
- main()
- {
- long loop;
- for (loop = 0; loop < 16; loop++)
- {
- _setbkcolor(loop);
- _outtext(" hello \n");
- }
- }
-
-
- 120. Errors R6012 to R6015 Documented in QuickC 1.01 Guide
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 14-MAR-1990 ArticleIdent: Q34988
-
- The C Run-Time error messages below are not included in
- "Appendix E -- Error Messages" in the "Microsoft C Optimizing Compiler
- User's Guide"; nor are they located in ERRMSG.DOC. They are documented
- in the "Microsoft QuickC Compiler Programmer's Guide" on Page 363, as
- follows:
-
- R6012 invalid near pointer reference
- R6013 invalid far pointer reference
- R6014 control-BREAK encountered
- R6015 unexpected interrupt
-
- According to the README.DOC found on the Product Disk for QuickC
- Version 1.00 and on the Setup Disk for QuickC Version 1.01, the
- run-time error messages R6012 and R6013 have changed as follows:
-
- 1. R6012 illegal near pointer use
-
- A null near pointer was used in the program.
-
- This error only occurs if pointer checking is in effect (i.e.,
- if the program was compiled in the QuickC environment
- with the Pointer Check option in the Compile dialog box, the
- /Zr option on the QCL command line, or the pointer_check
- pragma in effect).
-
- 2. R6013 illegal far pointer use
-
- An out-of-range far pointer was used in the program.
-
- This error only occurs if pointer checking is in effect (i.e. if
- the program was compiled in the QuickC environment with the
- Pointer Check option in the Compile dialog box, the /Zr option
- on the QCL command line, or the pointer_check pragma in effect).
-
- In addition, the following new error messages are documented:
-
- 1. R6014 control-BREAK encountered
-
- You pressed CTRL+BREAK to stop the execution of a program within
- the QuickC environment.
-
- 2. R6015 unexpected interrupt
-
- The program could not be run because it contained unexpected
- interrupts.
-
- When you create an in-memory program from a program list, QuickC
- automatically creates object files and passes them to the linker. If
- you compile with the Debug option turned on, the object files that
- QuickC passes to the linker contain interrupts that are required
- within the QuickC environment. However, you cannot run a program
- created from such object files outside of the QuickC programming
- environment.
-
-
- 121. Unresolved Externals when Linking for Protected Mode
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35031
-
- Problem:
-
- I am compiling my C program for protected-mode with the command:
-
- cl /Lp demo.c
-
- I'm using the Microsoft Segmented-Executable Linker Version
- 5.01.04, but at link-time I get about 10 unresolved externals,
- all of which are OS/2 API calls such as DOSWRITE, DOSCLOSE,
- DOSEXIT.
-
- If I link in the library DOSCALLS.LIB, as follows, the problem is
- corrected:
-
- cl /Lp demo.c doscalls.lib
-
- The manual does not state that DOSCALLS.LIB must be explicitly linked.
-
- Response:
-
- This problem occurs because you are using the wrong version of the
- Microsoft Segmented-Executable Linker. You should be using Version
- 5.01.21, which was distributed with C Version 5.10. Version 5.01.04 is
- the OS/2 linker.
-
- You must link in DOSCALLS.LIB with Version 5.01.04 because this
- version of LINK does not have the ability to bring in libraries that
- are themselves requested by a library.
-
- The library xLIBCyP.LIB (where x is the memory model and y is the math
- package) contains a request for DOSCALLS.LIB. Link Version 5.01.21
- understands this request and searches for DOSCALLS.LIB in the
- directories specified in the LIB environment variable; LINK Version
- 5.01.04 does not understand this request.
-
-
- 122. Don't Place Communal Data in Libraries
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_LIB S_LINK lib link
- Last Modified: 8-SEP-1988 ArticleIdent: Q35032
-
- Do not declare unitialized (communal) data in modules that will
- be placed in libraries. Doing so may result in the module not
- being included at link time.
-
- This information is documented in the last paragraph on Page 84 of the
- "Microsoft C Language Reference" manual, which states the following:
-
- "Unitialized variable declarations at the external level are
- not recommended for any file that might be placed in a library."
-
- Microsoft C supports four different storage classes for variables
- declared at the external level, as follows:
-
- 1. Static variables are local to the module and do not generate
- external references or public definitions, i.e., no other modules
- may reference these variables.
-
- 2. Initialized variables, without static, are allocated storage
- and generate public definitions, i.e., other modules may share
- these variables.
-
- 3. Uninitialized variables, with extern, are not allocated
- storage and they generate external references, i.e, this module
- isn't declaring the data, but it wants to share the data that other
- modules declare.
-
- 4. Communal variables are global variables that are not initialized
- or given the extern modifier. A communal variable is one that is
- used by everybody but not necessarily declared public by anybody;
- the linker will allocate storage for it, if needed.
-
- Communal variables do not have external references or public
- definitions. When the program is linked, if a public definition
- with the same name is found, all communal declarations are treated
- as external references. If no definition is found, the linker will
- allocate storage and again the communal declarations are treated
- like references. When a module is added to a library, the librarian
- takes all public definitions and adds them to the dictionary to be
- searched when the linker resolves references to the library.
-
- Note: Communal variables are NOT added to the dictionary. To do so
- would cause conflicts with other communal declarations and a possible
- public definition.
-
- A good way to declare data in a multi-module program is to use a
- single module that contains public definitions while every other
- module uses the extern modifier. You do not need to actually
- initialize all variables in this one module as long as one of them is
- initialized. This process is sufficient to force the module to be
- brought in while linking.
-
-
- 123. How C Interprets Integer Constants with Leading Zeroes
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 18-OCT-1988 ArticleIdent: Q35037
-
- Question:
-
- Why do the assignments "a = 20" and "a = 020" return different results
- when the values are printed? Why aren't 020 and 20 the same?
-
- The following is an example:
-
- a = 20;
- printf("%d", a); /* this prints "20" */
- a = 020;
- printf("%d", a); /* but this prints "16" */
-
- Response:
-
- In C, any number preceded by a 0 is handled as an octal number (base
- 8). Therefore, "a = 20" is handled as you would expect; however, "a =
- 020" is handled as an octal number and therefore represents the
- decimal value 16.
-
- Note also that ALL character constants of the form '\o', '\oo',
- '\ooo', and the string equivalents are always octal as well. (Hex
- character constants start with "\x".) For instance, '\33' or '\033'
- are both the ESCape character (decimal 27, hex 1B). There is no way
- to use decimal numbers to specify a character constant; however, you
- may use decimal integer constants instead (example: ch = 27; ).
-
-
- 124. Weitek WTL 1167 Math Coprocessor Support
-
- Product Version(s): 5.x | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35142
-
- The Weitek WTL 1167 is found on Compaq's Weitek Coprocessor Board. The
- WTL 1167 is a set of three chips used as a replacement for the Intel
- 80387. Benchmarks in the 1988 March BYTE, show the WTL 1167 with a 7
- percent to 68 percent speed increase over the 80387 on processing of
- double-precision numbers. ("Real-World" speed increase is more like 30
- percent.) Compaq's Weitek Coprocessor Board was designed with an 80387
- socket.
-
- Microsoft only has Math Coprocessor support for Intel chips. If you
- have the WTL 1167 on a Compaq Weitek Coprocessor Board, you also must
- have an 80387 to use our Math Coprocessor Library. Without the 80387
- you will have to use our Emulator or Alternate Math Libraries, or link
- with a third-party library.
-
-
-
- 125. Monochrome Display Adapter Normal Text Example
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35285
-
- On a monochrome display adapter, there is no way to display colors.
- However, you can display Normal Text, Bright Text, Reverse Video,
- Underline, and Blinking.
-
- The following program shows how to get Normal Text, No Blinking, No
- Underlining, and No Inverse on a monochrome display adapter:
-
- #include<graph.h>
- int oldcolor;
- long oldbkcolor;
-
- main()
- {
- _clearscreen(_GCLEARSCREEN);
- oldcolor=_gettextcolor();
- oldbkcolor=_getbkcolor();
- _settextposition(12,0);
- _settextcolor(2); /* foreground color Green */
- _setbkcolor(0L); /* background color Black */
- _outtext("Normal Text, on Mono\n");
- _settextcolor(oldcolor);
- _setbkcolor(oldbkcolor);
- }
-
-
- 126. MDA Bright Underlined Text Example
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35286
-
- On a monochrome display adapter, there is no way to display colors.
- However, you can display Normal Text, Bright Text, Reverse Video,
- Underline, and Blinking.
-
- The following program shows how to get Bright Text, No Blinking,
- Underlined, and No Inverse on a monochrome display adapter:
-
- #include<graph.h>
- int oldcolor;
- long oldbkcolor;
-
- main()
- {
- _clearscreen(_GCLEARSCREEN);
- oldcolor=_gettextcolor();
- oldbkcolor=_getbkcolor();
- _settextposition(12,0);
- _settextcolor(9); /* foreground color Intence Blue */
- _setbkcolor(0L); /* background color Black */
- _outtext("Bright Underlined Text, on Mono\n");
- _settextcolor(oldcolor);
- _setbkcolor(oldbkcolor);
- }
-
-
- 127. MDA Normal Inverse Text Example
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35287
-
- On a monochrome display adapter, there is no way to display colors.
- However, you can display Normal Text, Bright Text, Reverse Video,
- Underline, and Blinking.
-
- The following program shows how to get Normal Text, No Blinking, No
- Underlining, and Inverse on a monochrome display adapter:
-
- #include<graph.h>
- int oldcolor;
- long oldbkcolor;
-
- main()
- {
- _clearscreen(_GCLEARSCREEN);
- oldcolor=_gettextcolor();
- oldbkcolor=_getbkcolor();
- _settextposition(12,0);
- _settextcolor(0); /* foreground color Black */
- _setbkcolor(7L); /* background color White */
- _outtext("Normal Inverse Text, on Mono\n");
- _settextcolor(oldcolor);
- _setbkcolor(oldbkcolor);
- }
-
-
- 128. MDA Blinking Normal Text Example
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 27-OCT-1988 ArticleIdent: Q35288
-
- On a monochrome display adapter, there is no way to display colors.
- However, you can display Normal Text, Bright Text, Reverse Video,
- Underline, and Blinking.
-
- The following program shows how to get Normal Text, Blinking, No
- Underlining, and No Inverse on a monochrome display adapter:
-
- #include<graph.h>
- int oldcolor;
- long oldbkcolor;
-
- main()
- {
- _clearscreen(_GCLEARSCREEN);
- oldcolor=_gettextcolor();
- oldbkcolor=_getbkcolor();
- _settextposition(12,0);
- _settextcolor(18); /* foreground color Green + 16 */
- _setbkcolor(0L); /* background color Black */
- _outtext("Blinking Normal Text, on Mono\n");
- _settextcolor(oldcolor);
- _setbkcolor(oldbkcolor);
- }
-
-
- 129. MDA Blinking Bright Text Example
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35289
-
- On a monochrome display adapter, there is no way to display colors.
- However, you can display Normal Text, Bright Text, Reverse Video,
- Underline, and Blinking.
-
- The following program shows how to get Bright Text, Blinking, No
- Underlining, and No Inverse on a monochrome display adapter:
-
- #include<graph.h>
- int oldcolor;
- long oldbkcolor;
-
- main()
- {
- _clearscreen(_GCLEARSCREEN);
- oldcolor=_gettextcolor();
- oldbkcolor=_getbkcolor();
- _settextposition(12,0);
- _settextcolor(26); /* foreground color Intense Green + 16 */
- _setbkcolor(0L); /* background color Black */
- _outtext("Blinking Bright Text, on Mono\n");
- _settextcolor(oldcolor);
- _setbkcolor(oldbkcolor);
- }
-
-
- 130. MDA Blinking Normal Underlined Text Example
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35290
-
- On a monochrome display adapter, there is no way to display colors.
- However, you can display Normal Text, Bright Text, Reverse Video,
- Underline, and Blinking.
-
- The following program shows how to get Normal Text, Blinking,
- Underlined, and No Inverse on a monochrome display adapter:
-
- #include<graph.h>
- int oldcolor;
- long oldbkcolor;
-
- main()
- {
- _clearscreen(_GCLEARSCREEN);
- oldcolor=_gettextcolor();
- oldbkcolor=_getbkcolor();
- _settextposition(12,0);
- _settextcolor(17); /* foreground color Blue + 16 */
- _setbkcolor(0L); /* background color Black */
- _outtext("Blinking Normal Underlined Text, on Mono\n");
- _settextcolor(oldcolor);
- _setbkcolor(oldbkcolor);
- }
-
-
- 131. MDA Blinking Bright Underlined Text Example
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35291
-
- On a monochrome display adapter, there is no way to display colors.
- However, you can display Normal Text, Bright Text, Reverse Video,
- Underline, and Blinking.
-
- The following program shows how to get Bright Text, Blinking,
- Underlined, and No Inverse on a monochrome display adapter:
-
- #include<graph.h>
- int oldcolor;
- long oldbkcolor;
-
- main()
- {
- _clearscreen(_GCLEARSCREEN);
- oldcolor=_gettextcolor();
- oldbkcolor=_getbkcolor();
- _settextposition(12,0);
- _settextcolor(25); /* foreground color Intence Blue + 16 */
- _setbkcolor(0L); /* background color Black */
- _outtext("Blinking Bright Underlined Text, on Mono\n");
- _settextcolor(oldcolor);
- _setbkcolor(oldbkcolor);
- }
-
-
- 132. MDA Blinking Normal Inverse Text Example
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35292
-
- On a monochrome display adapter, there is no way to display colors.
- However, you can display Normal Text, Bright Text, Reverse Video,
- Underline, and Blinking.
-
- The following program shows how to get Normal Text, Blinking, No
- Underlining, and Inverse, on a monochrome display adapter:
-
- #include<graph.h>
- int oldcolor;
- long oldbkcolor;
-
- main()
- {
- _clearscreen(_GCLEARSCREEN);
- oldcolor=_gettextcolor();
- oldbkcolor=_getbkcolor();
- _settextposition(12,0);
- _settextcolor(16); /* foreground color Black + 16 */
- _setbkcolor(7L); /* background color White */
- _outtext("Blinking Normal Inverse Text, on Mono\n");
- _settextcolor(oldcolor);
- _setbkcolor(oldbkcolor);
- }
-
-
- 133. Directory Listing of C 5.10 for OS/2 Distribution Disks
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35293
-
- Below is a listing of the directories for each of the Microsoft C
- Version 5.10 Optimizing Compiler distribution disks for the OS/2 and
- DOS dual mode (5.25-inch disks). The information is the resulting
- output when the DOS command "dir" is performed on each directory and
- subdirectory.
-
- A line of colons (:::::) separates each disk; subdirectories are
- listed below their parent directory. The first line of each disk
- description is the name of the disk as it is printed on the label.
- Information in parentheses is supplemental and not contained on the
- disk label.
-
- The following is a listing of directories for C Version 5.10
- distribution disks:
-
- (Disk 1 of 14) - Setup
-
- Volume in drive A has no label
- Directory of A:\
-
- README DOC 63360 3-07-88 5:10a
- UTILITY DOC 17794 3-07-88 5:10a
- PACKING LST 11814 3-07-88 5:10a
- CL EXE 31329 3-07-88 5:10a
- CL HLP 2169 3-07-88 5:10a
- CL ERR 2276 3-07-88 5:10a
- C1 EXE 114521 3-07-88 5:10a
- C23 ERR 3272 3-07-88 5:10a
- SETUP EXE 93033 3-07-88 5:10a
- SETUP DOC 15179 3-07-88 5:10a
- 10 File(s) 3072 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 2 of 14) - Include Files and Startup Source Code
-
- Volume in drive A has no label
- Directory of A:\
-
- STARTUP <DIR> 3-07-88 5:10a
- INCLUDE <DIR> 3-07-88 5:10a
- 2 File(s) 29696 bytes free
-
- Volume in drive A has no label
- Directory of A:\INCLUDE
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- SYS <DIR> 3-07-88 5:10a
- ASSERT H 699 3-07-88 5:10a
- BIOS H 4866 3-07-88 5:10a
- CONIO H 952 3-07-88 5:10a
- CTYPE H 2465 3-07-88 5:10a
- DIRECT H 690 3-07-88 5:10a
- DOS H 5917 3-07-88 5:10a
- ERRNO H 1283 3-07-88 5:10a
- FCNTL H 1255 3-07-88 5:10a
- FLOAT H 6011 3-07-88 5:10a
- GRAPH H 7480 3-07-88 5:10a
- IO H 1294 3-07-88 5:10a
- LIMITS H 1553 3-07-88 5:10a
- MALLOC H 3097 3-07-88 5:10a
- MATH H 3324 3-07-88 5:10a
- MEMORY H 1065 3-07-88 5:10a
- SEARCH H 1025 3-07-88 5:10a
- SETJMP H 907 3-07-88 5:10a
- SHARE H 554 3-07-88 5:10a
- SIGNAL H 1905 3-07-88 5:10a
- STDARG H 614 3-07-88 5:10a
- STDDEF H 1100 3-07-88 5:10a
- STDIO H 4500 3-07-88 5:10a
- STDLIB H 4900 3-07-88 5:10a
- STRING H 2209 3-07-88 5:10a
- TIME H 2342 3-07-88 5:10a
- VARARGS H 642 3-07-88 5:10a
- PROCESS H 1988 3-07-88 5:10a
- OS2 H 707 3-07-88 5:10a
- OS2DEF H 5891 3-07-88 5:10a
- BSE H 1139 3-07-88 5:10a
- BSEDOS H 17730 3-07-88 5:10a
- BSEERR H 20940 3-07-88 5:10a
- BSESUB H 11512 3-07-88 5:10a
- 36 File(s) 29696 bytes free
-
- Volume in drive A has no label
- Directory of A:\INCLUDE\SYS
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- LOCKING H 573 3-07-88 5:10a
- STAT H 1497 3-07-88 5:10a
- TIMEB H 844 3-07-88 5:10a
- TYPES H 849 3-07-88 5:10a
- UTIME H 1061 3-07-88 5:10a
- 7 File(s) 29696 bytes free
-
- Volume in drive A has no label
- Directory of A:\STARTUP
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- DOS <DIR> 3-07-88 5:10a
- OS2 <DIR> 3-07-88 5:10a
- FILE2 H 1027 3-07-88 5:10a
- MSDOS H 6849 3-07-88 5:10a
- REGISTER H 922 3-07-88 5:10a
- STARTUP BAT 1663 3-07-88 5:10a
- MAKEFILE 4148 3-07-88 5:10a
- CHKSTK ASM 2044 3-07-88 5:10a
- CHKSUM ASM 3524 3-07-88 5:10a
- NULBODY C 13 3-07-88 5:10a
- README DOC 3199 3-07-88 5:10a
- MSDOS INC 6181 3-07-88 5:10a
- CMACROS INC 12066 3-07-88 5:10a
- BRKCTL INC 784 3-07-88 5:10a
- VERSION INC 503 3-07-88 5:10a
- WILD C 7182 3-07-88 5:10a
- _FILE C 1691 3-07-88 5:10a
- CRT0FP ASM 2223 3-07-88 5:10a
- FMSGHDR ASM 2429 3-07-88 5:10a
- SETARGV ASM 971 3-07-88 5:10a
- 22 File(s) 29696 bytes free
-
- Volume in drive A has no label
- Directory of A:\STARTUP\DOS
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- NULBODY LNK 149 3-07-88 5:10a
- STDENVP ASM 3780 3-07-88 5:10a
- CRT0 ASM 7612 3-07-88 5:10a
- CRT0DAT ASM 14175 3-07-88 5:10a
- CRT0MSG ASM 2840 3-07-88 5:10a
- EXECMSG ASM 1337 3-07-88 5:10a
- NMSGHDR ASM 3010 3-07-88 5:10a
- STDALLOC ASM 2825 3-07-88 5:10a
- STDARGV ASM 13852 3-07-88 5:10a
- 11 File(s) 29696 bytes free
-
- Volume in drive A has no label
- Directory of A:\STARTUP\OS2
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- NULBODY LNK 168 3-07-88 5:10a
- CRT0 ASM 10312 3-07-88 5:10a
- STDENVP ASM 5362 3-07-88 5:10a
- CRT0DAT ASM 10496 3-07-88 5:10a
- CRT0MSG ASM 2891 3-07-88 5:10a
- EXECMSG ASM 2231 3-07-88 5:10a
- NMSGHDR ASM 3486 3-07-88 5:10a
- STDALLOC ASM 3245 3-07-88 5:10a
- STDARGV ASM 13623 3-07-88 5:10a
- 11 File(s) 29696 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 3 of 14) - Compiler 1
-
- Volume in drive A has no label
- Directory of A:\
-
- PATCH <DIR> 3-07-88 5:10a
- C1 ERR 14393 3-07-88 5:10a
- C1L EXE 149303 3-07-88 5:10a
- C3 EXE 125221 3-07-88 5:10a
- ERRMSG DOC 17293 3-07-88 5:10a
- FPEXCEPT DOC 16254 3-07-88 5:10a
- 6 File(s) 15360 bytes free
-
- Volume in drive A has no label
- Directory of A:\PATCH
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- PATCH87 DOC 3937 3-07-88 5:10a
- PATCH87 EXE 4206 3-07-88 5:10a
- SETRHS EXE 543 3-07-88 5:10a
- RMRHS EXE 543 3-07-88 5:10a
- STKPAT BAT 94 3-07-88 5:10a
- STKPAT SCR 30 3-07-88 5:10a
- PTRACE87 PAT 188 3-07-88 5:10a
- PATCH320 DOC 2169 3-07-88 5:10a
- OS2PATCH EXE 1069 3-07-88 5:10a
- OS2PATCH DOC 1401 3-07-88 5:10a
- 12 File(s) 15360 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 4 of 14) - Compiler 2
-
- Volume in drive A has no label
- Directory of A:\
-
- FIXSHIFT COM 688 3-07-88 5:10a
- MSHERC COM 6749 3-07-88 5:10a
- QLIB DOC 12047 3-07-88 5:10a
- QLIB EXE 24557 3-07-88 5:10a
- QLIB INI 2905 3-07-88 5:10a
- C2 EXE 202919 3-07-88 5:10a
- QC HLP 50649 3-07-88 5:10a
- SETENV EXE 10870 3-07-88 5:10a
- MTDYNA DOC 43542 3-07-88 5:10a
- 9 File(s) 4096 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 5 of 14) - Utilities 1
-
- Volume in drive A has no label
- Directory of A:\
-
- ERROUT EXE 10729 3-07-88 5:10a
- EXEHDR EXE 29942 3-07-88 5:10a
- EXEMOD EXE 12336 3-07-88 5:10a
- EXEPACK EXE 14803 3-07-88 5:10a
- IMPLIB EXE 30166 3-07-88 5:10a
- LIB EXE 49661 3-07-88 5:10a
- LINK EXE 117001 3-07-88 5:10a
- MAKE EXE 38613 3-07-88 5:10a
- MOUSE COM 14545 3-07-88 5:10a
- README QC 30360 3-07-88 5:10a
- 10 File(s) 8192 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 6 of 14) - Utilities 2
-
- Volume in drive A has no label
- Directory of A:\
-
- EXT <DIR> 3-07-88 5:10a
- INI <DIR> 3-07-88 5:10a
- BIND EXE 36946 3-07-88 5:10a
- CALLTREE EXE 31233 3-07-88 5:10a
- ECH EXE 19351 3-07-88 5:10a
- EXP EXE 32220 3-07-88 5:10a
- M EXE 94821 3-07-88 5:10a
- MEGREP EXE 31915 3-07-88 5:10a
- RM EXE 24884 3-07-88 5:10a
- UNDEL EXE 30046 3-07-88 5:10a
- 10 File(s) 8192 bytes free
-
- Volume in drive A has no label
- Directory of A:\EXT
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- EXT DOC 15877 3-07-88 5:10a
- EXT H 8730 3-07-88 5:10a
- EXTHDR OBJ 1893 3-07-88 5:10a
- EXTHDRP OBJ 2021 3-07-88 5:10a
- SKEL C 2457 3-07-88 5:10a
- SKEL DEF 211 3-07-88 5:10a
- WS DLL 2609 3-07-88 5:10a
- WS ZXT 2084 3-07-88 5:10a
- 10 File(s) 8192 bytes free
-
- Volume in drive A has no label
- Directory of A:\INI
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- BRIEF INI 2094 3-07-88 5:10a
- EPSILON INI 978 3-07-88 5:10a
- QUICK INI 1058 3-07-88 5:10a
- 5 File(s) 8192 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 7 of 14) - Libraries (Small and Medium Models)
-
- Volume in drive A has no label
- Directory of A:\
-
- SLIBCR LIB 132047 3-07-88 5:10a
- SLIBFA LIB 46089 3-07-88 5:10a
- SVARSTCK OBJ 507 3-07-88 5:10a
- MLIBCR LIB 133071 3-07-88 5:10a
- MLIBFA LIB 46601 3-07-88 5:10a
- MVARSTCK OBJ 507 3-07-88 5:10a
- 6 File(s) 1024 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 8 of 14) - Libraries (Large and Compact Models)
-
- Volume in drive A has no label
- Directory of A:\
-
- CLIBCR LIB 141301 3-07-88 5:10a
- CVARSTCK OBJ 487 3-07-88 5:10a
- LLIBCR LIB 142837 3-07-88 5:10a
- LLIBFA LIB 47625 3-07-88 5:10a
- LVARSTCK OBJ 487 3-07-88 5:10a
- 5 File(s) 27648 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 9 of 14) - Floating-Point Libraries
-
- Volume in drive A has no label
- Directory of A:\
-
- FORTRAN <DIR> 3-07-88 5:10a
- EM LIB 16921 3-07-88 5:10a
- 87 LIB 4121 3-07-88 5:10a
- DOSCALLS LIB 29184 3-07-88 5:10a
- GRAPHICS LIB 59357 3-07-88 5:10a
- LIBH LIB 14209 3-07-88 5:10a
- QUICKLIB OBJ 7917 3-07-88 5:10a
- SETARGV OBJ 143 3-07-88 5:10a
- BINMODE OBJ 127 3-07-88 5:10a
- SLIBFP LIB 37281 3-07-88 5:10a
- MLIBFP LIB 38305 3-07-88 5:10a
- CLIBFA LIB 47113 3-07-88 5:10a
- CLIBFP LIB 38307 3-07-88 5:10a
- LLIBFP LIB 39331 3-07-88 5:10a
- 14 File(s) 15360 bytes free
-
- Volume in drive A has no label
- Directory of A:\FORTRAN
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- MDBGMSG OBJ 540 3-07-88 5:10a
- LDBGMSG OBJ 544 3-07-88 5:10a
- F4COMPAT BAT 3107 3-07-88 5:10a
- 5 File(s) 15360 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 10 of 14) - Microsoft QuickC for MS-DOS
-
- Volume in drive A has no label
- Directory of A:\
-
- QC EXE 326656 3-07-88 5:10a
- QCL EXE 28065 3-07-88 5:10a
- QCL HLP 1456 3-07-88 5:10a
- 3 File(s) 5120 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 11 of 14) - Microsoft CodeView for MS-DOS with Tutorial
-
- Volume in drive A has no label
- Directory of A:\
-
- SAMPLE <DIR> 3-07-88 5:10a
- CV EXE 232896 3-07-88 5:10a
- 2 File(s) 3072 bytes free
-
- Volume in drive A has no label
- Directory of A:\SAMPLE
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- CODEVIEW DOC 12928 3-07-88 5:10a
- ADAPT BAT 133 3-07-88 5:10a
- DEMOB BAT 254 3-07-88 5:10a
- LIFEB BAT 336 3-07-88 5:10a
- LIFEEB BAT 402 3-07-88 5:10a
- MENU BAT 550 3-07-88 5:10a
- SAMPLE BAT 1059 3-07-88 5:10a
- LIFE C 14713 3-07-88 5:10a
- LIFE EXE 33237 3-07-88 5:10a
- LIFE R 5282 3-07-88 5:10a
- C_AUTO CV 3571 3-07-88 5:10a
- E_AUTO CV 6788 3-07-88 5:10a
- L_AUTO CV 13272 3-07-88 5:10a
- M_AUTO CV 733 3-07-88 5:10a
- Q_AUTO CV 15 3-07-88 5:10a
- S_AUTO CV 9091 3-07-88 5:10a
- RESPOND COM 124 3-07-88 5:10a
- S1 @@@ 230 3-07-88 5:10a
- S12 @@@ 926 3-07-88 5:10a
- S13 @@@ 368 3-07-88 5:10a
- S14 @@@ 520 3-07-88 5:10a
- S2 @@@ 752 3-07-88 5:10a
- S3 @@@ 276 3-07-88 5:10a
- S4 @@@ 354 3-07-88 5:10a
- S5 @@@ 554 3-07-88 5:10a
- S6 @@@ 432 3-07-88 5:10a
- S7 @@@ 427 3-07-88 5:10a
- S8 @@@ 479 3-07-88 5:10a
- S9 @@@ 865 3-07-88 5:10a
- 31 File(s) 3072 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 12 of 14) - Utilities 3
-
- Volume in drive A has no label
- Directory of A:\
-
- SOURCE <DIR> 3-07-88 5:10a
- ILINK EXE 88929 3-07-88 5:10a
- LINK EXE 65539 3-07-88 5:10a
- EXEC EXE 9299 3-07-88 5:10a
- CV HLP 21552 3-07-88 5:10a
- CVPACK EXE 49400 3-07-88 5:10a
- 6 File(s) 10240 bytes free
-
- Volume in drive A has no label
- Directory of A:\SOURCE
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- SAMPLES DOC 1760 3-07-88 5:10a
- CFLOW C 44796 3-07-88 5:10a
- CFLOW DOC 3764 3-07-88 5:10a
- DEMO C 419 3-07-88 5:10a
- EMOEM ASM 12129 3-07-88 5:10a
- GRDEMO C 20907 3-07-88 5:10a
- SIEVE C 788 3-07-88 5:10a
- SORTDEMO C 25399 3-07-88 5:10a
- 10 File(s) 10240 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 13 of 14) - Microsoft Codeview for MS OS/2
-
- Volume in drive A has no label
- Directory of A:\
-
- INCLMT <DIR> 3-07-88 5:10a
- CVP EXE 222505 3-07-88 5:10a
- CVP HLP 21552 3-07-88 5:10a
- MEP EXE 97063 3-07-88 5:10a
- CL EXE 33900 3-07-88 5:10a
- CL ERR 2276 3-07-88 5:10a
- CL HLP 2169 3-07-88 5:10a
- C1 EXE 118643 3-07-88 5:10a
- C1L EXE 158625 3-07-88 5:10a
- C1 ERR 14393 3-07-88 5:10a
- C23 ERR 3272 3-07-88 5:10a
- C2 EXE 222515 3-07-88 5:10a
- C3 EXE 129609 3-07-88 5:10a
- BINDC BAT 2784 3-07-88 5:10a
- BINDC CMD 2712 3-07-88 5:10a
- 15 File(s) 41984 bytes free
-
- Volume in drive A has no label
- Directory of A:\INCLMT
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- SYS <DIR> 3-07-88 5:10a
- ASSERT H 703 3-07-88 5:10a
- BIOS H 4866 3-07-88 5:10a
- CONIO H 1024 3-07-88 5:10a
- CTYPE H 2952 3-07-88 5:10a
- DIRECT H 726 3-07-88 5:10a
- DOS H 5917 3-07-88 5:10a
- ERRNO H 1283 3-07-88 5:10a
- FCNTL H 1255 3-07-88 5:10a
- FLOAT H 6027 3-07-88 5:10a
- IO H 1438 3-07-88 5:10a
- LIMITS H 1553 3-07-88 5:10a
- MALLOC H 3370 3-07-88 5:10a
- MATH H 3709 3-07-88 5:10a
- MEMORY H 1149 3-07-88 5:10a
- SEARCH H 1137 3-07-88 5:10a
- SETJMP H 915 3-07-88 5:10a
- SHARE H 554 3-07-88 5:10a
- SIGNAL H 1941 3-07-88 5:10a
- STDARG H 622 3-07-88 5:10a
- STDDEF H 1217 3-07-88 5:10a
- STDIO H 5046 3-07-88 5:10a
- STDLIB H 5335 3-07-88 5:10a
- STRING H 2629 3-07-88 5:10a
- TIME H 2693 3-07-88 5:10a
- VARARGS H 650 3-07-88 5:10a
- PROCESS H 2370 3-07-88 5:10a
- OS2 H 707 3-07-88 5:10a
- OS2DEF H 5891 3-07-88 5:10a
- BSE H 1139 3-07-88 5:10a
- BSEDOS H 17730 3-07-88 5:10a
- BSEERR H 20940 3-07-88 5:10a
- BSESUB H 11512 3-07-88 5:10a
- 35 File(s) 41984 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 14 of 14) - MS OS/2 Libraries
-
- Volume in drive A has no label
- Directory of A:\
-
- EXAMPLE <DIR> 3-07-88 5:10a
- SLIBCP LIB 119999 3-07-88 5:10a
- MLIBCP LIB 121535 3-07-88 5:10a
- CLIBCP LIB 129257 3-07-88 5:10a
- LLIBCP LIB 130793 3-07-88 5:10a
- APILMR OBJ 105 3-07-88 5:10a
- API LIB 81408 3-07-88 5:10a
- CDLLSUPP LIB 9475 3-07-88 5:10a
- LLIBCDLL LIB 178143 3-07-88 5:10a
- LLIBCMT LIB 198913 3-07-88 5:10a
- CDLLOBJS LIB 203063 3-07-88 5:10a
- CDLLOBJS DEF 4397 3-07-88 5:10a
- CDLLOBJS CMD 2048 3-07-88 5:10a
- CRTEXE OBJ 1089 3-07-88 5:10a
- CRTDLL OBJ 577 3-07-88 5:10a
- CRTLIB OBJ 1177 3-07-88 5:10a
- 16 File(s) 0 bytes free
-
- Volume in drive A has no label
- Directory of A:\EXAMPLE
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- MHELLO C 2990 3-07-88 5:10a
- MKMHELLO CMD 433 3-07-88 5:10a
- STMAIN C 825 3-07-88 5:10a
- STMAIN DEF 41 3-07-88 5:10a
- STDLL C 393 3-07-88 5:10a
- STDLL DEF 124 3-07-88 5:10a
- MKSTDLL CMD 714 3-07-88 5:10a
- MTMAIN C 735 3-07-88 5:10a
- MTMAIN DEF 41 3-07-88 5:10a
- MTDLL C 393 3-07-88 5:10a
- MTDLL DEF 124 3-07-88 5:10a
- MKMTDLL CMD 1587 3-07-88 5:10a
- SNAP C 13083 3-07-88 5:10a
- MAKESNAP CMD 2148 3-07-88 5:10a
- 16 File(s) 0 bytes free
-
-
- 134. Getting the Address of a Function with FP_SEG and FP_OFF
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35295
-
- To get the address of a function, you may set a pointer to the
- function by using FP_SEG and FP_OFF to get the segment and offset
- for the function.
-
- The following sample code demonstrates this process:
-
- #include <dos.h>
- #include <stdio.h>
-
- int foo();
- int (*foo_ptr)();
- unsigned int seg_val;
- unsigned int off_val;
-
- void main(void);
- void main(void)
- {
- /* set the pointer to the function */
- foo_ptr = foo;
-
- /* use FP_SEG() and FP_OFF() to get segment and offset */
- seg_val = FP_SEG(foo_ptr);
- off_val = FP_OFF(foo_ptr);
- printf("Segment is %d; Offset is %d\n", seg_val, off_val);
- }
-
- int foo()
- {}
-
-
- 135. Differences between C signal() Function and DosSetSigHandler
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35297
-
- Question:
-
- I have some questions concerning signal handling in OS/2, and
- differences between the C run-time library signal() function and the
- OS/2 API routine DosSetSigHandler. What are the differences; what are
- the results of using these routines?
-
- Response:
-
- Under OS/2, the C run-time library signal() function has fewer options
- and different behavior than the OS/2 API DosSetSigHandler function.
- The signal() function is described in the next few paragraphs, then
- the features of DosSetSigHandler are explained.
-
- Features of the C Run-Time Library Signal() Function in OS/2
-
- The C run-time library signal() function only is for use in
- single-thread applications, and for floating-point exception handling
- in Dynamic Link Libraries.
-
- Using strictly C run-time functions, such as signal() and spawnlp(),
- signal handling in OS/2 is accomplished (or not, by default) by thread
- 1 of each process. This behavior occurs whether the process was invoked
- from the operating system or was spawned by another process.
-
- As a result, while this process is running, a child process is
- unaffected by how its parent handles signals; if a signal is generated
- during the execution of the child, the child either handles it with
- its own signal handler, or if it was spawned with P_WAIT or P_NOWAIT,
- control returns to the parent process. (However, no control returns to
- the parent process's signal handler, which is unlike the
- DosSetSigHandler's effect.) Once the parent resumes execution, its
- signal handler once again will be in effect for any newly generated
- signals.
-
- For example, say a parent process sets up a signal handler, then
- spawns MAKE. While running MAKE, if a CTRL+C signal occurs, either the
- process spawned by MAKE such as the CL driver, or MAKE itself will be
- interrupted. If CL is interrupted by CTRL+C, it returns an error to
- MAKE and MAKE terminates. If MAKE itself is interrupted, it
- terminates. In either case, control will be returned to the parent
- process after the point where it spawned MAKE, and the parent resumes
- execution. The parent's signal handler will handle signals generated
- after it starts executing again, but none of the signals generated by
- the child are kept by the system and returned to the parent.
-
- If both the parent and child have no signal handler, if the child is
- spawned with P_WAIT or P_NOWAIT and it is terminated without hanging
- the system, then control goes back to the parent. The parent continues
- executing until it is terminated.
-
- Features of OS/2's DosSetSigHandler
-
- The OS/2 API routine DosSetSigHandler has more options than the C
- run-time library signal() function. A child process will inherit
- (i.e., use) the parent's signal handler, or the closest ancestor's
- defined signal handler if its immediate parent didn't create one.
-
- If the parent called DosSetSigHandler to handle CTRL+C with Action = 0
- (install the system default action, in this case to terminate the
- process), a CTRL+C issued in the parent or child will use the parent's
- handler. If the CTRL+C occurred in the child, the child will be
- terminated (by default) when the parent's signal handler is called.
- The parent will resume execution after its signal handler function is
- completed in a similar manner to DOS. However, the child may install
- its own signal handler rather than using the parent's.
-
- If you use Action = 2 (install the specified signal handler
- for the given signal) for handling CTRL+C in the parent process,
- hitting CTRL+C in its child causes the child to pause while the
- handler is executed; however, the child won't terminate. For Action =
- 1 (ignore signal) in a DosSetSigHandler call by the parent for CTRL+C,
- CTRL+C is ignored in the child as well as the parent.
-
- If neither parent nor child sets up a signal handler, CTRL+C will kill
- them all regardless of which process gets the CTRL+C. This action
- occurs because signal handlers are being inherited, and signals are
- either handled in the current process if it has a handler, or
- effectively passed back up the process subtree (from child to parent)
- until a process is reached that has a CTRL+C signal handler.
-
- Because the default action for CTRL+C is to terminate the process, a
- process without a CTRL+C handler gets terminated, and the CTRL+C
- signal effectively gets passed up to its parent. If the parent doesn't
- have a CTRL+C handler, it terminates and passes control to its parent.
- If no one set up a signal handler, the original parent at the root of
- the process subtree handles the signal, and the default action is to
- return to the system.
-
- Some precautions for signal handling are recommended. After setting up
- a signal handler, avoid making system calls from thread 1, especially
- time-consuming calls such as waiting for keyboard input or some other
- event. If OS/2 is executing code for a system call at Ring 0, it
- cannot run a signal handler at Ring 3. Instead, executing the system
- code is completed, or aborted if it is a time-consuming call (which
- could result in incomplete I/O), and then the signal is handled.
-
- Another particularly bad scenario is if thread 1 blocks a critical
- section of code with a RAM semaphore, is interrupted and handles a
- signal, and then the signal handler resumes execution elsewhere so
- that the RAM semaphore is not cleared and the critical section remains
- blocked. If thread 1 must run critical sections of code, it should
- call DosHoldSignal to disable the signal prior to entering the
- critical section.
-
-
- 136. Using PRINT SCREEN Key to Print CGA Graphics
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 27-OCT-1988 ArticleIdent: Q35303
-
- To print graphics generated by a C program using the PRINT SCREEN key,
- you must first install GRAPHICS.COM (supplied by your DOS). This
- process only will work with the CGA modes. Hercules, EGA, and VGA modes
- will not print with this method; you must obtain a third party, public
- domain, or shareware program to print graphics from these modes.
-
- In the DOS environment, PRINT SCREEN prints any text screen to an
- attached printer hooked to PRN. This function isn't able to interpret
- a graphic screen to the printer because a graphic screen is defined
- and produced differently than a text screen.
-
- A unit of area is defined by a pixel rather than a character. (This
- can be noticed by the way a text screen is described "80 columns by 25
- rows" as opposed to a graphics screen "640 pixels by 200 pixels.")
-
- DOS supplies a TSR that allows the PRINT SCREEN to interpret a graphic
- screen. This is called GRAPHICS.COM. When it is installed, it will
- interpret a CGA graphic screen to a printer attached to PRN. This
- utility must be installed before running a C program that draws a
- graphic screen in the CGA modes, i.e., the program must have specified
- a _setvideomode to _MRES4COLOR, _MRESNOCOLOR, or _HRESBW. Any of the
- other video modes will require some other utility to interpret the
- screen for the printer.
-
- It also should be noted that GRAPHICS.COM was written to write to an
- IBM Personal Graphics or IBM Personal Color Printer. It may be
- necessary on some other printers to set some switch settings, if
- available, to emulate either of these printers. The printer manual for
- the specific printer should be consulted in these cases.
-
-
- 137. Libraries Created by IMPLIB Are Different than those from LIB
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# S880908-4
- Last Modified: 26-SEP-1988 ArticleIdent: Q35539
-
- The only similarity between Libraries created by IMPLIB and libraries
- created by LIB is the filename extension ".LIB".
-
- Libraries created by IMPLIB only contain the names of functions and
- modules to satisfy the linker. The actual code is brought in later by
- loading Dynamic Link Libraries (DLL).
-
- Regular libraries contain all the code for the functions. One or more
- functions are contained in a module (e.g. object file). The code for
- the entire module containing a called function is statically linked
- into the executable file.
-
- You cannot use LIB to get any information about libraries created by
- IMPLIB. You cannot combine IMPLIB and LIB libraries. To see what
- modules are in an IMPLIB library, use the type command to display the
- .LIB file; it is a text file.
-
-
- 138. Example Incorrect for the write() Function
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 26-SEP-1988 ArticleIdent: Q35545
-
- The example for the write() function on Page 641 of the "Microsoft C
- 5.1 Optimizing Compiler Run-Time Library Reference" is incorrect; it
- causes OS/2 to generate a General Protection (GP) fault.
-
- This example fails in OS/2 because it attempts to write 60,000 bytes
- from a buffer of size 6,000 bytes. In effect, it is attempting to read
- beyond the buffer of size 6000, causing the GP fault. In DOS, this
- error may go undetected, but an extra 54,000 bytes of random garbage
- may be written to the file.
-
- To work around this problem, change the number of bytes to write from
- 60,000 bytes to 6000 bytes.
-
-
- 139. The Total Bytes in MAP File Differs from Load Size in EXEMOD
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# S880908-4
- Last Modified: 19-SEP-1988 ArticleIdent: Q35628
-
- Question:
-
- When I run EXEMOD on my executable file and look at the minimum load
- size, it always is greater than or equal to the size of my executable
- listed in my MAP file. Why?
-
- Response:
-
- EXEMOD reflects the minimum load size of a program that is rounded up
- to the 16-byte paragraph level. As a result, the minimum load size
- will be up to 15-bytes larger than the size of the program indicated
- in your MAP file.
-
-
- 140. Process "exit" Values Must Lie Between 0 and 255 Inclusive
-
- Product Version(s): 4.00 5.00 5.10 | 4.00 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC
- Last Modified: 29-DEC-1988 ArticleIdent: Q39469
-
- Problem:
-
- I am testing the exit value of a process. This value is not accurate
- for values above 255.
-
- Response:
-
- Exit values must range between 0 and 255 inclusive. This limitation
- has its roots in the "terminate with return code" interrupt function
- (interrupt 21H, function 4CH). Using this function, exit values are
- specified in the AL register. The AL register allows values from 0 to
- 255. All Microsoft C programs under DOS terminate using this function.
-
- Under OS/2, the same limitation exists. Although OS/2 does not use
- interrupts as DOS does, the reasoning is analogous.
-
- Exit values can be tested using the functions spawnl, spawnle, spawnlp,
- spawnlpe, spawnv, spawnve, spawnvp, and spawnvpe. Also, batch files may
- test exit values using the IF ERRORLEVEL statement.
-
-
- 141. Incorrect Function Declaration
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr h_fortran h_masm s_pascal
- Last Modified: 23-SEP-1988 ArticleIdent: Q35730
-
- On Page 66 of the "Microsoft Mixed-Language Programmer's Guide"
- provided with C Versions 5.00 and 5.10, FORTRAN Versions 4.0x and
- 4.10, MASM Versions 5.00 and 5.10, and Pascal Version 4.00, the
- example program given in section 5.4.2 "Calling C from Pascal --
- Function Call" is incorrect. If the Pascal source code in the manual
- is compiled, the following errors will occur on the function
- declaration line:
-
- function Fact (n : integer) [C]; extern;
- ^ ^ ^
- Warning 173 Insert: ____________________| | |
- (the compiler is expecting a colon) | |
- | |
- 315 Type unknown or invalid assumed integer __| |
- Begin Skip |
- |
- 187 End Skip _________________________________________|
-
- The function declaration in the Pascal program is missing its return
- value. If the line is corrected to look as follows the program works
- properly:
-
- function Fact (n : integer) : integer [C]; extern;
-
-
- 142. Directory Listing for C 5.10 Distribution Disks (3.5-Inch)
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 23-SEP-1988 ArticleIdent: Q35753
-
- The following is a listing of the directories for each of the
- Microsoft C Version 5.10 Optimizing Compiler distribution disks
- (3.5-inch disks). The information is the resulting output when the DOS
- command "dir" is performed on each directory and subdirectory.
-
- A line of colons (:::::) separates each disk, and subdirectories are
- listed below their parent directory. The first line of each disk
- description is the name of the disk as it is printed on the label;
- however, information in parentheses is supplemental and not contained
- on the disk label.
-
- :::::::::::::::::::::::::::::::::::::::
- C 5.10 distribution disks, 3.5-inch disks
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 1 of 10) - Setup, Include Files, and Startup Source Code
-
- Volume in drive B has no label.
- Directory of B:\
-
- STARTUP <DIR> 3-07-88 5:10a
- INCLUDE <DIR> 3-07-88 5:10a
- README DOC 63358 3-07-88 5:10a
- UTILITY DOC 17794 3-07-88 5:10a
- PACKING LST 11504 3-07-88 5:10a
- CL EXE 31329 3-07-88 5:10a
- CL HLP 2169 3-07-88 5:10a
- CL ERR 2276 3-07-88 5:10a
- C1 EXE 114521 3-07-88 5:10a
- C23 ERR 3272 3-07-88 5:10a
- SETUP EXE 93033 3-07-88 5:10a
- SETUP DOC 15179 3-07-88 5:10a
- 12 File(s) 37888 bytes free
-
- Volume in drive B has no label.
- Directory of B:\INCLUDE
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- SYS <DIR> 3-07-88 5:10a
- ASSERT H 699 3-07-88 5:10a
- BIOS H 4866 3-07-88 5:10a
- CONIO H 952 3-07-88 5:10a
- CTYPE H 2465 3-07-88 5:10a
- DIRECT H 690 3-07-88 5:10a
- DOS H 5917 3-07-88 5:10a
- ERRNO H 1283 3-07-88 5:10a
- FCNTL H 1255 3-07-88 5:10a
- FLOAT H 6011 3-07-88 5:10a
- GRAPH H 7480 3-07-88 5:10a
- IO H 1294 3-07-88 5:10a
- LIMITS H 1553 3-07-88 5:10a
- MALLOC H 3097 3-07-88 5:10a
- MATH H 3324 3-07-88 5:10a
- MEMORY H 1065 3-07-88 5:10a
- SEARCH H 1025 3-07-88 5:10a
- SETJMP H 907 3-07-88 5:10a
- SHARE H 554 3-07-88 5:10a
- SIGNAL H 1905 3-07-88 5:10a
- STDARG H 614 3-07-88 5:10a
- STDDEF H 1100 3-07-88 5:10a
- STDIO H 4500 3-07-88 5:10a
- STDLIB H 4900 3-07-88 5:10a
- STRING H 2209 3-07-88 5:10a
- TIME H 2342 3-07-88 5:10a
- VARARGS H 642 3-07-88 5:10a
- PROCESS H 1988 3-07-88 5:10a
- OS2 H 707 3-07-88 5:10a
- OS2DEF H 5891 3-07-88 5:10a
- BSE H 1139 3-07-88 5:10a
- BSEDOS H 17730 3-07-88 5:10a
- BSEERR H 20940 3-07-88 5:10a
- BSESUB H 11512 3-07-88 5:10a
- 36 File(s) 37888 bytes free
-
- Volume in drive B has no label.
- Directory of B:\INCLUDE\SYS
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- LOCKING H 573 3-07-88 5:10a
- STAT H 1497 3-07-88 5:10a
- TIMEB H 844 3-07-88 5:10a
- TYPES H 849 3-07-88 5:10a
- UTIME H 1061 3-07-88 5:10a
- 7 File(s) 37888 bytes free
-
- Volume in drive B has no label.
- Directory of B:\STARTUP
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- DOS <DIR> 3-07-88 5:10a
- OS2 <DIR> 3-07-88 5:10a
- FILE2 H 1027 3-07-88 5:10a
- MSDOS H 6849 3-07-88 5:10a
- REGISTER H 922 3-07-88 5:10a
- STARTUP BAT 1663 3-07-88 5:10a
- MAKEFILE 4148 3-07-88 5:10a
- CHKSTK ASM 2044 3-07-88 5:10a
- CHKSUM ASM 3524 3-07-88 5:10a
- NULBODY C 13 3-07-88 5:10a
- README DOC 3199 3-07-88 5:10a
- MSDOS INC 6181 3-07-88 5:10a
- CMACROS INC 12066 3-07-88 5:10a
- BRKCTL INC 784 3-07-88 5:10a
- VERSION INC 503 3-07-88 5:10a
- WILD C 7182 3-07-88 5:10a
- _FILE C 1691 3-07-88 5:10a
- CRT0FP ASM 2223 3-07-88 5:10a
- FMSGHDR ASM 2429 3-07-88 5:10a
- SETARGV ASM 971 3-07-88 5:10a
- 22 File(s) 37888 bytes free
-
- Volume in drive B has no label.
- Directory of B:\STARTUP\DOS
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- NULBODY LNK 149 3-07-88 5:10a
- STDENVP ASM 3780 3-07-88 5:10a
- CRT0 ASM 7612 3-07-88 5:10a
- CRT0DAT ASM 14175 3-07-88 5:10a
- CRT0MSG ASM 2840 3-07-88 5:10a
- EXECMSG ASM 1337 3-07-88 5:10a
- NMSGHDR ASM 3010 3-07-88 5:10a
- STDALLOC ASM 2825 3-07-88 5:10a
- STDARGV ASM 13852 3-07-88 5:10a
- 11 File(s) 37888 bytes free
-
- Volume in drive B has no label.
- Directory of B:\STARTUP\OS2
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- NULBODY LNK 168 3-07-88 5:10a
- CRT0 ASM 10312 3-07-88 5:10a
- STDENVP ASM 5362 3-07-88 5:10a
- CRT0DAT ASM 10496 3-07-88 5:10a
- CRT0MSG ASM 2891 3-07-88 5:10a
- EXECMSG ASM 2231 3-07-88 5:10a
- NMSGHDR ASM 3486 3-07-88 5:10a
- STDALLOC ASM 3245 3-07-88 5:10a
- STDARGV ASM 13623 3-07-88 5:10a
- 11 File(s) 37888 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 2 of 10) - Compiler
-
- Volume in drive B has no label.
- Directory of B:\
-
- PATCH <DIR> 3-07-88 5:10a
- C1 ERR 14393 3-07-88 5:10a
- C1L EXE 149303 3-07-88 5:10a
- C3 EXE 125221 3-07-88 5:10a
- ERRMSG DOC 17293 3-07-88 5:10a
- FPEXCEPT DOC 16254 3-07-88 5:10a
- FIXSHIFT COM 688 3-07-88 5:10a
- MSHERC COM 6749 3-07-88 5:10a
- QLIB DOC 12047 3-07-88 5:10a
- QLIB EXE 24557 3-07-88 5:10a
- QLIB INI 2905 3-07-88 5:10a
- C2 EXE 202919 3-07-88 5:10a
- QC HLP 50649 3-07-88 5:10a
- SETENV EXE 10870 3-07-88 5:10a
- MTDYNA DOC 43542 3-07-88 5:10a
- 15 File(s) 24576 bytes free
-
- Volume in drive B has no label.
- Directory of B:\PATCH
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- PATCH87 DOC 3937 3-07-88 5:10a
- PATCH87 EXE 4206 3-07-88 5:10a
- SETRHS EXE 543 3-07-88 5:10a
- RMRHS EXE 543 3-07-88 5:10a
- STKPAT BAT 94 3-07-88 5:10a
- STKPAT SCR 30 3-07-88 5:10a
- PTRACE87 PAT 188 3-07-88 5:10a
- PATCH320 DOC 2169 3-07-88 5:10a
- OS2PATCH EXE 1069 3-07-88 5:10a
- OS2PATCH DOC 1401 3-07-88 5:10a
- 12 File(s) 24576 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 3 of 10) - Utilities
-
- Volume in drive B has no label.
- Directory of B:\
-
- EXT <DIR> 3-07-88 5:10a
- INI <DIR> 3-07-88 5:10a
- ERROUT EXE 10729 3-07-88 5:10a
- EXEHDR EXE 29942 3-07-88 5:10a
- EXEMOD EXE 12336 3-07-88 5:10a
- EXEPACK EXE 14803 3-07-88 5:10a
- IMPLIB EXE 30166 3-07-88 5:10a
- LIB EXE 49661 3-07-88 5:10a
- LINK EXE 117001 3-07-88 5:10a
- MAKE EXE 38613 3-07-88 5:10a
- MOUSE COM 14545 3-07-88 5:10a
- README QC 30351 3-07-88 5:10a
- BIND EXE 36946 3-07-88 5:10a
- CALLTREE EXE 31233 3-07-88 5:10a
- ECH EXE 19351 3-07-88 5:10a
- EXP EXE 32220 3-07-88 5:10a
- M EXE 94821 3-07-88 5:10a
- MEGREP EXE 31915 3-07-88 5:10a
- RM EXE 24884 3-07-88 5:10a
- UNDEL EXE 30046 3-07-88 5:10a
- 20 File(s) 21504 bytes free
-
- Volume in drive B has no label.
- Directory of B:\EXT
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- EXT DOC 15877 3-07-88 5:10a
- EXT H 8730 3-07-88 5:10a
- EXTHDR OBJ 1893 3-07-88 5:10a
- EXTHDRP OBJ 2021 3-07-88 5:10a
- SKEL C 2457 3-07-88 5:10a
- SKEL DEF 211 3-07-88 5:10a
- WS DLL 2609 3-07-88 5:10a
- WS ZXT 2084 3-07-88 5:10a
- 10 File(s) 21504 bytes free
-
- Volume in drive B has no label.
- Directory of B:\INI
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- BRIEF INI 2094 3-07-88 5:10a
- EPSILON INI 978 3-07-88 5:10a
- QUICK INI 1058 3-07-88 5:10a
- 5 File(s) 21504 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 4 of 10) - Libraries (Small, Medium, Compact, and Large
- Models)
-
- Volume in drive B has no label.
- Directory of B:\
-
- SLIBCR LIB 132047 3-07-88 5:10a
- SLIBFA LIB 46089 3-07-88 5:10a
- SVARSTCK OBJ 507 3-07-88 5:10a
- MLIBCR LIB 133071 3-07-88 5:10a
- MLIBFA LIB 46601 3-07-88 5:10a
- MVARSTCK OBJ 507 3-07-88 5:10a
- CLIBCR LIB 141301 3-07-88 5:10a
- CVARSTCK OBJ 487 3-07-88 5:10a
- LLIBCR LIB 142837 3-07-88 5:10a
- LLIBFA LIB 47625 3-07-88 5:10a
- LVARSTCK OBJ 487 3-07-88 5:10a
- 11 File(s) 33792 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 5 of 10) - Floating-Point Libraries and Microsoft QuickC for
- MS-DOS
-
- Volume in drive B has no label.
- Directory of B:\
-
- FORTRAN <DIR> 3-07-88 5:10a
- EM LIB 16921 3-07-88 5:10a
- 87 LIB 4121 3-07-88 5:10a
- DOSCALLS LIB 29184 3-07-88 5:10a
- GRAPHICS LIB 59357 3-07-88 5:10a
- LIBH LIB 14209 3-07-88 5:10a
- QUICKLIB OBJ 7917 3-07-88 5:10a
- SETARGV OBJ 143 3-07-88 5:10a
- BINMODE OBJ 127 3-07-88 5:10a
- SLIBFP LIB 37281 3-07-88 5:10a
- MLIBFP LIB 38305 3-07-88 5:10a
- CLIBFA LIB 47113 3-07-88 5:10a
- CLIBFP LIB 38307 3-07-88 5:10a
- LLIBFP LIB 39331 3-07-88 5:10a
- QC EXE 326656 3-07-88 5:10a
- QCL EXE 28065 3-07-88 5:10a
- QCL HLP 1456 3-07-88 5:10a
- 17 File(s) 25600 bytes free
-
- Volume in drive B has no label.
- Directory of B:\FORTRAN
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- MDBGMSG OBJ 540 3-07-88 5:10a
- LDBGMSG OBJ 544 3-07-88 5:10a
- F4COMPAT BAT 3107 3-07-88 5:10a
- 5 File(s) 25600 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 6 of 10) - Microsoft CodeView for MS-DOS with Tutorial
-
- Volume in drive B has no label.
- Directory of B:\
-
- SAMPLE <DIR> 3-07-88 5:10a
- SOURCE <DIR> 3-07-88 5:10a
- CV EXE 232896 3-07-88 5:10a
- ILINK EXE 88929 3-07-88 5:10a
- LINK EXE 65539 3-07-88 5:10a
- EXEC EXE 9299 3-07-88 5:10a
- CV HLP 21552 3-07-88 5:10a
- CVPACK EXE 49400 3-07-88 5:10a
- 8 File(s) 18432 bytes free
-
- Volume in drive B has no label.
- Directory of B:\SAMPLE
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- CODEVIEW DOC 12928 3-07-88 5:10a
- ADAPT BAT 133 3-07-88 5:10a
- DEMOB BAT 254 3-07-88 5:10a
- LIFEB BAT 336 3-07-88 5:10a
- LIFEEB BAT 402 3-07-88 5:10a
- MENU BAT 550 3-07-88 5:10a
- SAMPLE BAT 1059 3-07-88 5:10a
- LIFE C 14713 3-07-88 5:10a
- LIFE EXE 33237 3-07-88 5:10a
- LIFE R 5282 3-07-88 5:10a
- C_AUTO CV 3571 3-07-88 5:10a
- E_AUTO CV 6788 3-07-88 5:10a
- L_AUTO CV 13272 3-07-88 5:10a
- M_AUTO CV 733 3-07-88 5:10a
- Q_AUTO CV 15 3-07-88 5:10a
- S_AUTO CV 9091 3-07-88 5:10a
- RESPOND COM 124 3-07-88 5:10a
- S1 @@@ 230 3-07-88 5:10a
- S12 @@@ 926 3-07-88 5:10a
- S13 @@@ 368 3-07-88 5:10a
- S14 @@@ 520 3-07-88 5:10a
- S2 @@@ 752 3-07-88 5:10a
- S3 @@@ 276 3-07-88 5:10a
- S4 @@@ 354 3-07-88 5:10a
- S5 @@@ 554 3-07-88 5:10a
- S6 @@@ 432 3-07-88 5:10a
- S7 @@@ 427 3-07-88 5:10a
- S8 @@@ 479 3-07-88 5:10a
- S9 @@@ 865 3-07-88 5:10a
- 31 File(s) 18432 bytes free
-
- Volume in drive B has no label.
- Directory of B:\SOURCE
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- SAMPLES DOC 1760 3-07-88 5:10a
- CFLOW C 44796 3-07-88 5:10a
- CFLOW DOC 3764 3-07-88 5:10a
- DEMO C 419 3-07-88 5:10a
- EMOEM ASM 12129 3-07-88 5:10a
- GRDEMO C 20907 3-07-88 5:10a
- SIEVE C 788 3-07-88 5:10a
- SORTDEMO C 25399 3-07-88 5:10a
- 10 File(s) 18432 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 7 of 10) - MS OS/2 Compiler
-
- Volume in drive B has no label.
- Directory of B:\
-
- CL EXE 33900 3-07-88 5:10a
- CL ERR 2276 3-07-88 5:10a
- CL HLP 2169 3-07-88 5:10a
- C1 EXE 118643 3-07-88 5:10a
- C1L EXE 158625 3-07-88 5:10a
- C1 ERR 14393 3-07-88 5:10a
- C23 ERR 3272 3-07-88 5:10a
- C2 EXE 222515 3-07-88 5:10a
- C3 EXE 129609 3-07-88 5:10a
- BINDC BAT 2784 3-07-88 5:10a
- BINDC CMD 2712 3-07-88 5:10a
- 11 File(s) 32768 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 8 of 10) - Microsoft CodeView for MS OS/2, Microsoft Editor,
- and Include Files
-
- Volume in drive B has no label.
- Directory of B:\
-
- INCLMT <DIR> 3-07-88 5:10a
- CVP EXE 222505 3-07-88 5:10a
- CVP HLP 21552 3-07-88 5:10a
- MEP EXE 97063 3-07-88 5:10a
- 4 File(s) 242688 bytes free
-
- Volume in drive B has no label.
- Directory of B:\INCLMT
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- SYS <DIR> 3-07-88 5:10a
- ASSERT H 703 3-07-88 5:10a
- BIOS H 4866 3-07-88 5:10a
- CONIO H 1024 3-07-88 5:10a
- CTYPE H 2952 3-07-88 5:10a
- DIRECT H 726 3-07-88 5:10a
- DOS H 5917 3-07-88 5:10a
- ERRNO H 1283 3-07-88 5:10a
- FCNTL H 1255 3-07-88 5:10a
- FLOAT H 6027 3-07-88 5:10a
- IO H 1438 3-07-88 5:10a
- LIMITS H 1553 3-07-88 5:10a
- MALLOC H 3370 3-07-88 5:10a
- MATH H 3709 3-07-88 5:10a
- MEMORY H 1149 3-07-88 5:10a
- SEARCH H 1137 3-07-88 5:10a
- SETJMP H 915 3-07-88 5:10a
- SHARE H 554 3-07-88 5:10a
- SIGNAL H 1941 3-07-88 5:10a
- STDARG H 622 3-07-88 5:10a
- STDDEF H 1217 3-07-88 5:10a
- STDIO H 5046 3-07-88 5:10a
- STDLIB H 5335 3-07-88 5:10a
- STRING H 2629 3-07-88 5:10a
- TIME H 2693 3-07-88 5:10a
- VARARGS H 650 3-07-88 5:10a
- PROCESS H 2370 3-07-88 5:10a
- OS2 H 707 3-07-88 5:10a
- OS2DEF H 5891 3-07-88 5:10a
- BSE H 1139 3-07-88 5:10a
- BSEDOS H 17730 3-07-88 5:10a
- BSEERR H 20940 3-07-88 5:10a
- BSESUB H 11512 3-07-88 5:10a
- 35 File(s) 242688 bytes free
-
- Volume in drive B has no label.
- Directory of B:\INCLMT\SYS
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- LOCKING H 573 3-07-88 5:10a
- STAT H 1517 3-07-88 5:10a
- TIMEB H 852 3-07-88 5:10a
- TYPES H 849 3-07-88 5:10a
- UTIME H 1073 3-07-88 5:10a
- 7 File(s) 242688 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 9 of 10) - MS OS/2 Libraries 1
-
- Volume in drive B has no label.
- Directory of B:\
-
- SLIBCP LIB 119999 3-07-88 5:10a
- MLIBCP LIB 121535 3-07-88 5:10a
- CLIBCP LIB 129257 3-07-88 5:10a
- LLIBCP LIB 130793 3-07-88 5:10a
- APILMR OBJ 105 3-07-88 5:10a
- API LIB 81408 3-07-88 5:10a
- 6 File(s) 143360 bytes free
-
- :::::::::::::::::::::::::::::::::::::::
-
- (Disk 10 of 10) - MS OS/2 Libraries 2
-
- Volume in drive B has no label.
- Directory of B:\
-
- EXAMPLE <DIR> 3-07-88 5:10a
- CDLLSUPP LIB 9475 3-07-88 5:10a
- LLIBCDLL LIB 178143 3-07-88 5:10a
- LLIBCMT LIB 198913 3-07-88 5:10a
- CDLLOBJS LIB 203063 3-07-88 5:10a
- CDLLOBJS DEF 4397 3-07-88 5:10a
- CDLLOBJS CMD 2048 3-07-88 5:10a
- CRTEXE OBJ 1089 3-07-88 5:10a
- CRTDLL OBJ 577 3-07-88 5:10a
- CRTLIB OBJ 1177 3-07-88 5:10a
- 10 File(s) 93184 bytes free
-
- Volume in drive B has no label.
- Directory of B:\EXAMPLE
-
- . <DIR> 3-07-88 5:10a
- .. <DIR> 3-07-88 5:10a
- MHELLO C 2990 3-07-88 5:10a
- MKMHELLO CMD 433 3-07-88 5:10a
- STMAIN C 825 3-07-88 5:10a
- STMAIN DEF 41 3-07-88 5:10a
- STDLL C 393 3-07-88 5:10a
- STDLL DEF 124 3-07-88 5:10a
- MKSTDLL CMD 714 3-07-88 5:10a
- MTMAIN C 735 3-07-88 5:10a
- MTMAIN DEF 41 3-07-88 5:10a
- MTDLL C 393 3-07-88 5:10a
- MTDLL DEF 124 3-07-88 5:10a
- MKMTDLL CMD 1587 3-07-88 5:10a
- SNAP C 13083 3-07-88 5:10a
- MAKESNAP CMD 2148 3-07-88 5:10a
- 16 File(s) 93184 bytes free
-
-
- 143. Quick Reference Documentation Error with _setbkcolor
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 23-SEP-1988 ArticleIdent: Q35805
-
- In the Library Routines section of the C Versions 5.00 and 5.10
- "Microsoft Quick Reference Guide," the function _setbkcolor has the
- incorrect argument type. Instead of a short type argument, the
- argument should be a long type.
-
-
- 144. Sample Pascal Program Documentation Error: function Fact
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | h_masm S_PASCAL h_fortran
- Last Modified: 23-SEP-1988 ArticleIdent: Q35812
-
- In the Microsoft Mixed-Language Programming Guide in section 5.4.2 on
- Page 64, the Pascal function declaration is stated as follows:
-
- function Fact (n: integer) [C]; extern;
-
- The Pascal function declaration should be the following:
-
- function Fact (n: integer) : integer [C]; extern;
-
-
-
- 145. Source Not Available for MS Binary to IEEE Conversion
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-OCT-1988 ArticleIdent: Q35988
-
- The following functions are not included in the C Run-Time Library
- Source Routines:
-
- dieeetomsbin
- dmsbintoieee
- fieeetomsbin
- fmsbintoieee
-
- These functions are incorrectly listed in a flier called "Microsoft C
- Run-Time Library Source Runtime" as included in the product.
-
-
- 146. C: Automatic Casting from Near Pointer to Far Pointer
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-MAY-1989 ArticleIdent: Q43486
-
- In Microsoft C, the automatic type casting from a near pointer to a
- far pointer that is performed by the compiler will make the segment
- address of the resulting pointer the same as that of DGroup. In those
- cases, no explicit type casting is needed.
-
- Two of the cases of the automatic casting are shown in the following
- sample program:
-
- #include <malloc.h>
-
- void foo (char far *) ;
- void main (void)
- {
- char far *lpChar ;
- char * npChar ;
- lpChar = malloc( 100 ); /* malloc is mapped to _nmalloc,
- ** and returns near pointer, automatic type
- ** casting is performed with assignment */
-
- foo( npChar ) ; /* npChar is converted to a far pointer
- ** with the segment address to be DS */
- }
-
- void foo (char far * p)
- {
- }
-
-
- 147. IEEE Floating-Point Representation and MS languages
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm b_quickbas
- Last Modified: 8-MAR-1989 ArticleIdent: Q36068
-
- The following information discusses how real*4 (single precision) and
- real*8 (double precision) numbers are stored internally by Microsoft
- languages that use the IEEE floating-point format. The Microsoft
- Binary Format (MBF) for floating-point storage, which is used by the
- BASIC interpreter for MS-DOS and by QuickBASIC up through Versions
- 3.x, is NOT discussed in this article.
-
- This information applies to all versions of Microsoft languages that
- use IEEE floating-point format, including the following:
-
- 1. C Versions 3.00, 4.00, 5.00, and 5.10
-
- 2. FORTRAN Versions 3.1x, 3.20, 3.30, 4.0x, and 4.10
-
- 3. MASM Versions 1.25, 1.27, 3.0x, 4.00, 5.00, and 5.10
-
- 4. Pascal Versions 3.1x, 3.20, 3.30, 3.31, 3.32, and 4.00
-
- 5. The coprocessor version of QuickBASIC Version 3.00 (QB87.EXE), and
- QuickBASIC Versions 4.00, 4.00b, and 4.50
-
- There are three internal varieties of real numbers. Microsoft is
- consistent with the IEEE numeric standards. Real*4 and real*8 are used
- in all of our languages. Real*10 is used only with MASM. Real*10 is
- also what any 8087, 80287, or 80387 coprocessor and the emulator math
- package use when performing floating-point calculations.
-
- In FORTRAN, real*4 is declared using the words "REAL" or "REAL*4."
- The words "DOUBLE PRECISION" or "REAL*8" are used to declare a real*8
- number.
-
- In C, real*4 is declared using the word "float." Real*8 is declared
- using the word "double" or "long double."
-
- In Pascal, real*4 is declared using the word "real4," and real*8 is
- declared using the word "real8." The word "real" defaults to real*4,
- but this can be changed to real*8 with the $real:8 metacommand.
-
- In MASM, real*4 is declared with the "DD" directive, real*8 is
- declared with the "DQ" directive, and real*10 is declared with the
- "DT" directive.
-
- In QuickBASIC, the default variable type is real*4. Variables that
- have an exclamation point ("!") as their last character are also
- real*4. Variables that have a cross-hatch (also called pound-sign,
- "#" as the last character of its name are double precision (real*8).
- The DEFSNG and DEFDBL statements can be used to declare that variables
- whose names begin with certain letters and are of a certain type.
- These types can also be declared with the keywords SINGLE and DOUBLE.
-
- The values are stored as follows:
-
- real*4 sign bit, 8 bit exponent, 23 bit mantissa
- real*8 sign bit, 11 bit exponent, 52 bit mantissa
- real*10 sign bit, 15 bit exponent, 64 bit mantissa
-
- In real*4 and real*8 formats, there is an assumed leading one in the
- mantissa that is not stored in memory, so the mantissas are actually
- 24 or 53 bits, even though only 23 or 52 bits are stored. The
- real*10 format stores actually stores this bit.
-
- The exponents are biased by half of their possible value. This means
- you subtract this bias from the stored exponent to get the actual
- exponent. If the stored exponent is less than the bias, it is actually
- a negative exponent.
-
- The exponents are biased as follows:
-
- 8-bit (real*4) exponents are biased by 127
- 11-bit (real*8) exponents are biased by 1023
- 15-bit (real*10) exponents are biased by 16383
-
- These exponents are not powers of ten; they are powers of two, i.e.,
- 8-bit stored exponents can be up to 127. 2**127 is roughly equivalent
- to 10**38, which is the actual limit of real*4.
-
- The mantissa is stored as a binary fraction of the form 1.XXX... .
- This fraction has a value greater than or equal to 1 and less than 2.
- Note that real numbers are always stored in normalized form, i.e., the
- mantissa is left-shifted such that the high-order bit of the mantissa
- is always one. Because this bit is always one, it is assumed (not
- stored) in the real*4 and real*8 formats. The binary (not decimal)
- point is assumed to be just to the right of the leading one.
-
- The format, then, for the various sizes is as follows:
-
- BYTE 1 BYTE 2 BYTE 3 BYTE 4 ... BYTE n
- real*4 SXXX XXXX XMMM MMMM MMMM MMMM MMMM MMMM
- real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM
- real*10 SXXX XXXX XXXX XXXX 1MMM MMMM MMMM MMMM ... MMMM MMMM
-
- S represents the sign bit, the X's are the exponent bits, and the M's
- are the mantissa bits. Note that the leftmost one is assumed in real*4
- and real*8 formats, but present as "1" in BYTE 3 of the real*10
- format.
-
- To shift the binary point properly, you first un-bias the exponent and
- then move the binary point to the right or left the appropriate number
- of bits.
-
- The following are some examples in real*4 format:
-
- SXXX XXXX XMMM MMMM ... MMMM MMMM
- 2 = 1 * 2**1 = 0100 0000 0000 0000 ... 0000 0000 = 4000 0000
- Note the sign bit is zero, and the stored exponent is 128, or
- 100 0000 0 in binary, which is 127 plus 1. The stored mantissa
- is (1.) 000 0000 ... 0000 0000, which has an implied leading
- 1 and binary point, so the actual mantissa is one.
- -2 = -1 * 2**1 = 1100 0000 0000 0000 ... 0000 0000 = C000 0000
- Same as +2 except that the sign bit is set. This is true for
- all IEEE format floating-point numbers.
- 4 = 1 * 2**2 = 0100 0000 1000 0000 ... 0000 0000 = 4080 0000
- Same mantissa, exponent increases by one (biased value is
- 129, or 100 0000 1 in binary.
- 6 = 1.5 * 2**2 = 0100 0000 1100 0000 ... 0000 0000 = 40C0 0000
- Same exponent, mantissa is larger by half--it's
- (1.) 100 0000 ... 0000 0000, which, since this is a binary
- fraction, is 1 1/2 (the values of the fractional digits are
- 1/2, 1/4, 1/8, etc.).
- 1 = 1 * 2**0 = 0011 1111 1000 0000 ... 0000 0000 = 3F80 0000
- Same exponent as other powers of two, mantissa is one less
- than two at 127, or 011 1111 1 in binary.
- .75 = 1.5 * 2**-1 = 0011 1111 0100 0000 ... 0000 0000 = 3F40 0000
- The biased exponent is 126, 011 1111 0 in binary, and the
- mantissa is (1.) 100 0000 ... 0000 0000, which is 1 1/2.
- 2.5 = 1.25 * 2**1 = 0100 0000 0010 0000 ... 0000 0000 = 4020 0000
- Exactly the same as two except that the bit which represents
- 1/4 is set in the mantissa.
- 0.1 = 1.6 * 2**-4 = 0011 1101 1100 1100 ... 1100 1101 = 3DCC CCCD
- 1/10 is a repeating fraction in binary. The mantissa is
- just shy of 1.6, and the biased exponent says that 1.6 is to
- be divided by 16 (it is 011 1101 1 in binary, which is 123 in
- decimal). The true exponent is 123 - 127 = -4, which means
- that the factor by which to multiply is 2**-4 = 1/16. Note
- that the stored mantissa is rounded up in the last bit--an
- attempt to represent the unrepresentable number as accuartely
- as possible. (The reason that 1/10 and 1/100 are not exactly
- representable in binary similar to the reason that 1/3 is not
- exactly representable in decimal.)
- 0 = 1.0 * 2**-128 = all zero's--a special case.
-
-
- 148. Different Results between Alternate and Coprocessor/Emulator Math
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm
- Last Modified: 12-OCT-1988 ArticleIdent: Q36069
-
- There may be differences between the floating point values you get
- when using coprocessor/emulator math and the alternate math packages.
-
- This behavior applies to C Versions 3.00, 4.00, 5.00, and 5.01, Pascal
- Versions 3.1x, 3.20, 3.30, 3.31, 3.32, and 4.00, FORTRAN Versions
- 3.1x, 3.20, 3.30, 3.31, 4.0x, and 4.10, and MASM Versions 1.25, 1.27,
- 3.0x, 4.00, 5.00, and 5.10.
-
- When you do any floating point arithmetic with the coprocessor all
- values are pushed onto the coprocessor stack. The coprocessor stack
- only holds 10-byte reals. This means that all real*4 and/or real*8
- (real/double) are expanded to 10-byte reals, then all of the
- arithmetic is done on these 10-byte reals. The emulator package does
- this same expansion. The results of floating point calculations are
- then rounded back down to real*4 or real*8 format.
-
- Alternate math calculations are performed using real*4 or real*8
- format which can result in less precision than that available with
- coprocessor/emulator math.
-
-
- 149. Share Problems Using sopen and Incorrect oflag
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 12-OCT-1988 ArticleIdent: Q36611
-
- The "important" note on Page 550 of the "Microsoft Optimizing 5.1
- Compiler Run-Time Library Reference" manual has an error in the second
- condition listed as causing problems when opening a new file with the
- sopen function under DOS Versions 3.00, 3.10, or 3.20 with SHARE
- installed.
-
- "With oflag set to any combination that includes O_FLAG..." is
- incorrect. There is no O_FLAG setting available. The oflag setting
- should be O_CREAT | O_RDWR. This oflag setting with pmode set to
- S_IREAD requires that shflag be set to SH_COMPAT to avoid problems
- with the new file created by sopen.
-
- The problems that can occur when the wrong sopen options are used
- include not opening the new file, or opening the new file but not
- being able to write to it resulting in a file of zero length.
-
- These problems may also occur in DOS Version 3.30.
-
-
- 150. Filename from tmpnam Has Prefix from P_tmpdir
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 18-OCT-1988 ArticleIdent: Q36675
-
- The tmpnam function generates a temporary filename that can be used as
- a temporary file. The character string that tmpnam creates consists of
- the path prefix defined by the P_tmpdir entry in stdio.h, followed by
- a sequence consisting of the digit characters "0" through "9".
-
- This information is in the "Microsoft C 5.1 Optimizing Compiler
- Run-Time Library Reference" manual on Page 611. The "Microsoft C 4.00
- Run-Time Library Reference" manual does not describe this naming
- behavior.
-
- In Version 5.00 and 5.10, the P_tmpdir entry is defined in stdio.h
- as follows:
-
- #define P_tmpdir "\\"
-
- In Version 4.00, the P_tmpdir entry is defined in stdio.h as follows:
-
- #define P_tmpdir "\\TMP"
-
- Thus, a string for a temporary filename created under Version 4.00
- will have the form \TMP\x (where x is the generated number), and it
- will be necessary to have a TMP subdirectory.
-
-
- 151. Warning C4000 Unknown Warning
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q36695
-
- This information is from section D.1.3 (Page 340) of the "Microsoft
- QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
- "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
- 5.10.
-
- The messages listed in this section indicate potential problems but do
- not hinder compilation and linking. The number in parentheses at the
- end of an error-message description gives the minimum warning level
- that must be set for the message to appear.
-
- The following is the warning:
-
- C4000 Unknown Warning
- The compiler detected an unknown error condition.
-
- Please report this condition to Microsoft Corporation, using
- the Product Assistance Request form at the back of this
- manual.
-
- The occurance of this warning indicates a problem with the compiler.
- Please include the smallest possible example of source code which
- demonstrates the problem when sending the Software Problem Report to
- Microsoft.
-
-
- 152. Warning C4017 Cast of int Expression to far Pointer
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q36706
-
- This information is from section D.1.3 (Page 340) of the "Microsoft
- QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
- "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
- 5.10.
-
- This message indicates potential problems but does not hinder
- compilation and linking. The number in parentheses at the end of a
- warning-message description gives the minimum warning level that must
- be set for the message to appear.
-
- The following is the warning:
-
- C4017 cast of int expression to far pointer
-
- A far pointer represents a full segmented address. On
- an 8086/8088 processor, casting an 'int' value to a
- far pointer may produce an address with a meaningless
- segment value. (1)
-
- A possible cause for this warning is that a function that returns a far
- pointer was not prototyped and the compiler assumed the return type of
- the function to be "int" instead of a far pointer as was actually
- intended.
-
- The followin is a code example:
-
- main()
- {
- char far *address ;
-
- address = foo () ;
- }
-
- Since foo was not prototyped, the compiler will assume that foo
- returns an integer. If the warning level is set at 2, this code would
- receive the warning C4016 "foo : no function return type" (if the
- warning level were set to 1).
-
-
- 153. Warning C4028 Parameter 'n' Declaration Different
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q36710
-
- This information is from section D.1.3 (Page 340) of the "Microsoft
- QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
- "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
- 5.10.
-
- This message indicates potential problems but does not hinder
- compilation and linking. The number in parentheses at the end of a
- warning-message description gives the minimum warning level that must
- be set for the message to appear.
-
- The following is the warning:
-
- C4028 parameter 'n' declaration different
-
- The type of the given parameter did not agree with the
- corresponding type in the argument-type list or with
- the corresponding formal parameter. (1)
-
- Note: this message may appear when it should actually have produced
- the warning C4074 if an ellipsis is used in the prototype.
-
- The call of the function gave a parameter type that did not match up
- with prototype and function definition, as in the following code
- fragment:
-
- void foo (int) ;
-
- main ()
- {
- float fp ;
- foo (fp) ;
- }
-
- void foo (int)
- {
- }
-
-
- 154. Warning C4037 'identifier' : Formal Parameters Ignored
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q36722
-
- This information is from section D.1.3 (Page 340) of the "Microsoft
- QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
- Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
- 5.10.
-
- This message indicates potential problems but does not hinder
- compilation and linking. The number in parentheses at the end of a
- warning-message description gives the minimum warning level that must
- be set for the message to appear.
-
- The following is the warning:
-
- C4037 'identifier' : formal parameters ignored
-
- No storage class or type name appeared before the
- declarators of formal parameters in a function
- declaration, as in the following example:
-
- int *f(a,b,c);
-
- The formal parameters are ignored. (1)
-
- The prototype for this function, f, did not declare the types of
- arguments that the function receives. You could correct the above
- example as follows:
-
- int *f (int a, int b, int c) ;
-
-
- 155. Warning C4040 near/far/huge on 'identifier' Ignored
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q36725
-
- This information is from section D.1.3 (Page 340) of the "Microsoft
- QuickC Programmer's Guide and section E.3.3 (Page 269) of the
- "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
- 5.10.
-
- This message indicates potential problems but does not hinder
- compilation and linking. The number in parentheses at the end of a
- warning-message description gives the minimum warning level that must
- be set for the message to appear.
-
- The following is the warning:
-
- C4040 near/far/huge on 'identifier' ignored
-
- The 'near' or 'far' keyword has no effect in the
- declaration of the given identifier and is ignored.
-
- You cannot declare an array to be huge if it is declared within a
- function because this array will reside on the stack that is limited
- to the default data segment. You can move the declaration of the array
- with the huge keyword outside of all functions, use the "static" or
- "extern" keywords to move the array into a far data segment, or use a
- huge or far pointer.
-
- QuickC Versions 1.00 and 1.01 do not support the huge keyword or the
- huge-memory model.
-
-
-
- 156. Warning C4047 'operator': Different Levels of Indirection
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q36729
-
- This information is from section D.1.3 (Page 340) of the "Microsoft
- QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
- "Microsoft C Optimizing Compiler User's Guide" for Version 5.00 and
- 5.10.
-
- This message indicates potential problems but does not hinder
- compilation and linking. The number in parentheses at the end of a
- warning-message description gives the minimum warning level that must
- be set for the message to appear.
-
- The following is the warning message:
-
- C4047 'operator' : different levels of indirection
-
- An expression involving the specified operator had
- inconsistent levels of indirection. (1)
-
- The following example illustrates this condition:
-
- char **p ;
- char *q ;
- .
- .
- p = q ;
-
- You will commonly get this warning if you do not cast MALLOC() to your
- pointer type. The following code fragment will produce the C4047
- message:
- char *string ;
- string = malloc (5) ;
-
- To eliminate this warning message in this example, cast MALLOC() as
- follows:
- string = (char *) malloc (5) ;
-
- This is a result of the fact that MALLOC()'s default return type is
- "void *".
-
-
- 157. C2086 Error When Compiling with /Oi and #include <mt\math.h>
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 16-JAN-1990 ArticleIdent: Q36782
-
- When using the multithreaded version of <math.h>, error C2086
- "identifier redefinition" occurs if -Oi (or -Ox) intrinsic
- optimization is enabled. The cause of the error is the fact that the
- compiler has built-in prototypes for intrinsic functions. Because
- <mt\math.h> declares these functions differently, the C2086 error is
- generated.
-
- This conflict arises for the following floating-point routines:
-
- acos asin atan atan2 cos exp fabs fmod log log10 pow
- sin sinh sqrt tan tanh
-
- The conflict occurs because the compiler has built-in function
- prototypes for routines for which it is generating intrinsics. When
- you compile with the normal include files, the compiler's internal
- prototype is the same as the one in <math.h>, so there is no conflict.
- However, when you use <mt\math.h>, the prototypes are changed from
- "_CDECL" to "far pascal", which causes the redefinition error.
-
- One workaround is to use the following
-
- #pragma function ({func1} {func2} {etc})
-
- at the start of the module to force functions to be used instead of
- intrinsics. This will also work if you are using the alternate math
- library with multithreaded and/or DLL modules and the link fails with
- unresolved externals.
-
- A second workaround to this conflict is to use the C preprocessor's
- conditional-compilation facility, as in the following fragment of
- <mt\math.h>:
-
- ----------------------------------------------------------------------
- last part of <mt\math.h>
- ----------------------------------------------------------------------
-
- /* function prototypes */
-
- #ifndef INTRINSICS /* this is the modification */
-
- double far pascal acos(double);
- double far pascal asin(double);
- double far pascal atan(double);
- double far pascal atan2(double, double);
- double far pascal cos(double);
- double far pascal cosh(double);
- double far pascal exp(double);
- double far pascal fabs(double);
- double far pascal fmod(double, double);
- double far pascal log(double);
- double far pascal log10(double);
- double far pascal pow(double, double);
- double far pascal sin(double);
- double far pascal sinh(double);
- double far pascal sqrt(double);
- double far pascal tan(double);
- double far pascal tanh(double);
-
- #endif /* INTRINSICS; end of modification */
-
- int far _CDECL abs(int);
- double far pascal atof(const char far *);
- double far pascal cabs(struct complex);
- double far pascal ceil(double);
- int far _CDECL dieeetomsbin(double far *, double far *);
- int far _CDECL dmsbintoieee(double far *, double far *);
- int far _CDECL fieeetomsbin(float far *, float far *);
- double far pascal floor(double);
- int far _CDECL fmsbintoieee(float far *, float far *);
- double far pascal frexp(double, int far *);
- double far pascal hypot(double, double);
- double far pascal j0(double);
- double far pascal j1(double);
- double far pascal jn(int, double);
- long far _CDECL labs(long);
- double far pascal ldexp(double, int);
- int far _CDECL matherr(struct exception far *);
- double far pascal modf(double, double far *);
- double far pascal y0(double);
- double far pascal y1(double);
- double far pascal yn(int, double);
-
- In this version of <mt\math.h>, the intrinsic math routines have been
- pulled out of the main block of function prototypes and conditionally
- compiled; the preprocessor will include them only if the symbol
- "INTRINSICS" is not defined. This way, under normal circumstances,
- nothing is different; when you #include <mt\math.h>, all the
- prototypes are included. But when you want to optimize with /Ox or
- /Oi, you can use the following command-line option so that the
- preprocessor will remove those prototypes from the compilation:
-
- cl ... /D INTRINSICS ...
-
-
- 158. Microsoft OS/2 Languages Use Virtual Memory
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | h_fortran 4.10 h_masm 5.10 S_PASCAL 4.00
- Last Modified: 18-OCT-1988 ArticleIdent: Q36791
-
- Question:
-
- Will Microsoft's OS/2 languages use virtual memory under OS/2?
-
- Response:
-
- OS/2 will make use of virtual memory if memman=MOVE is set in the
- CONFIG.OS2 or CONFIG.SYS file, physical RAM becomes full, and there is
- enough free disk space to swap to. OS/2 is generally not dependent on
- the nature of the application for using virtual memory, except for
- device drivers that may require fixed segments of physical RAM.
-
-
- 159. Error C2106 when Assigning a String Literal to a char Array
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 18-OCT-1988 ArticleIdent: Q36870
-
- A common error in C is to attempt to fill a character array, defined
- as char arrayname[somelength], with a string constant by use of the
- simple-assignment operator (i.e., the equal sign, = ). This error
- causes the compiler error "error C2106: '=' : left operand must be
- lvalue."
-
- Example 1, which does not compile and causes this error, follows
- immediately. An extended example (Example 2), which compiles and runs
- and demonstrates some concepts, is given below along with its output.
-
- The following is Example 1:
-
- /* This code gives compiler error C2106. */
- #include <string.h>
- char string1[10];
-
- void main(void);
- void main(void)
- {
- string1 = "String1";
- }
-
- As another way to fill an array, non-auto (i.e. global) char arrays
- and char pointers (starting with C Version 5.00) may be initialized
- when declared as in the following two lines:
-
- char string1[10] = "String1";
- char *string2 = "String2";
-
- The following is Example 2:
-
- /* This example demonstrates some string usage principles. */
- #include <stdio.h>
- #include <string.h>
- #include <malloc.h>
-
- char string1[40]; /* string1 is an array of char */
- char *string2; /* string2 is a pointer to char */
- /* Important: Know when to malloc space for string2. */
-
- void main(void);
- void main(void)
- {
- /* This shows the correct way to achieve the */
- /* assignment intended by string1 = "String1"; */
- strcpy(string1, "Contents of string1");
- printf("1:%s\n\n", string1);
-
- /* These two assignments show two ways to */
- /* use a char pointer with a string literal. */
- string2 = "Contents of string2"; /* point to the literal */
- printf("2:%s\n", string2);
- /* allocate memory for char *string2 to point at */
- string2 = (char *) malloc(sizeof(string1));
- strcpy(string2, "Contents of string2, again");
- printf("3:%s\n\n", string2);
- free(string2);
-
- /* This shows a failed attempt to fill a char */
- /* array by assignment through a char pointer. */
- string2 = string1;
- string2 = "Contents of string2, but not string1";
- printf("4:%s\n", string1);
- printf("5:%s\n\n", string2);
-
- /* This shows how correctly to use a pointer */
- /* to fill a char array with a string literal. */
- string2 = string1;
- strcpy(string2, "Contents of string2, and also string1");
- printf("6:%s\n", string1);
- printf("7:%s\n\n", string2);
- }
-
- The output of this example is as follows:
-
- 1:Contents of string1
-
- 2:Contents of string2
-
- 3:Contents of string2, again
-
- 4:Contents of string1
- 5:Contents of string2, but not string1
-
- 6:Contents of string2, and also string1
- 7:Contents of string2, and also string1
-
-
- 160. _Settexwindow() and Scrolling
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 21-DEC-1988 ArticleIdent: Q36947
-
- Problem:
-
- The _settextwindow() function specifies a window where the text output
- to the screen is displayed. When the text window is full, the
- uppermost line scrolls up and out of the window. This scrolling occurs
- in most cases, but not all. The _settextwindow function knows to
- scroll the text in the window if the current line being written to is
- the last line in the window and one of either the following situations
- occurs:
-
- 1. The string being printed ends with a carriage control
- character, '\n'.
-
- 2. The string wraps onto the next line. (In this case, the
- wrapping is enabled by a _wrapon(_GWRAPON) call.)
-
- The text in the window will not scroll if these conditions are not
- met. More than likely, the last line in the window will be
- over-written.
-
- This is expected behavior for the _settextwindow and related
- functions.
-
- The examples below assume that the text window is defined by the
- coordinates (1,1, 14,80).
-
- The following example causes the text window to scroll because the
- second _outtext call (which prints to the last line in the window)
- ends in a carriage return character, '\n':
-
- _settextposition (13,1) ; /* set cursor to 2nd to */
- /* last line in the window.*/
-
- _outtext ("This will appear on line 13\n") ;
- _outtext ("This will appear on the last line (14)\n") ;
- _outtext ("The text window has now scrolled.") ;
-
- The following example also scrolls because the text output on the
- final line in the window wraps around to the next line:
-
- _wrapon (_GWRAPON) ; /* enable wrapping of text.*/
- _settextposition (14,1) ; /* set cursor to last line.*/
- _outtext ("This will be forty characters in length..") ;
- _outtext ("This will wrap around the right window border") ;
-
- The example below will not scroll the text window. The second
- _outtext() will just over-write the first. It will not scroll because
- wrapping has been disabled, and there is no carriage control character
- to signal the window to scroll.
-
- The following example demonstrates this behavior:
-
- _wrapon (_GWRAPOFF) ; /* disable wrapping of text*/
- _settextposition (14,1) ; /* set cursor to last line.*/
- _outtext ("This will appear on the last line (line 14)...") ;
- _settextposition (14,1) ; /* set cursor to last line.*/
- _outtext ("This will over-write, not scroll.") ;
-
-
-
- 161. Warning C1015 May be Caused by Lack of Available File Handles
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 11-JAN-1990 ArticleIdent: Q36953
-
- Compiler error C1015, which is not documented in the text, is often
- caused by an error finding or opening an include file. This new error
- message is noted in the C Version 5.10 file ERRMSG.DOC.
-
- This error can occur if the INCLUDE environment variable has
- not been set correctly for your include file directory or the TMP
- variable is set to a Ram Disk.
-
- Especially under DOS, this error also can be generated by not having
- enough file handles available. (A file handle is an integer used by
- the operating system to keep track of every open file.) The number of
- file handles available to DOS can be increased from the default of
- eight to a number up to 20 (or higher with some OEM adaptations of
- MS-DOS versions later than Version 3.20) by placing the following line
- in CONFIG.SYS and rebooting your computer:
-
- FILES=20
-
- It has been reported that if you do not set files above the default
- of eight, error C1015 appears soon after compilation begins. Setting
- files to 20 corrects the problem.
-
- File handles will typically be used during compilation and linkage by
- the CL driver, the compiler passes, your C source code file, include
- files, the linker, libraries, and temporary files created by the
- compiler or linker.
-
- Closing a file makes its handle available to the operating system
- again, so the lack of available file handles refers to the number of
- files open at any one time.
-
-
- 162. C2086, C2061 on CFLOW.C when Language Extentions Not Enabled
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-DEC-1988 ArticleIdent: Q36955
-
- Compiling the sample program CFLOW.C with language extensions disables
- results in the following errors:
-
- cflow.c(4) : error C2086: 'size_t' : redefinition
- cflow.c(934) : error C2061: syntax error : identifier 'c'
-
- The Microsoft extensions to C can be disabled by compiling with
- the option /Za (enforce ANSI compatibility) or, when in QuickC,
- clearing the X from the Language Extensions check box in the Compile
- dialog box.
-
- The C2086 error occurs because both CFLOW.C and STDIO.H have the following:
-
- typedef unsigned int size_t;
-
- Redefinition of a typedef is a language extension. This information is
- stated in the "Microsoft C Optimizing Compiler User's Guide" on Page
- 100.
-
- The C2061 error occurs on the line
-
- static int near c;
-
- because the keyword "near" is an extension to C, and so is understood
- by the compiler to be the simple identifier being defined, leaving the
- now-surplus "c" to be flagged as syntactically incorrect. This
- information is documented in the user's guide on Page 99.
-
-
- 163. Warning C4067 Unexpected Characters Following 'directive'
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC S_ERROR
- Last Modified: 12-DEC-1988 ArticleIdent: Q36992
-
- The warning below is from Section D.1.3 (Page 340) of the "Microsoft
- QuickC Programmer's Guide" and Section E.3.3 (Page 269) of the
- "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
- 5.10.
-
- This message indicates potential problems but does not hinder
- compilation and linking. The number in parentheses at the end of a
- warning-message description gives the minimum warning level that must
- be set for the message to appear.
-
- The following is the warning:
-
- C4067 unexpected characters following 'directive' directive-
- newline expected
-
- Extra characters followed a preprocessor directive, as
- in the following example:
-
- #endif NO_EXT_KEYS
-
- This is accepted in Version 3.0, but not in Versions
- 4.0 and 5.0. Versions 4.0 and 5.0 require comment
- delimeters, such as the following:
-
- #endif /* NO_EXT_KEYS */
-
- As with Versions 4.00, 5.00, and 5.10 of the C optimizing compiler,
- QuickC Versions 1.00 and 1.01 do not accept the extra characters
- unless surrounded by comment delimeters.
-
-
- 164. Warning C4077 Unknown check_stack Option
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC S_ERROR
- Last Modified: 12-DEC-1988 ArticleIdent: Q37001
-
- The warning below is from Section D.1.3 (Page 349) of the "Microsoft
- QuickC Programmer's Guide" and Section E.3.3 (Page 278) of the
- "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
- 5.10.
-
- This message indicates potential problems but does not hinder
- compilation and linking. The number in parentheses at the end of a
- warning-message description gives the minimum warning level that must
- be set for the message to appear.
-
- C4077 unkown check_stack option
-
- An unknown option was given with the old form of the
- 'check_stack' pragma, as in the following example:
-
- #pragma check_stack yes
-
- In the old form of the check_stack pragma, the argument
- to the argument to the pragma must be empty, +, or -. (1)
-
- The following is an example of using the check_stack pragma:
-
- syntax Compiled with /Gs Action
- (Pointer Check)
-
- #pragma check_stack() yes Turns off Stack checking
- for routines that follow.
- #pragma check_stack() no Turns on Stack checking
- for routines that follow.
- #pragma check_stack(on) yes or no Turns on Stack checking
- for routines that follow.
- #pragma check_stack(off) yes or no Turns off Stack checking
- for routines that follow.
-
- Note: for earlier versions of Microsoft C, the check_stack pragma had
- a different format. check_stack+ was to enable stack checking and
- check_stack- was to disable stack checking. Although the Microsoft
- Optimizing compiler still accepts this format, its use is discouraged
- because it may not be supported in future versions.
-
- This information was taken from Page 98 of the C user's guide and
- Page 169 of the QuickC programmer's guide.
-
-
- 165. Warning C4086 Expected
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC S_ERROR
- Last Modified: 12-DEC-1988 ArticleIdent: Q37004
-
- The warning below is from Section D.1.3 (Page 340) of the "Microsoft
- QuickC Programmer's Guide" and Section E.3.3 (Page 269) of the
- "Microsoft C Optimizing Compiler User's Guide" for Version 5.00 and
- 5.10.
-
- This message indicates potential problems but does not hinder
- compilation and linking. The number in parentheses at the end of a
- warning-message description gives the minimum warning level that must
- be set for the message to appear.
-
- The following is the warning:
-
- C4086 expected [1|2|4]
-
- An invalid argument was given for a "pack" pragma, as
- in the following example:
-
- #pragma pack (yes)
-
- The "pack" pragma is used when you want to specify packing other than
- the packing specified on the command line for particular structures.
- The /Zp option and the "pack" pragma control how structure data are
- packed into memory.
-
- For detailed information on the /Zp option and the "pack" pragma, see
- Page 210 of the QuickC programmer's guide and Page 100 of the C user's
- guide.
-
-
- 166. How to Determine the Amount of Available DOS Memory
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-DEC-1988 ArticleIdent: Q37022
-
- Question:
-
- Is there a C run-time function that I can use to determine how much
- RAM is available under DOS?
-
- Response:
-
- No function exists that specifically performs this task. Functions
- "_freect" or "_memavl" only return available memory for dynamic
- allocation in the near heap. The near heap is located above the stack
- within the 64K byte or smaller default data segment called DGROUP.
- Function _memavl indicates the amount of near space that never has
- been allocated, whereas _freect allows you to detect what has been
- freed.
-
- However, you may use the function "_dos_allocmem" defined below
- to determine the amount of far heap above the default data segment:
-
- #include <dos.h>
- unsigned _dos_allocmem(size, segment) ;
- unsigned size ;
- unsigned *segment ;
-
- If the attempted memory allocation is NOT successful, _dos_allocmem
- puts the maximum possible free memory size (in 16-byte paragraphs)
- in the word pointed to by "segment". If you request to allocate
- 0xFFFF paragraphs of memory (which will fail in any case), you should
- be able to find out the amount of available memory. (DOS function
- call 48h performs the same task.)
-
- Note: the value returned to *segment is in paragraphs too. If other
- memory allocation functions are going to use this value, it should be
- converted to bytes.
-
- Refer to the "Microsoft C Version 5.10 Optimizing Compiler Run-time
- Library Reference" for specific information on using _dos_allocmem.
-
-
- 167. Link Error No Stack Segment after Using Windows SDK Install
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 12-DEC-1988 ArticleIdent: Q37023
-
- If a C program generates linker errors stating that no stack segment
- exists and that there are several unresolved externals references made
- by the startup code, the program may have been linked with libraries
- modified by the Windows SDK Install program.
-
- The Windows install program modifies C libraries, upon your request,
- so that when linking Window applications it can look for the standard
- library names with no other linker options specified. A more detailed
- explanation can be found in the README.WRI on the Development
- Utilities Disk 1 that comes with Windows SDK Version 2.00.
-
- The install program retains the original C library. The library will
- have its same name with a "C" appended. For instance, SLIBCE.LIB will
- be copied to SLIBCEC.LIB. When you link with this library, make sure
- to use the /NOD option and specify the library by name.
-
-
- 168. Setup Won't Accept Drive on Novell Network
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 18-NOV-1988 ArticleIdent: Q37198
-
- Setup on Novell network Versions 2.0x gives "cannot create subdirectory
- G:\(etc.)" when trying to specify a destination for bound executables
- (i.e., the first question about paths that the setup program asks).
-
- It will not install on a network because it is illegal to do so
- without a special licensing agreement with Microsoft. If you have this
- agreement you receive a setup program that installs on the network.
-
- This scenario should not be confused with the situation of someone
- installing Microsoft software on their immediate machine and using
- network drives to store files they have created. This process is
- allowed.
-
-
- 169. Coordinates Incorrect in Run-Time Library Manual
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 18-NOV-1988 ArticleIdent: Q37199
-
- Page 51 of the "Microsoft C Run-Time Library Manual" states that the
- range of physical coordinates is (0,0) to (640, 350). This information
- is incorrect. The correct range of physical coordinates is (0,0) to
- (639, 349).
-
-
- 170. Redirection with spawn() or exec()
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# S880925-1 s_quickc
- Last Modified: 18-NOV-1988 ArticleIdent: Q37200
-
- Question:
-
- There is a problem when you use spawnvp or spawnlp to invoke the
- SORT.EXE that usually comes with DOS. When you run the program, it
- seems that SORT.EXE starts, but then it does nothing. The behavior is
- similar to starting SORT.EXE from the DOS prompt without any arguments.
-
- How do I do any redirection with spawn() or exec()?
-
- Response::
-
- Use the system() function. For example, you can make a run SORT.EXE
- by executing the following:
-
- system("SORT <INFILE >OUTFILE");
-
- This process has the minor disadvantage of taking up extra memory for
- another copy of COMMAND.COM. This behavior shouldn't be a problem
- unless you're short on available memory. If you do not have very much
- memory, the following information may help.
-
- Because COMMAND.COM, and NOT the EXEC loader, handles redirection,
- this behavior is expected. Child processes inherit the handles of
- their parents; therefore, to redirect the input and output of the
- child, change the definitions of STDIN and STDOUT in the
- parent process. The proper way to redirect input for a filter is
- described starting on Page 441 of the "MS-DOS Encyclopedia," along with
- a complete MASM example.
-
- Note: the dup and dup2 functions in the C Version 5.10 run-time
- library are the same as the INT 21h functions 45h and 46h,
- respectively.
-
- There also are partial examples of this technique on Page 230 of the
- "Microsoft C 5.1 Run-Time Library Reference" manual and on page 353 of
- "Advanced MS-DOS Programming" (by Duncan, published by Microsoft
- Press).
-
- It is possible to use freopen() to redefine STDIN and STDOUT; however,
- doing so causes any redirection that may have been performed on the
- parent process to be lost.
-
-
- 171. System Memory Allocation Error after Using halloc or malloc
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# S880914-27
- Last Modified: 18-NOV-1988 ArticleIdent: Q37201
-
- After running a program you have created that uses malloc or
- halloc functions, DOS may print the following message:
-
- Memory Allocation Error
- Cannot Load COMMAND.COM.
-
- You are able to allocate, use, write, read, and free memory, but when
- your program finishes, you receive the error. If you remove halloc()
- from your program, it terminates normally.
-
- Your program is probably writing outside of a memory block you
- allocated using halloc or malloc. DOS maintains information about
- memory usage in blocks immediately preceding the area you're given.
- This error is usually are result of overwriting these information
- blocks. The solution is to find out where you're overwriting DOS's
- memory and avoid doing it.
-
- Note: this error can also be the result of writing PAST the end of a
- block because you could corrupt the list entry for the NEXT block.
-
- You can determine where the overwrite occurs by using CodeView to set
- a tracepoint on the space after the allocated block. If you don't have
- enough memory to run CodeView, you can narrow down the problem by
- using a pointer to check those bytes at selected points in your
- program.
-
-
- 172. Operator sizeof Returns Type size_t, Defined as unsigned int
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 21-NOV-1988 ArticleIdent: Q37205
-
- The sizeof operator returns a value that is of type size_t. The
- definition of size_t is implementation-dependent, according to the
- ANSI standard. In Microsoft C, the size_t type is defined in STDEF.H
- and in MALLOC.H as an unsigned int. This information is documented in
- the "Microsoft C Optimizing Compiler Run-Time Library Reference" on
- Pages 38 and 98.
-
- To use sizeof on huge items, which can be larger than 64K, you will
- need to use a typecast on the sizeof expression as follows:
-
- char huge a[95000];
- unsigned long sizea;
-
- sizea = (unsigned long) sizeof(a);
-
- Note: the Index entry for "size_t type" lists Pages 38 and 97; it
- should say Pages 38 and 98.
-
- The "Microsoft C Optimizing Compiler Language Reference" manual
- describes the sizeof operator on Pages 120-121, section 5.3.4, but
- does not give the return type.
-
-
- 173. No Such Thing as a static auto Variable.
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC docerr
- Last Modified: 21-NOV-1988 ArticleIdent: Q37219
-
- Page 86 (section 4.6.2, third paragraph) of the "Microsoft QuickC and
- Optimizing C Language Reference" states "A static auto variable can
- be initialized..."
-
- However, the storage classes static and auto are mutually exclusive --
- there is no "static auto" class. The text should read, "A static OR
- auto variable can be initialized..."
-
-
- 174. Domain Error
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc h_fortran s_pascal
- Last Modified: 21-NOV-1988 ArticleIdent: Q37223
-
- A domain error occurs when you pass an invalid value to a function.
- "Domain" refers to arguments to a function; "range" refers to the
- return values.
-
- For example, if you pass a -1 to sqrt(), you receive the math error
- "M6201 Domain Error" because -1 is not in the domain of the square
- root function (i.e., you can't take the square root of -1).
-
- This error also can occur if an incorrect type is passed to the
- function. (For example, passing an int to a function that expects
- double.) You should receive warnings in these cases if you have
- declared proper function prototypes (perhaps by including the math.h
- file).
-
- Make sure the value you pass to a function is of the proper type and
- the value is within that function's domain.
-
-
- 175. Why "CDECL" Is Everywhere in Your Include Files
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 26-OCT-1988 ArticleIdent: Q37233
-
- Question:
-
- When I look at the include files provided with the Microsoft C
- compiler, I see all the function prototypes prefixed with "_CDECL".
- Why?
-
- Response:
-
- When Microsoft extensions are enabled, the manifest constant "_CDECL"
- takes the value "cdecl", which says that the associated function takes
- standard C calling conventions. (C calling conventions are used by
- default except when the /Gc switch is specified during compilation.
- The /Gc switch tells the compiler to default to FORTRAN/Pascal-style
- function calling and naming conventions.)
-
- Thus, the _CDECL's on the function prototypes tell the compiler to
- generate the runtime library function calls using C calling and naming
- conventions always--even if the /Gc option is used.
-
- For more information, see the "Mixed Language Programming Guide" and
- the "Microsoft C Language Reference."
-
-
- 176. Loadtime DLL Initialization for C 5.10
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | softlib CRTDLL.ARC S12104.EXE
- Last Modified: 21-SEP-1989 ArticleIdent: Q37355
-
- Question:
-
- How do I implement load-time DLL initialization without losing C
- run-time support for my DLL?
-
- Response:
-
- Single-Threaded DLLs (that use LLIBCDLL.LIB)
-
- There is an object module DLLINIT.OBJ that must be linked with your
- routine. You must make an explicit call to C_INIT() to bring in
- the C run-time startup code. If you are going to use DosLoadModule()
- and DosFreeModule() to bring in and remove your DLL, then you must also
- link in DLLTERM.OBJ. No explicit calls are necessary to use this
- routine.
-
- Multi-Threaded DLLs
-
- There is an object module CRTDLL_I.OBJ that replaces the CRTDLL.OBJ
- that comes with the C package. You should use CRTDLL_I.OBJ in the
- exact same manner you would use CRTDLL.OBJ. You must also make a
- reference to C_INIT() in your initialization routine. The prototype is
- as follows:
-
- void far
- pascal C_INIT();.
-
- All three object modules are in the Software Library archive file
- CRTDLL.ARC. This file can be found in the Software Library by
- searching on the filename CRTDLL.ARC, the Q number of this article, or
- S12104.
-
-
- 177. "pascal" Attribute for Multi-Thread Functions Returning Double
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 22-NOV-1988 ArticleIdent: Q37459
-
- Although it is not documented, an important requirement for returning
- floating-point values from functions in a multi-thread environment is
- defining and prototyping functions with the "pascal" function
- attribute as we have done for all functions prototyped to return a
- double in \include\mt\math.h.
-
- When you use the pascal attribute on floating-point functions, the
- floating-point return value is placed on the calling thread's stack,
- providing each thread with its own return value as desired.
-
- When using the default of the C function call/return convention
- instead of pascal, we use a global variable __fac (floating-point
- accumulator) for returning floating-point values. For multi-thread
- applications or DLL's using CRTLIB.DLL, the global variable __fac
- could be unintentionally modified by another thread, so it is not
- contained in CRTEXE.OBJ, CRTDLL.OBJ, or CRTDLL.LIB. Consequently,
- references to __fac will be unresolved at link time.
-
-
- 178. Scan Codes for IBM and Compatible Keyboards
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 8-NOV-1988 ArticleIdent: Q37617
-
- Below are the scan codes for IBM and compatible keyboards. All scan
- codes are in hexadecimal. See the "IBM PC Technical Reference" for more
- details.
-
- The scan codes are as follows:
-
- 83 key (PC,PC/XT) 84 key (PC/AT) 101/102 key (PC/AT PS/2)
-
- Key Scan Code Key Scan Code Key Scan Code
-
- ESC 01 KP ESC 01 ESC 01
- 1 02 1 02 1 02
- 2 03 2 03 2 03
- 3 04 3 04 3 04
- 4 05 4 05 4 05
- 5 06 5 06 5 06
- 6 07 6 07 6 07
- 7 08 7 08 7 08
- 8 09 8 09 8 09
- 9 0A 9 0A 9 0A
- 0 0B 0 0B 0 0B
- - 0C - 0C - 0C
- = 0D = 0D = 0D
- BACKSPACE 0E BACKSPACE 0E BACKSPACE 0E
- TAB 0F TAB 0F TAB 0F
- Q 10 Q 10 Q 10
- W 11 W 11 W 11
- E 12 E 12 E 12
- R 13 R 13 R 13
- T 14 T 14 T 14
- Y 15 Y 15 Y 15
- U 16 U 16 U 16
- I 17 I 17 I 17
- O 18 O 18 O 18
- P 19 P 19 P 19
- [ 1A [ 1A [ 1A
- ] 1B ] 1B ] 1B
- RETURN 1C RETURN 1C RETURN 1C
- CTRL 1D CTRL 1D L CTRL 1D
- A 1E A 1E A 1E
- S 1F S 1F S 1F
- D 20 D 20 D 20
- F 21 F 21 F 21
- G 22 G 22 G 22
- H 23 H 23 H 23
- J 24 J 24 J 24
- K 25 K 25 K 25
- L 26 L 26 L 26
- ; 27 ; 27 ; 27
- ' 28 ' 28 ' 28
- ` 29 ESC 29 ` 29
- L SHIFT 2A L SHIFT 2A L SHIFT 2A
- Z 2C Z 2C Z 2C
- X 2D X 2D X 2D
- C 2E C 2E C 2E
- V 2F V 2F V 2F
- B 30 B 30 B 30
- N 31 N 31 N 31
- M 32 M 32 M 32
- , 33 , 33 , 33
- . 34 . 34 . 34
- / 35 / 35 / 35
- R SHIFT 36 R SHIFT 36 R SHIFT 36
- PRT SCR 37 PRT SCR 37 KP * 37
- ALT 38 ALT 38 ALT 38
- Space 39 Space 39 Space 39
- CAPS LOCK 3A CAPS LOCK 3A CAPS LOCK 3A
- F1 3B F1 3B F1 3B
- F2 3C F2 3C F2 3C
- F3 3D F3 3D F3 3D
- F4 3E F4 3E F4 3E
- F5 3F F5 3F F5 3F
- F6 40 F6 40 F6 40
- F7 41 F7 41 F7 41
- F8 42 F8 42 F8 42
- F9 43 F9 43 F9 43
- F10 44 F10 44 F10 44
- NUM LOCK 45 NUM LOCK 45 NUM LOCK 45
- SCROLL LOCK 46 SCROLL LOCK 46 SCROLL LOCK 46
- KP 7 47 KP 7 47 KP 7 47
- KP 8 48 KP 8 48 KP 8 48
- KP 9 49 KP 9 49 KP 9 49
- KP - 4A KP - 4A KP - 4A
- KP 4 4B KP 4 4B KP 4 4B
- KP 5 4C KP 5 4C KP 5 4C
- KP 6 4D KP 6 4D KP 6 4D
- KP + 4E KP + 4E KP + 4E
- KP 1 4F KP 1 4F KP 1 4F
- KP 2 50 KP 2 50 KP 2 50
- KP 3 51 KP 3 51 KP 3 51
- KP 0 52 KP 0 52 KP 0 52
- KP . 53 KP . 53 KP . 53
- Sys Req 54 F11 57
- F12 58
- R CTRL E0 10
- KP / E0 36
- R ALT E0 38
- RIGHT ARROW E0 40
- HOME E0 47
- UP ARROW E0 48
- PAGE UP E0 49
- LEFT ARROW E0 4B
- END E0 4F
- DOWN ARROW E0 50
- PAGE DOWN E0 51
- INSERT E0 52
- DELETE E0 53
- KP ENTER E0 1C
- PAUSE E1 10 45
- PRINT SCR E0 2A E037
-
- (Source : Norton's Guide to the IBM PC and PS/2)
-
-
- 179. Backslash Character Interpreted In /Ss and /St Options
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 14-NOV-1988 ArticleIdent: Q37619
-
- When specifying the /St and /Ss for titles and subtitles in your
- source listing, you must use double-backslash (\\) marks if you want
- your title or subtitle to contain a single backslash. If you do not
- include the second backslash, the next character will be interpreted
- as an escape character.
-
-
- 180. EOH Is Not a Defined Constant for getch or getche
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 14-NOV-1988 ArticleIdent: Q37620
-
- The "Microsoft C 5.10 Optimizing Compiler Run-Time Library Reference"
- manual for the functions getch and getche states that when reading a
- function or cursor key, the first call to either function will return
- 0 or EOH. This is misleading; EOH appears to be a constant that is
- defined in an include file, though it is not. These functions actually
- return 0 or 0xE0. The 0x convention is followed throughout the manual
- for hexadecimal numbers, except in this case.
-
-
- 181. Amount of Disk Space Needed for Minimum C 5.10 Setup for DOS
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 14-NOV-1988 ArticleIdent: Q37621
-
- Question:
-
- How much disk space will I need to set up the Microsoft C Version 5.10
- Compiler in a minimum configuration for DOS?
-
- Response:
-
- In a minimum configuration, you will need to have about 1.45 megabytes
- of disk space available. This includes the small, medium, and graphics
- libraries and all include files and passes of the compiler.
-
- This does not include any user source code, temporary files, the
- Microsoft editor, CodeView or any utilities.
-
- Although you will be able to use the compiler in this minimum setup,
- we recommend that you have about 2.5 megabytes of disk space and do a
- complete setup.
-
-
- 182. Using Function Name Without "()" Produces No Code
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 17-JUL-1990 ArticleIdent: Q50234
-
- When a function name declared in your program is used without
- parentheses, the compiler does not produce any code. The compiler does
- not produce error messages or warnings as long as the function has
- been prototyped. This occurs regardless of whether or not the function
- takes parameters because the compiler calculates the function address,
- but because the function call operator "()" is not present, no call is
- made. This result is similar to the following:
-
- int a;
-
- a; /* no code generated here either */
-
- Code Example
- ------------
-
- void foo(int a, int b);
- void main(void)
- {
- foo; /* Using foo without function call operator () */
- }
-
- The above code compiles and links correctly without errors or warnings
- but produces no code in reference to foo(). For this to work
- correctly, add the function call operator "()".
-
-
- 183. Using a Logical AND Operation && and OR Operation ||
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 16-NOV-1988 ArticleIdent: Q37624
-
- Question:
-
- Why does the statement for the integers a, b, c, and d result in
- values of 1 for a, 2 for b, but 0 for c and d in the following
- example?
-
- a = (b = 2) || (c = 3) && (d = 4)
-
- I thought that the logical AND operation && would be performed before
- the logical OR operation ||, so that c and d would be assigned 3 and
- 4. The "Microsoft C 5.1 Optimizing Compiler Reference," Page 137
- states "Expressions with higher-precedence operators are evaluated
- first."
-
- Response:
-
- While it's true that logical AND has a higher precedence than logical
- OR, precedence in C means how operands are grouped, not necessarily
- the order in which they are evaluated. The documentation is incorrect
- on this point.
-
- The following
-
- lvalue = operand1 || operand2 && operand3;
-
- will be grouped as follows:
-
- lvalue = operand1 || (operand2 && operand3);
-
- However, this does not mean (operand2 && operand3) will be evaluated
- first in the above statement. In fact, this statement is a logical OR
- expression with two operands: operand1 and (operand2 && aoperand3).
- Operands are defined as an entity on which an operator acts; in this
- case the logical OR operator || acts on operand1 and (operand2 &&
- operand3). Logical OR expressions are evaluated in left-to-right
- order, so operand1 will be evaluated first.
-
- As noted in the proposed ANSI C standard, section 3.3.14 of both the
- November 1987 and May 1988 drafts for the logical OR operator, "If the
- first operand compares unequal to 0, the second operand is not
- evaluated." In this case, if operand1 != 0, (operand2 && operand3)
- will not be evaluated. This is the behavior of both the C Version 5.10
- and QuickC Version 1.01 compilers. This behavior has been a feature
- of C since the original K & R, and is so handy that many modern
- Pascal compilers now provide this functionality.
-
- The following example demonstrates this behavior:
-
- #include <stdio.h>
- int a,b,c,d;
- main() {
- a = (b = 2) || (c = 3) && (d = 4);
- printf("a = %d, b = %d, c = %d, d = %d\n",a,b,c,d);
- }
-
- The following is an example of output resulting from a program
-
- a = 1, b = 2, c = 0, d = 0
-
- Because (b = 2) is not 0, no further evaluations are performed, and c
- and d are not assigned 3 and 4. If the intent is to assign values to
- variables, then separate assignment statements should be made.
-
- As noted in "The C Programming Language", second edition by Kernighan
- and Ritchie, Page 54, "The moral is that writing code that depends on
- the order of evaluation is a bad programming practice in any
- language."
-
-
- 184. MKTEMP() Function Example Clarification
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 14-NOV-1988 ArticleIdent: Q37625
-
- The mktemp() function example in the "Microsoft C Optimizing Compiler
- Run-Time Library Reference" manual is correct. However, it is not
- clear that the following code statements are required:
-
- strcpy (names[i], template) ;
- result = mktemp(names[i]) ;
-
- These statements ensure that mktemp() is given the original template
- for each successive call. In the example, the template is defined
- as "fnXXXXXX". The first call to mktemp() will produce a file
- name of "fn000001". If you submit such a filename instead of
- the template, "fnXXXXXX", mktemp() will fail because it is unable
- to generate another unique name.
-
- The following example demonstrates this behavior:
-
- /*****************************************************************/
- /* This is the mktemp example in the "Microsoft QuickC Run-Time */
- /* Library Reference" manual on Page 433. The example copies the */
- /* template to temporary storage so as not to destroy the */
- /* original template. */
- /*****************************************************************/
-
- #include <io.h>
- #include <stdio.h>
-
- char *template = "fnXXXXXX";
- char *result;
- char names[5][9];
-
- main()
- {
- int i;
-
- for (i=0;i<5;i++) {
- strcpy(names[i], template); /* Save the template... */
- result = mktemp(template); /* Get another file name. */
- if (result == NULL)
- printf("Problem creating the tempfile");
- else{
- printf("the unique file name is %s\n",result);
- fopen(result, "w");
- }
- }
- )
-
- Without the two commented lines in this example, this code fragment
- generates one unique name, then terminates as the pointer "result"
- becomes NULL because mktemp() cannot generate another unique name with
- the template given.
-
-
- 185. _malloc Should Be malloc in Reference Manual
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 8-NOV-1988 ArticleIdent: Q37626
-
- The "Microsoft C Optimizing Compiler Run-Time Library Reference"
- manual has a documentation error on Page 410, in the "malloc,
- _fmalloc, _nmalloc" entry. The third paragraph in the Return Value
- section states the following:
-
- The _malloc and _nmalloc functions...
-
- It should state the following:
-
- The malloc and _nmalloc functions...
-
-
- 186. How errno Is Handled in Multi-Threaded Programs
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | docerr
- Last Modified: 16-NOV-1988 ArticleIdent: Q37633
-
- The "Microsoft C for MS OS/2 and MS-DOS Operating Systems: Version 5.1
- Update" manual does not explain how errno is handled in multi-threaded
- programs. The following explains this information.
-
- In single-threaded programs, errno is a function returning an int, as
- can be observed by looking at the header file errno.h in the default
- include subdirectory. In the multi-thread case, errno is a function
- returning a pointer representing an array (as usual). This array has
- 32 entries, one for each thread. OS/2 API routine calls are used to
- manage the assignation of threads to entries in this array. For the
- multi-thread libraries, errno is defined as follows:
-
- #define errno *(__errno())
-
- where __errno is
-
- int far * far __errno( void );
-
- so "errno = EDOMAIN;" becomes "*(__errno()) = EDOMAIN;".
-
- You can determine the behavior at compile time because errno will be
- defined in the multi-thread case, i.e., "#ifdef errno".
-
-
- 187. Different OS/2 Libraries: DOSCALLS.LIB OS2.LIB API.LIB
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-JAN-1989 ArticleIdent: Q37641
-
- Question:
-
- What are the differences between DOSCALLS.LIB, OS2.LIB, and API.LIB?
-
- Response:
-
- DOSCALLS.LIB has the OS/2 Version 1.00 systems calls in it.
-
- OS2.LIB is a superset of DOSCALLS.LIB, this library came with the
- OS/2 SDK not with the retail version of C 5.1. It has the OS/2
- Version 1.10 systems calls in it (PM calls have been added to the
- OS/2 Version 1.00 calls).
-
- API.LIB is the library used for programs that are going to be bound to
- run in both OS/2 and DOS. They are the FAPI ( Family API) routines.
-
- You can use OS2.LIB in place of DOSCALLS.LIB because it contains all
- of the routines. Only use API.LIB if you are binding.
-
-
- 188. EMULATOR_TEXT and EMULATOR_DATA Segments in Small Model
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC
- Last Modified: 8-NOV-1988 ArticleIdent: Q37664
-
- Small-model C programs compiled with the floating-point emulator
- library (/FPi or /FPc option) may produce two segments of code and
- data each. If there are floating-point operations in your program, the
- compiler will generate these extra segments. The map file shows these
- segments as EMULATOR_TEXT and EMULATOR_DATA.
-
- EMULATOR_TEXT is the code segment for the emulator. In some cases,
- small-model programs can have two code segments. Because the code in
- the emulator only is accessed through far calls and interrupts, this
- is not a problem. Both EMULATOR_TEXT and EMULATOR_DATA are in separate
- segments from DGROUP and _TEXT in all memory models.
-
-
- 189. cl /Fs Filename Fails to Generate Symbol Table on Error
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 8-NOV-1988 ArticleIdent: Q37665
-
- When compiling with the /Fs option to produce a source listing, it
- will provide you with tables for global and local symbols. However, if
- the compiler generates error messages, then a list file will not
- contain the symbol tables.
-
-
- 190. Additional Causes of Error C2152
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC docerr
- Last Modified: 14-NOV-1988 ArticleIdent: Q37666
-
- Page 267 of the "Microsoft C 5.1 Optimizing Compiler User's Guide"
- (Page 337 of the "Microsoft QuickC Programmer's Guide") states that
- error C2152 (pointers to functions with different attributes) is
- caused when the following occurs:
-
- An attempt was made to assign a pointer to a function
- declared with one calling convention (cdecl, fortran, or
- pascal) to a pointer to a function declared with a
- different calling convention.
-
- This is correct, but incomplete. Additional causes are mixing near
- and far function pointers and mixing interrupt and non-interrupt
- function pointers.
-
-
- 191. Error C2170 Identifier : Intrinsic Not Declared as a Function
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error docerr
- Last Modified: 14-NOV-1988 ArticleIdent: Q37719
-
- The error below is from "Compilation-Error Messages" in the
- "Microsoft C Optimizing Compiler User's Guide," Section E.3.2, Page
- 268. It is not documented in either the "Microsoft QuickC Compiler
- Programmer's Guide," or in the README.DOC file, for the Microsoft
- QuickC Compiler Versions 1.00 and 1.01.
-
- The following is the error:
-
- C2170 identifier : intrinsic not declared as a function
-
- You tried to use the intrinsic pragma for an item other
- than a function, or for a function that does not have an
- intrinsic form. (The section titled "Generating Intrinsic
- Functions" in Section 3.3.15 lists the functions that have
- intrinsic forms.)
-
- The section reference given in the error explanation is wrong. It is
- found in Section 3.3.13.1 beginning on Page 93 of the "Microsoft C
- Optimizing Compiler User's Guide."
-
- When the compiler encounters any of the errors listed in this section,
- it continues parsing the program (if possible) and outputs additional
- error messages. However, no object file is produced.
-
-
- 192. Error C2172 Function : Actual Is Not a Pointer...
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q37721
-
- The following error is from "Compilation-Error Messages" in the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.1.2, Page
- 339, and from "Compiler and Run-Time Errors -- New Messages" in the
- Microsoft C Optimizing Compiler file ERRMSG.DOC, on Version 5.00's
- Setup Disk and on Version 5.10's Compiler Disk 1, but not in the
- "Microsoft C Optimizing Compiler User's Guide" for those versions:
-
- C2172 function : actual is not a pointer, parameter number
-
- An attempt was made to pass a non-pointer argument to a
- function that expected a pointer. The given number
- indicates which argument was in error.
-
- When the compiler encounters any of the errors listed in this section,
- it continues parsing the program (if possible) and outputs additional
- error messages. However, no object file is produced.
-
-
- 193. Error C2174 Function : Actual Has Type Void : Parameter...
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q37723
-
- The following error is from "Compilation-Error Messages" in the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.1.2, Page
- 340, and from "Compiler and Run-Time Errors -- New Messages" in the
- Microsoft C Optimizing Compiler file ERRMSG.DOC, on Version 5.00's
- Setup Disk and on Version 5.10's Compiler Disk 1, but not in the
- "Microsoft C Optimizing Compiler User's Guide" for those versions:
-
- C2174 function : actual has type void : parameter number,
- parameter list number
-
- An attempt was made to pass a void argument to a function.
- Formal parameters and arguments to functions cannot have
- type void; however, they can have type void * (pointer
- to void). This error occurs in calls that return a pointer
- to a function. The first number indicates which argument
- was in error; the second number indicates which argument
- list contained the invalid argument.
-
- When the compiler encounters any of the errors listed in this section,
- it continues parsing the program (if possible) and outputs additional
- error messages. However, no object file is produced.
-
-
- 194. Error C2173 Function : Actual Is Not a Pointer...
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q37724
-
- The following error is from "Compilation-Error Messages" in the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.1.2, Page
- 339, and from "Compiler and Run-Time Errors -- New Messages" in the
- Microsoft C Optimizing Compiler file ERRMSG.DOC, on Version 5.00's
- Setup Disk and on Version 5.10's Compiler Disk 1, but not in the
- "Microsoft C Optimizing Compiler User's Guide" for those versions.
-
- C2173 function : actual is not a pointer : parameter number :
- parameterlist number
-
- An attempt was made to pass a non-pointer argument to a
- function that expected a pointer. This error occurs in
- calls that return a pointer to a function. The first
- number indicates which argument was in error; the second
- number indicates which argument list contained the invalid
- argument.
-
- When the compiler encounters any of the errors listed in this section,
- it continues parsing the program (if possible) and outputs additional
- error messages. However, no object file is produced.
-
-
- 195. Error C2143 Syntax Error : Missing 'token1' before 'token2'
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q37726
-
- The following error is from "Compilation-Error Messages" in the
- "Microsoft C Optimizing Compiler User's Guide," Section E.3.2, Page
- 265, and in the "Microsoft QuickC Compiler Programmer's Guide,"
- Section D.1.2, Page 336:
-
- C2143 syntax error : missing 'token1' before 'token2'
-
- The compiler expected token1 to appear before token2. This
- message may appear if a required closing brace (}), right
- parenthesis ()), or semicolon (;) is missing.
-
- When the compiler encounters any of the errors listed in this section,
- it continues parsing the program (if possible) and outputs additional
- error messages. However, no object file is produced.
-
- This error can occur when a semicolon (;) is missing at the end of a
- function prototype. The following program demonstrates this:
-
- void foo(void)
- void main(void)
- {
- }
-
- When this code is compiled, the following errors occur:
-
- error C2085: 'main' : not in formal parameter list
- error C2143: syntax error : missing ';' before '{'
-
- With no semicolon to mark the end of the prototype, the compiler
- interprets the prototype as the start of a function definition, and
- the next line to follow the prototype as if it were the first
- declaration within a function definition.
-
-
- 196. Error C2152 Identifier : Pointers to Functions...
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 14-NOV-1988 ArticleIdent: Q37727
-
- The following error is from "Compilation-Error Messages" in the
- "Microsoft C Optimizing Compiler User's Guide," Section E.3.2, Page
- 267, and in the "Microsoft QuickC Compiler Programmer's Guide,"
- Section D.1.2, Page 337:
-
- C2152 identifier : pointers to functions with different
- attributes
-
- An attempt was made to assign a pointer to a function
- declared with one calling convention (cdecl, fortran, or
- pascal) to a pointer to a function declared with a
- different calling convention.
-
- When the compiler encounters any of the errors listed in this section,
- it continues parsing the program (if possible) and outputs additional
- error messages. However, no object file is produced.
-
- Additional causes for this error include mixing near and far function
- pointers and mixing interrupt and non-interrupt function pointers.
-
-
- 197. Share Problems Documentation Error for open
-
- Product Version(s): 5.00 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 14-NOV-1988 ArticleIdent: Q37758
-
- The important note on Page 446 of the "Microsoft Optimizing 5.1
- Compiler Run-Time Library Reference" manual has an error in the second
- possible work around described in the second paragraph of the note.
-
- "Another work around is to open the file with pmode set to S_IREAD and
- omode..." is incorrect. The word omode should be replaced with the
- word oflag.
-
-
- 198. Emulator Math Operations in My DLL that Uses LLIBCDLL
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 14-NOV-1988 ArticleIdent: Q37778
-
- Question:
-
- I am using LLIBCDLL.LIB for my DLL. This library is supposed to use
- the alternate math package; however, when I compile and link, it
- appears to get emulator instructions in the code and my DLL does not
- act correctly. Where are these emulator instructions coming from, and
- how do I get rid of them?
-
- Response:
-
- Most likely the problem is that you are not using the /FPa switch on
- the compile line. You need this switch or the compiler assumes the
- emulator math package (default) and puts emulator math commands in
- your code. When this emulator math code is linked with LLIBCDLL.LIB,
- which uses alternate math, it will not work correctly.
-
-
- 199. Reading the ESC Key from the Keyboard with _gets
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 15-NOV-1988 ArticleIdent: Q38023
-
- When the ESC key is pressed when entering a keyboard string to be read
- with the run-time library function _gets, it clears the keyboard
- buffer, and the only characters that are read by the _gets function
- are those pressed after the ESC key.
-
- This is a DOS command line feature. The _gets function does not
- receive the input of the command line until the ENTER key is pressed.
- Pressing the ESC key clears the keyboard buffer. If you need to accept
- the ESC key stroke, use the _getc function.
-
-
- 200. A Case where BUFF
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-NOV-1988 ArticleIdent: Q38024
-
- When the variable buff has been declared in an assembly-language
- program, such as the following
-
- .data
- public buff
- _buff db 200 dup (0xab)
- .data ends
-
- there is a difference between the two following C declarations:
-
- extern unsigned char buff[];
-
- extern unsigned *buff;
-
- The difference is that the first declaration says that there
- is a block of memory that is named buff; the second says
- that there is something called buff that is a pointer.
-
- This difference can be seen by referencing buff as follows:
-
- buff[x]
-
- If buff is declared as an array, the referencing is correct.
-
- However, if buff is declared as a pointer, the referencing is
- incorrect. The data pointed to by buff (ab in this example) is
- translated into a memory address, then x bytes is added to it
- generating an incorrect reference.
-
-
- 201. Signed char Type Converted to int Type at Function Call
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-NOV-1988 ArticleIdent: Q38025
-
- Question :
-
- Any char value equal to or greater than 0x80 is printed with 0xff
- preceding it when I do the following:
-
- 1. Declare an array of char and initialize it with hexadecimals.
-
- 2. Later in the program, use printf to display the values of the
- array element.
-
- 3. Use "%2x" as format string. (See sample program below.)
-
- Why does this behavior occur?
-
- Response:
-
- Use "unsigned char" to declare the array "bit", or use the /J compiler
- option to change the char type from its default of signed char to
- unsigned char.
-
- This is not a problem of Microsoft C Compiler. In the sample program
- below, the element of array "bits" has char type, which is a signed
- type in the Microsoft C compiler. In C when a variable is used as an
- actual argument in a function call, usual unary data type conversion is
- automatically performed before the argument is passed to the function.
-
- In particular, signed char type is converted to int type using sign
- extension (see the "Microsoft C Optimizing Compiler Language
- Reference" manual for data conversion rules.) Because signed char type
- can represent values from -128 to 127 (in our compiler -128 is not
- defined), and a negative value is represented in two's complement form,
- any hexadecimal number greater than 0x80, which is a negative value in
- signed char type, will be converted to signed int type in
- corresponding two's complement form.
-
- For example, 0x80 (-128) is converted to 0xff80; 0x81 (-127) is
- converted to 0xff81.
-
- When using "printf" with unsigned hexadecimal integer control
- character "%x", the values are displayed in its unsigned hexadecimal
- format. If "%d" is used, the values are displayed in signed decimal
- format.
-
- The following is a sample program:
-
- #include <stdio.h>
- char bits[8] = {0x80, 0x81, 0x91, 0x00, 0x7f, 0x20, 0x40, 0x08} ;
- main()
- { int i ;
- for (i=0; i<8 ; i++)
- printf("%2x ", bits[i]) ;
- printf("\n") ;
- for (i=0; i<8 ; i++)
- printf("%d ", bits[i]) ;
- }
-
- Output :
- ff80 ff81 ff91 00 7f 20 08
- -128 -127 -111 0 127 32 8
-
-
- 202. Minimum Range Values in the Include File limits.h
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC
- Last Modified: 15-NOV-1988 ArticleIdent: Q38026
-
- Question:
-
- Why is the minimum value of CHAR and INT off by one in the include
- file limits.h?
-
- Response:
-
- This behavior occurs because there is no corresponding positive value
- for the SIGNED CHAR's minimum value. For example, the range of a
- SIGNED CHAR is -128 to 127. The range specified in limits.h is -127 to
- 127. The range of a signed int is -32768 to 32767, but limits.h
- specifies the range as -32767 to 32767.
-
- If you were to take the absolute value of -128 with the ABS() function,
- you would expect to get +128. This is correct; however, you must
- ensure that you store the result in a variable that has a storage
- class that can represent the value.
-
- For example, it does not make sense, and is not possible, to take the
- absolute value of -128 and try and store it in a SIGNED CHAR. 127 is
- the maximum positive value for a this storage class.
-
- The return value from the ABS() function is undefined if you try
- to store the result in a storage class that cannot represent the
- value.
-
-
- 203. Two's Complement
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 16-NOV-1988 ArticleIdent: Q38027
-
- Question:
-
- What is two's complement?
-
- Response:
-
- In most of the C compilers, including Microsoft C Compiler, negative
- values are represented internally in two's complement format. Two's
- complement can be obtained by negating each bit of the value, then
- adding 1. Performing two's complement twice generates the original
- value.
-
- The following is an example:
-
- Original value | Two's complement
- -------------------------|------------------------------
- (dec) (hex) (binary) | (dec) (hex) (binary)
- 127 0x7f 01111111 | -127 0x81 10000001
- 111 0x6f 01101111 | -111 0x91 10010001
- -111 0x91 10010001 | 111 0x6f 01101111
-
-
- 204. Turning Off Cursor in Text Mode
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_c
- Last Modified: 17-NOV-1988 ArticleIdent: Q38124
-
- Question:
-
- How do I turn off the cursor in text mode? I can do it in graphics
- mode but that doesn't work in text mode.
-
- Response:
-
- There is no function in the run-time library to do that; however, you
- can do it with a bios function call.
-
- Use INT 10 FUNCTION 1. Set the CH register to 20h and call the
- interrupt to turn off the cursor. The following is a sample program:
-
- #include <dos.h>
-
- void main(void)
- {
- union REGS regs;
-
- regs.h.ah = 1;
- regs.h.ch = 20;
- int86 ( 0x10, ®s, ®s );
-
- }
-
-
- 205. SDK C Documentation Incorrect for memcpy
-
- Product Version(s): 4.50 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 18-NOV-1988 ArticleIdent: Q38189
-
- Page 339 of the "Microsoft Operating System/2 Software Development
- Kit/ Microsoft C Optimizing Compiler Run-Time Library Reference"
- incorrectly states that the memcpy function ensures proper copying of
- source bytes to the destination if both regions overlap. Microsoft C
- Optimizing Compiler Versions 4.50 or later do not guarantee that
- source bytes in the overlapping area are copied before being
- overwritten.
-
- The memcpy function in Version 4.00 of the Microsoft C compiler
- ensures that copying worked for overlapping regions. Starting with the
- Microsoft C Compiler Version 4.50, this was no longer true. The OS/2
- SDK was first released with C Version 4.50 without the new Microsoft C
- run-time library reference documentation. When the OS/2 SDK package
- was updated to C Versions 5.00 and 5.10, the old Microsoft C run-time
- library reference was not updated. The separate retail packages of the
- Microsoft C Optimizing Compiler Versions 5.00 and 5.10 has the new C
- run-time library reference.
-
- The change was made because ANSI requires that the memmove function,
- not the memcpy function, be used to copy overlapping regions. Because
- no memmove function exists in the Microsoft C Compiler Version 4.00,
- and Microsoft follows ANSI standards, the function memcpy included
- overlapping checking. The added memmove function in C Version 5.00
- prompted the change in the memcpy function. The memmove was added to
- handle overlapping regions while memcpy (the old handler of overlapped
- regions) was implemented as the "fast" copy.
-
-
- 206. C: _acrtused Must Be Defined When Not Including Start-Up Code
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc acrtused __acrtused ROM
- Last Modified: 26-JAN-1990 ArticleIdent: Q43646
-
- The object modules created by the Microsoft C Optimizing Compiler,
- Versions 5.10 and earlier, contain a reference to the variable
- _acrtused. This variable causes the linker to bring in the C start-up
- code. To not link the C start-up code, it is necessary to define
- _acrtused as follows:
-
- int _acrtused = 0;
-
-
- 207. P_NOWAIT Is Not Implemented in DOS Version 4.00
-
- Product Version(s): 5.00 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 18-NOV-1988 ArticleIdent: Q38191
-
- The include file process.h states that P_NOWAIT is enabled in DOS
- Version 4.00. This is incorrect. P_NOWAIT is NOT enabled in the
- current version of DOS Version 4.00. P_NOWAIT is a modeflag as used in
- SPAWNxx functions. P_NOWAIT is used to continue executing the parent
- process concurrently with the child process. P_NOWAIT is implemented in
- OS/2.
-
- Original DOS Version 4.00 was a multitasking, real-mode only MS-DOS.
- The limitations of the real-mode environment made DOS Version 4.00 a
- specialized product. Although MS-DOS Version 4.00 supports full preemtive
- multitasking, system memory is limited to the 640 kilobytes available
- in real mode. This means that all processes have to fit into the
- single 640-kilobyte memory area. Because of these restrictions, MS-DOS
- Version 4.00 was not intended for general release, but as a platform
- for specific OEMs to support extended architectures. Therefore, MS-DOS
- Version 4.00 was released as a special OEM product only.
-
-
- 208. Run-Time Functions remove and unlink both Delete a File
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 21-NOV-1988 ArticleIdent: Q38198
-
- The Microsoft C Optimizing Compiler Run-Time Library contains two
- routines that delete a file. The remove function is documented on Page
- 490, and the unlink function is documented on Page 628 of the
- "Microsoft C Optimizing Compiler Run-Time Library Reference" manual.
- Both routines take the same argument and perform the same operation.
-
- The unlink function exists for Unix/XENIX compatibility. This
- information is documented in Sections B.2.1, B.2.3, and B.5.4 of the
- same manual.
-
-
- 209. Why pointer1++ = pointer2 Is Illegal
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 21-NOV-1988 ArticleIdent: Q38218
-
- Question:
-
- Why is the following statement
-
- pointer1++ = pointer2 ;
-
- illegal, causing error 2106 : left operand must be lvalue,
- when the following statement is legal?
-
- *pointer1++ = *pointer2 ;
-
- Both pointer1 and pointer2 are declared as pointers to the same type.
-
- Response:
-
- Because the post-increment operator ++ has higher precedence than the
- assignment operator =, the following statement
-
- pointer1++ = pointer2 ;
-
- is equivalent to the following statement:
-
- (pointer1++) = pointer2 ;
-
- As defined by the post-increment operation, the result of evaluating
- the expression (pointer1++) is NOT a lvalue. So (pointer1++) cannot
- be used as a left operand of the assignment operator.
-
- However, a statement such as the following, which is equivalent to
- *(pointer1++) = *pointer2 ;, is legal:
-
- *pointer1++ = *pointer2 ;
-
- This statement is legal because although (pointer1++) is not a lvalue,
- it can be used for indirection and *(pointer1++) is a lvalue.
-
- It is very important to understand the difference between the value of
- the expression (pointer1++) and the value of pointer1. Although
- (pointer1++) has higher precedence in the above statements, the result
- of evaluating (pointer1++) has the old value that pointer1 had before
- the evaluation of the expression (pointer1++). Because of the side
- effect of the post-increment operator, the evaluation of (pointer1++)
- causes the value of pointer1 to be incremented by 1 only after the
- rest of the statement has been evaluated. In other words, as an
- address, (pointer1++) points to the same memory location as pointer1
- used to. Therefore, *pointer1++ or *(pointer1++) represents the same
- object as *pointer1 used to.
-
- The following example has the effect of assigning "a" to memory
- offset location 0x100, then incrementing ptr1 to point to memory
- offset 0x101:
-
- char * ptr1 = 0x100; /* ptr1 points to memory offset 0x100
- in the current data segment
- for small or medium memory models */
- *ptr1++ = 'a';
-
-
- 210. /Au Switch Loads DS for Each Function, Not Module
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 21-NOV-1988 ArticleIdent: Q38221
-
- Page 1 of the the "Microsoft C 5.10 (and 5.00) Quick Reference Guide"
- states the following under the /Au switch:
-
- "SS not equal to DS; DS loaded for each module"
-
- This should read as follows:
-
- "SS not equal to DS; DS loaded for each function"
-
- This message is correctly noted on Page 154 of the "Microsoft C 5.1
- Optimizing Compiler User's Guide."
-
-
- 211. Error C1053 Compiler Limit : Struct/union Nesting
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error docerr
- Last Modified: 19-DEC-1988 ArticleIdent: Q38225
-
- The following error is from "Fatal-Error Messages" in the "Microsoft C
- Optimizing Compiler User's Guide," Section E.3.1, Page 250, and in the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.1.1, Page
- 319:
-
- C1053 compiler limit : struct/union nesting
-
- Structure and union definitions were nested to more than
- 10 levels.
-
- The error message and explanation given for C1053 in the "Microsoft
- QuickC Compiler Programmer's Guide" is incorrect. It has been switched
- with the message and description for C1027.
-
- The compiler cannot recover from a fatal error; it terminates after
- printing the error message.
-
-
- 212. Error C1015 Cannot Open Include File 'filename'
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 30-NOV-1988 ArticleIdent: Q38266
-
- The error below is from "Fatal-Error Messages" in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.1.1, Page 315, and in
- the file ERRMSG.DOC found on the Compiler Disk 1 for Microsoft C
- Optimizing Compiler Version 5.10 and on the Setup Disk for Version
- 5.00. It is not in the "Microsoft C Optimizing Compiler User's Guide."
-
- The following is the error:
-
- C1015 cannot open include file 'filename'
-
- The given file either did not exist, could not be opened,
- or was not found. Make sure your environment settings are
- valid and that you have given the correct path name for
- the file.
-
- The compiler cannot recover from a fatal error; it terminates after
- printing the error message.
-
- Some causes of this error include the following:
-
- 1. Incorrectly set environment variables, especially TMP and INCLUDE.
- This error can occur if the INCLUDE environment variable has not
- been set correctly for your include file directory, or if spaces or
- other syntax errors are in the setting.
-
- 2. Improper file handles setting. If the files= line in CONFIG.SYS is
- not high enough, this error will occur. If not set at all, the
- default is usually 8, which is too few. If it is set to greater
- than 20 and the DOS version cannot support that number, it will
- default to 8. File handles will typically be used during
- compilation and linkage by the CL driver, the compiler passes, the
- C source code file, the include files, the linker, libraries, and
- temporary files created by the compiler or linker.
-
-
- 213. Error C1033 Cannot Open Assembly-Language Output 'filename'
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 30-NOV-1988 ArticleIdent: Q38267
-
- The following error is from "Fatal-Error Messages" in the
- "Microsoft C Optimizing Compiler User's Guide," Section E.3.1, Page
- 247, and in the "Microsoft QuickC Compiler Programmer's Guide,"
- Section D.1.1, Page 316:
-
- C1033 cannot open assembly-language output file 'filename'
-
- One of the conditions listed under error message C1032
- prevents the given file from being opened.
-
- The compiler cannot recover from a fatal error; it terminates after
- printing the error message.
-
- The following is the information listed under error message C1032:
-
- One of the following statements about the file name or path name
- given (filename) is true:
-
- 1. The given name is not valid.
-
- 2. The file with the given name cannot be opened for lack of
- space.
-
- 3. A read-only file with the given name already exists.
-
-
- 214. Error C1034 Cannot Open Source File 'filename'
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 30-NOV-1988 ArticleIdent: Q38268
-
- The following error is from "Fatal-Error Messages" in the "Microsoft C
- Optimizing Compiler User's Guide," Section E.3.1, Page 247, and in the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.1.1, Page
- 316:
-
- C1034 cannot open source file 'filename'
-
- One of the conditions listed under error message C1032
- prevents the given file from being opened.
-
- The compiler cannot recover from a fatal error; it terminates after
- printing the error message.
-
- The following is the information listed under error message C1032:
-
- One of the following statements about the file name or
- path name given (filename) is true:
-
- 1. The given name is not valid.
-
- 2. The file with the given name cannot be opened for
- lack of space.
-
- 3. A read-only file with the given name already
- exists.
-
-
- 215. Error C1036 Cannot Open Source Listing File 'filename'
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 30-NOV-1988 ArticleIdent: Q38269
-
- The following error is from "Fatal-Error Messages" in the "Microsoft C
- Optimizing Compiler User's Guide," Section E.3.1, Page 248, and in the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.1.1, Page
- 316:
-
- C1036 cannot open source listing file 'filename'
-
- One of the conditions listed under error message C1032
- prevents the given file from being opened.
-
- The compiler cannot recover from a fatal error; it terminates after
- printing the error message.
-
- The following is the information listed under error message C1032:
-
- One of the following statements about the file name or path name
- given (filename) is true:
-
- 1. The given name is not valid.
-
- 2. The file with the given name cannot be opened for lack of
- space.
-
- 3. A read-only file with the given name already exists.
-
-
- 216. Error C1037 Cannot Open Object File 'filename'
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 30-NOV-1988 ArticleIdent: Q38270
-
- The following error is from "Fatal-Error Messages" in the "Microsoft C
- Optimizing Compiler User's Guide," Section E.3.1, Page 248, and in the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.1.1, Page
- 317:
-
- C1037 cannot open object file 'filename'
-
- One of the conditions listed under error message C1032
- prevents the given file from being opened.
-
- The compiler cannot recover from a fatal error; it terminates after
- printing the error message.
-
- The following is the information listed under error message C1032:
-
- One of the following statements about the file name or path name
- given (filename) is true:
-
- 1. The given name is not valid.
-
- 2. The file with the given name cannot be opened for lack of
- space.
-
- 3. A read-only file with the given name already exists.
-
-
- 217. Error C1059 Out of Near Heap Space
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 30-NOV-1988 ArticleIdent: Q38271
-
- The following error is from "Fatal-Error Messages" in (1) the
- "Microsoft C Optimizing Compiler User's Guide," Section E.3.1, Page
- 250, and in (2) the "Microsoft QuickC Compiler Programmer's Guide,"
- Section D.1.1, Page 319:
-
- C1059 out of near heap space
-
- (1) The compiler has run out of storage for items that it
- stores in the "near" (default data segment) heap. This
- usually means that your program has too many symbols or
- complex expressions. To correct the problem, divide the
- file into several smaller source files, or break
- expressions into smaller subexpressions.
-
- (2) The compiler ran out of storage for items that it stores
- in the "near" (default data segment) heap.
-
- The compiler cannot recover from a fatal error; it terminates after
- printing the error message.
-
- The following is from "Part 2: Notes for the Microsoft C Optimizing
- Compiler User's Guide" in the README.DOC file on Compiler Disk 1 for
- Microsoft C Version 5.10. A similar section is found in the README
- file on the Setup Disk for Version 5.00.
-
- This release includes an alternate form of compiler pass 1 named
- C1L.EXE. This compiler pass can be used to compile programs that get
- the error message "out of near heap space". Invoke C1L.EXE by entering
- the CL command with the /B1 <path> option, as follows:
-
- cl /B1 <path>\c1l.exe <sourcefile>.c
-
- In the preceding command, <path> is the path (including drive and
- directory) where C1L.EXE resides, and <sourcefile> is the name of the
- C source file you want to compile.
-
-
- 218. Example Incorrect on Page 373 of C Run-Time Library Reference
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 22-NOV-1988 ArticleIdent: Q38283
-
- The example for intdosx on Page 373 of the "Microsoft C 5.1 Optimizing
- Compiler Run-Time Library Reference" is incorrect.
-
- To get the example to work correctly, the line that reads
-
- char far *dir = "\newdir"; /* Directory to create */
-
- must be changed to read as follows:
-
- char far *dir = "\\newdir"; /* Directory to create */
-
- The backslash character \ in a C string is interpreted as part of an
- escape code. To actually represent the backslash character for a
- file's path, use two consecutive backslashes.
-
-
- 219. 80386 and 80387 Instruction Set
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | h_fortran s_pascal s_quickc
- Last Modified: 7-DEC-1988 ArticleIdent: Q38284
-
- Question:
-
- According to the "Microsoft C 5.1 Optimizing Compiler User's Guide,"
- you can generate 80286 and 80287 instructions with your high-level
- language compilers. Can I also use the 80386 and 80387 instruction
- set?
-
- Response:
-
- You can use the 80386 and 80387 chips. However, none of our products
- generate true 80386 code, or use 32-bit addressing. Although our
- compilers do not generate specific 80386 or 80387 code, the code which
- is generated will run faster than on a 80286 and 80287.
-
-
- 220. Detecting Presence of 80x87 Math Coprocessor
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G881027-5369 8087 80287 80387 87 /FPc
- Last Modified: 30-NOV-1988 ArticleIdent: Q38285
-
- Question:
-
- My Microsoft C program is compiled with the /FPi (floating-point
- emulator) option. I would like to warn the user if they are running it
- on a machine that has no math coprocessor. Is there any way to detect
- if an 80x87 is currently being used by the floating-point libraries?
-
- Response:
-
- There is no direct way to query the Microsoft C floating-point
- libraries as to whether or not they're using a math coprocessor. If
- you compile /FPi, you're telling the compiler you don't want to have
- to worry about whether or not a coprocessor is present. Consequently,
- the compiler generates code that will do the following:
-
- 1. Check to see if a 80x87 coprocessor is present.
-
- 2. If so, use it.
-
- 3. If not, emulate it with software routines.
-
- There is nothing in this algorithm to tell your program what it found.
- The only way you'll know it's emulating the coprocessor is by
- observing how slowly your program runs.
-
- If you really need to know whether a coprocessor is present, you'll
- have to test it yourself. For more information on how to test for the
- presence of an 80x87 coprocessor, please consult Intel's "80286 and
- 80287 Programmer's Reference Manual," Pages 3-2 and 3-3 (in the 2nd
- half of the book). This section is titled "System-Level Numeric
- Programming," and states that your program can detect the presence of
- the 80287 NPX. It then gives an assembly-language example that works
- correctly for both 8086- and 80286-based machines.
-
- Here is how you could use this routine in your program:
-
- 1. During initialization of your program, call the short Intel routine
- to see if a coprocessor is present.
-
- 2. If there is a coprocessor, proceed normally.
-
- 3. If there is no coprocessor, put up a message box explaining the
- following to the user:
-
- "Your computer lacks a coprocessor, but <my_app> will emulate it in
- software; this emulation will slow down the calculations that
- <my_app> needs to perform. To increase the performance of
- <my_app>, as well as other programs, add a numeric coprocessor to
- your system."
-
- 4. Proceed with your program as you normally would. The C run-time
- libraries will automatically adjust for the presence or lack of a
- 80x87.
-
-
- 221. Cannot Define Preprocessor Directives with #define
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC
- Last Modified: 28-NOV-1988 ArticleIdent: Q38291
-
- The Microsoft C Compiler does not allow a "#define" statement to
- define another preprocessor directive. Although the preprocessor
- output option ( /P or /E ) generates the desired expansion, the
- Microsoft C Compiler Version 5.10 generates the following error
- messages when compiling the code below:
-
- error C2014: preprocessor command must start as first non-whitespace
- error C2054: expected '(' to follow 'define'
- error C2061: syntax error : identifier 'MAX'
-
- The following code demonstrates the problem:
-
- #define A( x ) x##define MAX 100
-
- A( # )
- /*
- Preprocessor output expands A( # ) to be:
- #define MAX 100
- */
-
- char w[ MAX ];
- void main(void);
- void main()
- {
- w[ 0 ] = w[ MAX ];
- }
-
-
- 222. wait and cwait Are for Protected Mode
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 7-DEC-1988 ArticleIdent: Q38293
-
- Page 556 of the "Microsoft C 5.1 Optimizing Compiler User's Guide"
- states that to obtain the exit code for an asynchronous spawned
- process, you must call the wait or cwait function and specify the
- process ID.
-
- Wait, Cwait, and asynchronous spawns can only occur in protected mode.
-
- The wait function suspends the calling process until any of the
- caller's immediate child processes terminate. If all of the caller's
- child processes have terminated before it calls the wait function, the
- function returns immediately.
-
- The cwait function suspends the calling process until the specified
- child process terminates.
-
- For more information, refer to the "Microsoft C 5.1 Optimizing
- Compiler User's Guide" Update Pages 30 and 48.
-
-
- 223. Overwriting End of HALLOC Causes Crash at Termination
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-DEC-1988 ArticleIdent: Q38294
-
- The following message appearing at the termination of a program can be
- caused by overwriting past the end of a block of memory allocated by
- the halloc function:
-
- Memory allocation error: Cannot load command.com
-
- The bytes following a halloc'd block are used by DOS for keeping
- track of memory allocation, and DOS may be unable to load command.com
- upon completion of your process if this area is corrupted.
-
- This error can also conceivably be caused by overwriting blocks of
- memory allocated by other functions such as malloc, _nmalloc, and _fmalloc.
-
-
- 224. How the Null Character Is Handled by Printf Functions.
-
- Product Version(s): 4.00 5.00 5.10 | 4.00 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 28-NOV-1988 ArticleIdent: Q38296
-
- When the C run-time functions printf, fprintf, or sprintf encounter
- the character-conversion specifier %c in their format-control string,
- they will convert the corresponding argument of int type to unsigned
- char type and write the resulting value to output. Therefore, if the
- argument is a NULL character, the value 0 (not the character "0") is
- written to the output.
-
- The output can be stdout, a file (with fprintf) or a string (with
- sprintf). In case of stdout, the NULL character is ignored by the
- display device. In the case of string, the NULL character will be
- interpreted as a terminator character when the resulting string is
- used later in the program.
-
- The output of the following program is the result of expected
- behavior:
-
- #include <stdio.h>
- char buffer[30] ;
- main()
- {
- printf("Before,%c,After\n", '\0') ;
- sprintf(buffer, "Before,%c,After\n", '\0') ;
- printf(buffer) ;
- }
- /* end of sample program */
-
- Output :
-
- Before,,After
- Before,
-
-
- 225. Spawn Will Not Pass Redirection to Child
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# S880925-1
- Last Modified: 12-DEC-1988 ArticleIdent: Q38308
-
- Question:
-
- When using the program below to spawn sort.exe, it seems that "sort"
- starts, but then sits there doing nothing. The behavior is similar to
- starting "sort" from the DOS prompt without any arguments.
-
- The following program demonstrates the problem:
-
- #include <stdio.h>
- #include <process.h>
- main()
- {
- char *args[6] ;
- args[0] = "sort" ;
- args[1] = "<" ;
- args[2] = "infile.dat" ; /* exists */
- args[3] = ">" ; /* direct output to a disk file */
- args[4] = "outfile.dat" ;
- args[5] = NULL ;
-
- spawnvp (P_WAIT, "sort.exe", args) ;
- }
-
- Why doesn't this work correctly? What can I do about it?
-
- Response:
-
- Because COMMAND.COM, and NOT the EXEC loader, handles indirection,
- this is the expected behavior. Child processes inherit the handles of
- their parents; therefore, to redirect the input and output of the
- child you first change the definitions of STDIN and STDOUT in the
- parent process. The proper way to redirect input for a filter is
- described starting on Page 441 of the "MS-DOS Encyclopedia," along with
- a complete MASM example. Note: the dup and dup2 functions in the C
- Version 5.10 run-time library are the same as the INT 21h functions 45h
- and 46h, respectively.
-
- There also are partial examples of this technique on Page 230 of the
- "Microsoft C Version 5.10 Run-Time Library Reference" manual and on
- Page 353 of "Advanced MS-DOS Programming" (by Duncan, published by
- Microsoft Press).
-
- It is possible to use freopen() to redefine STDIN and STDOUT; however,
- doing so loses any redirection that may have been performed on the
- parent process.
-
- The easiest workaround is to use the system function to spawn a copy
- of COMMAND.COM that runs SORT.EXE, as follows:
-
- system("sort.exe <infile.dat >outfile.dat");
-
-
- 226. Attributes in Hercules Graphics Mode
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 19-DEC-1988 ArticleIdent: Q38312
-
- Problem:
-
- I'm using a Hercules graphics adapter in graphics mode and I would
- like to do high-intensity "bold" graphics, but I can't seem to get it
- to work correctly.
-
- Response:
-
- Using the Hercules graphics adapter in graphics mode, each pixel maps
- to only 1 bit in memory. Because there is only 1 bit, that pixel can
- only be on or off. In Hercules graphics mode, there is no facility for
- attributes such as high-intensity, blinking, reverse, or underline.
-
- In Hercules graphics mode, the only way to get blinking, reverse, and
- underline is for your program to manipulate or turn on and off each
- pixel. High-intensity will not be possible.
-
- If you put the adapter into Text mode, you can use all of these
- attributes freely.
-
-
- 227. C Setup Gives Error U2155 When Building Libraries
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_LIB
- Last Modified: 15-JAN-1990 ArticleIdent: Q38319
-
- Problem:
-
- When installing Optimizing C, I get the following error:
-
- LIB : error U2155: <path> : module not in library; ignored
-
- Response:
-
- Most likely, this is caused by having a dash (-) embedded in the path
- specified as the combined libraries destination. Restart SETUP and do
- not include a dash in the library path.
-
- This is a problem with LIB.EXE.
-
- LIB cannot handle the "-" (hyphen, dash) character embedded in a
- directory/file name. Instead, it interprets the dash as the extraction
- operator giving rise to error U2155. The hyphen is a legal character
- for DOS file and directory names and many people use it (for example,
- MS-C for the C directory.) In this example, LIB will terminate with
- the following cryptic message:
-
- U2155: C:\MS-C\MLIBCE.LIB module not in library (ms.obj)
-
- The message is dependent upon the directory/file name used, but the
- symptom is always the same: module not in library, invalid object
- module, object file not found, etc.
-
- Note: this error can occur in situations other than setting up the
- compiler. Anytime you pass a directory/file name that contains a
- hyphen, you can cause this behavior.
-
-
- 228. _Fheapwalk Does Not Check the Near Heap
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 30-NOV-1988 ArticleIdent: Q38327
-
- The HeapWalk routines are provided as an aid in debugging heap-related
- problems in programs. In large-, huge-, and compact-memory models
- _heapwalk will map onto the function _fheapwalk. In small- and
- medium-memory models, it maps onto function _nheapwalk. The _fheapwalk
- function will not check or examine the near heap in the default data
- segement while _nheapwalk will examine only the near heap.
-
- Because _fheapwalk will not check the near heap, you should not assume
- that the HeapWalk routine will always reflect information about all
- your pointers when you are using compact-, large- and huge-memory
- models. This is because in these models, malloc will draw upon the
- far heap until it is exhausted, then turn to the near heap. In this
- case, it is possible to have valid pointers but _fheapwalk will not
- acknowledge them.
-
- For this reason, you should not assume that _fheapwalk will provide
- information about all your pointers, or you should use both _fheapwalk
- and _nheapwalk to check both the near heap and the far heap.
-
-
- 229. C 5.10 Doesn't Implement Multibyte Integer Character Constants
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 28-NOV-1988 ArticleIdent: Q38328
-
- Page 28 of the ANSI C draft proposal X3J11/88-001 describes an integer
- character constant as being a sequence of one or more multibyte
- characters enclosed in single quotation marks, e.g. 'a' or 'ab'.
-
- Page 21 of the "Microsoft C 5.1 Optimizing Compiler Language
- Reference Guide" states that an integer character constant
- is formed by enclosing a single character from the representable
- character set within single quotation marks. It makes no reference to
- multibyte character constants (e.g. 'ab'). If a source file has the
- character constant defined as follows, the error "C2015: Too many
- chars in constant" is generated:
-
- int ch = 'ab';
-
- This error is correct, because Microsoft C Version 5.10 does not
- implement multi-character integer character constants. Note that
- page 29 of the draft standard says that such constructions are
- "implementation-defined."
-
-
- 230. sscanf Example Using a Comma (,) as Delimiter
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 12-DEC-1988 ArticleIdent: Q38335
-
- The example below shows how to use the sscanf C Run-Time function
- to read from an internal buffer delimiting fields with a comma (,).
- The key is to use the brackets in the format of sscanf function. The
- format would be %[^','], which tells the function to read from the
- buffer until a comma (,) is reached.
-
- The following is a C source example illustrating the use of brackets
- and the caret (^):
-
- #include <math.h>
- #include <stdio.h>
-
- char *tokenstring = "first,25.5,second,15";
- int result, i;
- double fp;
- char o[10], f[10], s[10], t[10];
-
- main()
- {
- result = sscanf(tokenstring, "%[^','],%[^','],%[^','],%s", o, s, t, f);
- fp = atof(s);
- i = atoi(f);
- printf("%s\n %lf\n %s\n %d\n", o, fp, t, i);
- }
-
-
- 231. Shared and Instance Segments in a DLL
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | SR# G881019-4906 -ND SINGLE S_LINK
- Last Modified: 24-JAN-1990 ArticleIdent: Q38714
-
- Question:
-
- How can I get both shared and instance data in a DLL? I'd like to have
- the default data segment (DGROUP) and most of the far segments to be
- instance data and a single far data segment to be shared data. I've
- tried to do this by doing the following:
-
- 1. Isolating the data for the far segment in fardata.c and compiling
- it with -NDSEG1
-
- 2. Linking with a .DEF file that contains the following:
-
- DATA MULTIPLE NONSHARED
- SEGMENTS
- SEG1 CLASS 'FAR_DATA' SHARED
-
- When I do this, ALL data segments (including SEG1) are instance; I
- determined this from both my test program and the output of the exehdr
- utility.
-
- How can I make the SEG1 segment shared?
-
- Response:
-
- Every time you use /NDSEG1 option compiler will generate the
- following segment definitions:
-
- SEG1 class 'FAR_DATA'
- SEG1_CONST class 'FAR_DATA'
- SEG1_BSS class 'FAR_DATA'
- GROUP SEG1_GROUP SEG1, SEG1_CONST, SEG1_BSS
-
- SEG1, SEG1_CONST, and SEG1_BSS are all members of the same group
- (physical segment). (SEG1_CONST AND SEG1_BSS are created automatically
- by the compiler, as is the group SEG1_GROUP.) The linker overrides the
- SEGMENTS specification if ANY of the segments in the group are left at
- the default. The solution is to ask the linker to share ALL of the
- segments in the group. In your case, insert the following into the
- .DEF file:
-
- DATA MULTIPLE NONSHARED
- SEGMENTS
- SEG1 CLASS 'FAR_DATA' SHARED
- SEG1_CONST CLASS 'FAR_DATA' SHARED
- SEG1_BSS CLASS 'FAR_DATA' SHARED
-
- Note: if the segment(s) you want to share are part of a group, you
- must set ALL of the segments in the group to be shared or NONE will
- be.
-
-
- 232. Finding Out what Video Adapters Are Installed and Active
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | video display monitor color monochrome black white b/w mono
- Last Modified: 14-DEC-1988 ArticleIdent: Q38726
-
- Question:
-
- I am writing a program that has to determine what adapter boards are
- installed in a machine. In addition, it must also determine which
- board is active. How can I use the functions supplied with C to get
- this information?
-
- Response:
-
- There is no way using the functions we supply to find out what type of
- video adapters are installed in your system. There is, however, a
- book entitled "Programmer's Guide to PC & PS/2 Video Systems,"
- published by Microsoft Press, which has an appendix that has a MASM
- example of finding out what adapters are installed. (This example
- could be translated into C.)
-
- However, even if you write code to find out what adapters are
- installed, there is no simple way to tell the graphics library to
- use an adapter other than the one it wants to use. The library will
- pick an adapter according to the following rules:
-
- 1. If there is a VGA in the system, it uses it regardless of what
- other adapters are installed and regardless of what adapter is
- currently the default adapter. The only way to change this is to
- hook the BIOS INT 10h interrupt as described below.
-
- 2. If there is no VGA, it uses the current adapter. This can be set
- with the MODE command in DOS before you start your program.
-
- If you hook INT 10h, you can change the behavior with the VGA to pick
- the current adapter. The _setvideomode function makes a call to INT
- 10h function 1Bh to determine whether a VGA is installed or not. You
- can write code to change the return value if the VGA is not the
- current adapter, leaving it alone if the VGA is the current adapter.
-
- The _getvideoconfig function only gives information on the current
- video mode, as set by _setvideomode. It is not helpful for finding out
- what adapters are installed in your system.
-
- You can find out what adapter the library would use by making calls to
- _setvideomode. If the mode cannot be selected, _setvideomode will
- return zero. For example, if you tried to select a VGA mode and
- _setvideomode returned zero, you would know that no VGA was present in
- the system. You then could attempt to select an EGA, etc.
-
-
- 233. Initializing Large Character Arrays
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G881128-6987
- Last Modified: 16-JAN-1989 ArticleIdent: Q38728
-
- Question:
-
- How can I initialize an array of characters larger than 512 bytes?
- When I try initializing using a character string literal, as follows,
-
- char a[] = " *** 1000 characters *** ";
-
- I get the following compiler message:
-
- Warning C4009: string too big, trailing chars truncated
-
- Response:
-
- One method of initializing character arrays is to use a character
- string literal. The minimum limit allowed by ANSI for a characters
- string literal after concatenation is 509 characters. The limit in
- Microsoft C is 512 characters. Because the limit on the length of a
- string literal is 512 characters, you cannot initialize character
- arrays longer than 512 bytes with this method.
-
- The following won't work correctly either because the compiler treats
- these as a single string literal rather than specially as an
- initializer:
-
- char stuff[] =
- "xxx...xxx"
- ...
- "xxx...xxx";
-
- (The ANSI standard says that strings separated only by white space are
- automatically concatenated.)
-
- There are, however, a few other methods you can use that will work
- successfully, such as the following:
-
- char stuff [] =
- { 'a', ...
- ...
- ... 'z' };
-
- However, such an initializer is no fun to type. If you decide to use
- this method, you might want to write a program that will read a data
- file and output the proper initializer.
-
- You might also want to try the following:
-
- char stuff[][10] = {
- "0123456789",
- ...
- "0123456789" };
-
- The value 10 is not important EXCEPT that it must match the actual
- length of the string constants. If any of the constants are shorter
- than the length you specify, the end of that row will be padded out
- with zero bytes. If any are longer, the extra characters will be
- thrown away. You can use another pointer to access the following in
- almost any method you want:
-
- char *stuffptr = (char *) stuff;
-
- This method seems to be the most convenient.
-
- You can also define the array in MASM and link it to your C
- program. In MASM, once you've done the correct segment and public
- definitions, you could write the following:
-
- stuff db "abcdefghijkl"
- db "morestuff"
- ...
- db "laststuff"
-
- In C, you could access the array with the following:
-
- extern char stuff[]; /* char * stuff; will NOT work */
-
- Finally, you could read the values into the array at run-time from a
- data file. If you read the file in large blocks, (e.g. using read or
- fread) you'll find that the I/O is quite fast.
-
-
- 234. Mixing Old Declarations with Prototypes Causes Passing Errors
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G881107-5854
- Last Modified: 12-DEC-1988 ArticleIdent: Q38729
-
- Question:
-
- It is my understanding that both of the following functions should
- produce identical results:
-
- float AAA(float x1, float x2)
- {
- x1 = x2;
- }
-
- float BBB(x1,x2)
- float x1,x2;
- {
- x1 = x2;
- }
-
- However, they don't. Looking at the code, I see that in BBB, the two
- parameters are treated as double instead of float. When I compile with
- the /Zg switch, which generates function prototypes, the following
- prototypes are generated:
-
- extern float AAA(float x1, float x2);
- extern float BBB(double x1, double x2);
-
- Why is this behavior occuring?
-
- Response:
-
- The following is from the May 5, 1988 ANSI draft, Section 3.3.2.2:
-
- "If the expression that denotes the called function has a type that
- does not include a prototype...arguments that have type float are
- promoted to double.
-
- "If the expression that denotes the called function has a type that
- includes a prototype, the arguments are implicitly converted, as if
- by assignment, to the types of the corresponding parameters."
-
- For AAA, you're using the new function definition style. Note that if
- you call this function (perhaps in another module) without a prototype
- in scope, you'll have problems because you'll pass doubles rather than
- floats (see first paragraph above).
-
- BBB uses the old style of definition as described in K & R. Because
- K & R specified that the floats are to be widened to doubles when
- they're passed to functions (and in a variety of other situations
- as well), the old style declarations maintain the old semantics.
-
- Therefore, the /Zg switch is correctly generating the function
- prototypes.
-
- Your program wouldn't run when you declared the following prototype
- before calling BBB because the prototype that was in scope when you
- CALLED BBB did not match the implicit prototype generated when the
- function was defined:
-
- void BBB(float, float);
-
- As a result, you passed floats to a function that was expecting
- doubles.
-
-
- 235. Changing Default int to 32 Bits
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: END-USER | SR# G881110-6126
- Last Modified: 12-DEC-1988 ArticleIdent: Q38730
-
- Question:
-
- I am porting a VERY large C program from another C compiler to OS/2.
- In the other compiler, the type int is defined as being the same as
- long (i.e., 32 bits). In Microsoft C, int is defined as being the same
- as short (i.e., 16 bits).
-
- Is there a compiler switch to change int to long rather than short?
-
- Response:
-
- There's no compiler switch that changes the default int to long rather
- than short. If you included a "typedef long int;" or a "#define int
- long" in each and every module you compiled, you would take care of
- some of the problems. However, redefining the identifier "int" is
- likely to cause you severe and difficult-to-find problems. We
- emphatically do NOT recommend it.
-
- Note: K & R and ANSI are both very clear that int could be any size,
- provided that it's at least 16 bits. It is bad coding practice to rely
- on 32-bit ints because it makes porting code difficult.
-
- Changing all int variables to long causes your program to run very
- slowly because whenever it does arithmetic, it will have to do slower
- 32-bit arithmetic rather than the more efficient built-in 16-bit
- arithmetic. This situation is true even on 80386 processors because
- current versions of our compilers do not support the generation of
- code that takes advantage of the 80386's 32-bit registers.
-
- A far better strategy is to change only the variables that need to be
- long to long. This way, you will avoid a lot of unintended side
- effects and you will not do more 32-bit arithmetic than is necessary.
-
-
- 236. Overflow in Integer Math Expressions Not Checked
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC
- Last Modified: 12-DEC-1988 ArticleIdent: Q38733
-
- The operations performed by the integer arithmetic and shift operators
- do not check for overflow or underflow conditions. Information may be
- lost if the result of an operation cannot be represented in the type of
- the operands after conversion. All expressions are evaluated prior to
- assignment to a variable.
-
- Rules for numeric conversion are described on Page 115 of the
- "Microsoft C Language Reference" manual.
-
- The following example demonstrates the overflow condition:
-
- #include <stdio.h>
- void main(void);
- void main()
- {
- long l;
-
- l = 70 * 1000; /* First Example */
- printf( "l = %ld\n", l ); /* l = 4464 = 70000 % 65536 */
- /* Overflow not caught!!! */
-
- l = 70L * 1000; /* Second Example */
- printf( "l = %ld\n", l ); /* l = 70000 */
- /* arithmetic in long--no */
- /* overflow */
- }
-
- In the first example, 70 and 1000 are considered as integers. Because
- both are integer types, integer math is being performed. Integers can
- have at most a value of 32,767. When 70 is multiplied to 1000, the
- product exceeds the maximum value that an integer can hold. Overflow
- is not checked and information is lost. Thus we get a value of 4464,
- which is 70,000 mod 65,536.
-
- The workaround is the second example. Conversions occur if the types
- of the operands are different. Because 70 is a long integer (32 bits.
- Without the L, it is considered a normal integer of 16 bits). Because
- a long integer is used, all operands will be converted to long and the
- math will be done using 32-bit arithmetic. The product is large enough
- to handle the multiplication, so the correct result of 70,000 is
- generated.
-
-
- 237. Viewing Array Elements in CodeView
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-DEC-1988 ArticleIdent: Q38735
-
- Question:
-
- In CodeView, why am I unable to view elements of an array with an
- index of type char in my C program? Whenever I do so, I get the
- following error:
-
- "operand types incorrect for this operation"
-
- Response:
-
- Using a char variable to index an array is only valid in the C
- language. As CodeView supports multiple languages, it does not allow
- a char variable to index into an array, even if the program is written
- in C.
-
- For a workaround to view elements of an array indexed by a variable of
- type "char", you need to cast the variable to an int type in
- CodeView's Dialog Box as follows:
-
- > ? buffer[(int)i]
-
- The following code sample demonstrates the situation:
-
- #include <stdio.h>
- main()
- {
- int j = 5;
- char i = 5;
- char buffer[10];
-
- scanf("%s",buffer);
-
- }
-
- When the above program is loaded, CodeView allows you to view
- the fifth element of the array with the following commands:
-
- > ?buffer[5]
-
- > ?buffer[j].
-
- However, the following command causes the error: "operand types
- incorrect for this operation":
-
- > ?buffer[i]
-
-
- 238. Error L1006 Option : Stack Size Exceeds 65535 Bytes
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error docerr
- Last Modified: 7-DEC-1988 ArticleIdent: Q38769
-
- The following error is from "Linker Error Messages" in (1) the manual
- "CodeView and Utilities," Section C.2, Page 360, and in (2) the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.4, Page 365:
-
- (1)
- L1010 option : stack size exceeds 65536 bytes
-
- The size specified for the stack in the /STACK option of
- the LINK command was more than 65,536 bytes.
-
- (2)
- L1006 option : stack size exceeds 65535 bytes
-
- The size specified for the stack was more than 65,535
- bytes.
-
- Fatal errors cause the linker to stop execution. Fatal error messages
- have the following format:
-
- location : fatal error L1xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- The documentation of the error in the "CodeView and Utilities" manual
- is incorrect. The error number should be L1006, not L1010. The upper
- limit of the stack as given in both the error message and its
- description should be 65535, not 65536. The QuickC manual is correct.
-
- This error is documented in the files ERRMSG.DOC for Microsoft C
- Version 5.10, README.DOC for Microsoft Macro Assembler Version 5.10,
- CVREADME.DOC for Microsoft FORTRAN Version 4.10, and README.DOC for
- Microsoft Pascal Version 4.00, but the description given has a
- documentation error. The error is given as:
-
- L1006 <option-text>: stack size exceeds 65535 bytes
-
- The value given as a parameter to the /STACKSIZE option exceeds
- the maximum allowed.
-
- The option /STACKSIZE is wrong. The LINK option to change the stack is
- either /STACK or /ST. Specifying /STACKSIZE will generate the error:
-
- LINK : fatal error L1002: STACKSIZE : unrecognized option name
-
-
- 239. Error L1081 Out of Space for Run File
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 7-DEC-1988 ArticleIdent: Q38790
-
- The following error is from "Linker Error Messages" in the manual
- "CodeView and Utilities," Section C.2, Page 364, and in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.4, Page 369:
-
- L1081 out of space for run file
-
- The disk on which the .EXE file was being written was
- full.
-
- Free more space on the disk and restart the linker.
-
- Fatal errors cause the linker to stop execution. Fatal error messages
- have the following format:
-
- location : fatal error L1xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
-
- 240. Error L1087 Unexpected End-of-File on Scratch File
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 7-DEC-1988 ArticleIdent: Q38795
-
- The following error is from "Linker Error Messages" in the manual
- "CodeView and Utilities," Section C.2, Page 364, and in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.4, Page 370:
-
- L1087 unexpected end-of-file on scratch file
-
- The disk with the temporary linker-output file was
- removed.
-
- Fatal errors cause the linker to stop execution. Fatal error messages
- have the following format:
-
- location : fatal error L1xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- This error can be caused by insufficient space on the disk (hard,
- floppy, or RAM) where the temporary file is being written.
-
-
- 241. Error L2002 Fixup Overflow Near Number...
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 7-DEC-1988 ArticleIdent: Q38806
-
- The L2002 error below is from "Linker Error Messages" in the manual
- "CodeView and Utilities," Section C.2, Page 366, and in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.4, Page 372.
-
- The following is the error:
-
- L2002 fixup overflow near number in frame seg segname target seg
- segname target offset number
-
- The following conditions can cause this error:
-
- A small-model program is compiled with the /NT option.
-
- A group is larger than 64K.
-
- The program contains an intersegment short jump or
- intersegment short call.
-
- The name of a data item in the program conflicts with
- that of a subroutine in a library included in the
- link.
-
- An EXTRN declaration in an assembly-language source
- file appeared inside the body of a segment, as in the
- following example:
-
- code SEGMENT public 'CODE'
- EXTRN main:far
- start PROC far
- call main
- ret
- start ENDP
- code ENDS
-
- The following construction is preferred:
-
- EXTRN main:far
- code SEGMENT public 'CODE'
- start PROC far
- call main
- ret
- start ENDP
- code ENDS
-
- Revise the source file and recreate the object file. (For
- information about frame and target segments, refer to the
- "Microsoft MS-DOS Programmer's Reference.")
-
- Nonfatal errors indicate problems in the executable file. LINK
- produces the executable file. Nonfatal error messages have the
- following format:
-
- location : error L2xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- Force data outside of DGROUP by using the /Gt compiler switch along
- with a large data model (compact, large, or huge).
-
- Using the linker switch /CO twice can cause this. For example, when
- LINK is invoked with /CO when a LINK environment variable is also set
- to /CO, then this situation results.
-
-
- 242. Error L1070 Segment Size Exceeds 64K
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 12-JAN-1989 ArticleIdent: Q38807
-
- The following error is from "Linker Error Messages" in (1) the manual
- "CodeView and Utilities," Section C.2, Page 363, and in (2) the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.4, Page 369:
-
- (1)
- L1070 segment size exceeds 64K
-
- A single segment contained more than 64K of code or data.
-
- Try compiling and linking using the large model.
-
- (2)
- L1070 name: segment size exceeds 64K
-
- The specified segment contained more than 64K of code or
- data.
-
- Try compiling and linking using the large model.
-
- Fatal errors cause the linker to stop execution. Fatal error messages
- have the following format:
-
- location : fatal error L1xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- Use a large data model (compact, large, or huge). Try applying the /Gt
- compilation option to lower the threshhold.
-
-
- 243. Error L1072 Common Area Longer than 65536 Bytes
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 12-JAN-1989 ArticleIdent: Q38808
-
- The following error is from "Linker Error Messages" in (1) the manual
- "CodeView and Utilities," Section C.2, Page 364, and in (2) the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.4, Page 369:
-
- L1072 common area longer than 65536 bytes
-
- (1) The program had more than 64K of communal variables. This
- error cannot appear with object files generated by the
- Microsoft Macro Assembler, MASM. It occurs only with
- programs produced by the Microsoft FORTRAN or C Compilers
- or other compilers that support communal variables.
-
- (2) The program had more than 64K of communal variables. This
- error cannot appear with object files generated by the
- Microsoft Macro Assembler, MASM. It occurs only with
- programs produced by the Microsoft QuickC Compiler or
- other compilers that support communal variables.
-
- Fatal errors cause the linker to stop execution. Fatal error messages
- have the following format:
-
- location : fatal error L1xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- Use a large data model (compact, large, or huge). Try applying the /Gt
- compilation option to lower the threshhold.
-
-
- 244. Error L1085 Cannot Open Temporary File
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 7-DEC-1988 ArticleIdent: Q38809
-
- The following error is from "Linker Error Messages" in the manual
- "CodeView and Utilities," Section C.2, Page 364, and in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.4, Page 370:
-
- L1085 cannnot open temporary file
-
- The disk or the root directory was full.
-
- Delete or move files to make space.
-
- Fatal errors cause the linker to stop execution. Fatal error messages
- have the following format:
-
- location : fatal error L1xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- This error can be caused by insufficient file handles. Resident
- software (TSR) can use up some handles, or can cause other kinds of
- interference that can cause this error.
-
-
- 245. Error L1089 Filename : Cannot Open Response File
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 11-JAN-1990 ArticleIdent: Q38810
-
- The following error is from "Linker Error Messages" in the manual
- "CodeView and Utilities," Section C.2, Page 365, and in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.4, Page 370:
-
- L1089 filename : cannot open response file
-
- LINK could not find the specified response file.
-
- This usually indicates a typing error.
-
- Fatal errors cause the linker to stop execution. Fatal error messages
- have the following format:
-
- location : fatal error L1xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- Also, check the TMP environment variable setting and/or TSR's.
-
-
- 246. Error L2029 Unresolved Externals
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 11-JAN-1990 ArticleIdent: Q38818
-
- The following error is from "Linker Error Messages" in the manual
- "CodeView and Utilities", Section C.2, Page 368, and in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.4, Page 373:
-
- L2029 unresolved externals
-
- One or more symbols were declared to be external in one or
- more modules, but they were not publicly defined in any of
- the modules or libraries. A list of the unresolved
- external references appears after the message, as shown in
- the following example:
-
- EXIT in file(s):
- MAIN.OBJ (main.for)
- OPEN in file(s):
- MAIN.OBJ (main.for)
-
- The name that comes before in file(s) is the unresolved
- external symbol. On the next line is a list of object
- modules that have made references to this symbol. This
- message and the list are also written to the map file, if
- one exists.
-
- Nonfatal errors indicate problems in the executable file. LINK
- produces the executable file. Nonfatal error messages have the
- following format:
-
- location : error L2xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- This linker error message means that a reference to a function or
- procedure was made, but the actual routine to that reference was never
- found (in either a library or in another object module). This message
- is not in regards to inclusion or exclusion of include files in a C
- program. (Include files in a C program usually do not contain
- functions, but rather function prototypes.) If this error message
- should occur, check the following:
-
- 1. Make sure the command line used to invoke the linker or the
- compiler/linker is correct.
-
- 2. Check that you have specified all libraries that are needed by
- the program (e.g. graphics.lib, a third-party library).
-
- 3. Check the spelling of the procedure or function name in the
- program and make sure it corresponds to how the function is
- actually declared.
-
- 4. Make a listing of the libraries that are being linked with to
- see if the missing procedure or function is indeed in the library.
- This process will require the use of LIB.EXE.
-
- 5. If you are in QuickC and this message occurs, check to see if
- the function that is being called is contained in the core library.
- If it isn't, you need to set a Program List in the QuickC editor.
-
- 6. Check the name that the linker can't resolve. If the name is
- preceded by two underscores, then most likely it is either an
- internal routine for startup or other internal functions or the
- library was built with an incorrect version of LIB.
-
- Make sure a main() has been declared and/or a function in C wasn't
- preceded with an undesired underscore. This error can also occur if a
- C program is being mixed with an assembler routine and the assembler
- routine was not assembled with the /MX and /ML options to preserve the
- case of the functions, or the function in the assembler program didn't
- have an underscore in front of its name to make it compatible with the
- C naming convention.
-
-
- 247. Error L2041 Stack Plus Data Exceeds 64K
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 7-DEC-1988 ArticleIdent: Q38819
-
- The error below is from "Linker Error Messages" in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.4, Page 374. It is also
- in the file ERRMSG.DOC on Compiler Disk 1 for Microsoft C Version 5.10
- and on the Setup Disk for Microsoft C Version 5.00, and in the file
- README.DOC on Disk 1 for Microsoft Macro Assembler Version 5.10, and
- in the file CVREADME.DOC on the CodeView for MS-DOS disk for Microsoft
- FORTRAN Version 4.10. It is not found in the manual "CodeView and
- Utilities."
-
- The following is the error:
-
- L2041 stack plus data exceeds 64K
-
- The combined size of the program stack segment plus DGROUP
- was greater than 64K; as a result, the program will not
- load up correctly.
-
- Nonfatal errors indicate problems in the executable file. LINK
- produces the executable file. Nonfatal error messages have the
- following format:
-
- location : error L2xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- To correct the problem, do the following:
-
- 1. Reduce the stack size.
-
- 2. Use a large data model (compact, large, or huge). Try applying the
- /Gt compilation option to lower the threshhold.
-
- 3. Use the FAR keyword to move data out of DGROUP.
-
-
- 248. Error L2025 Name : Symbol Defined More than Once
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 7-DEC-1988 ArticleIdent: Q38820
-
- The following error is from "Linker Error Messages" in the manual
- "CodeView and Utilities", Section C.2, Page 368, and in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.4, Page 373:
-
- L2025 name : symbol defined more than once
-
- Remove the extra symbol definition from the object file.
-
- Nonfatal errors indicate problems in the executable file. LINK
- produces the executable file. Nonfatal error messages have the
- following format:
-
- location : error L2xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
- One way this error can be caused is by incorrectly using or omitting a
- keyword such as pascal. If the included function prototype has the
- keyword and the library routine does not, or vice versa, the linker
- reports that the function is defined more than once.
-
-
- 249. %TMP% in NEW_VARS.BAT Causes Fatal Error C1042
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran
- Last Modified: 12-DEC-1988 ArticleIdent: Q38839
-
- If you append new_vars.bat to your AUTOEXEC.BAT and your TMP
- environment variable is already set for specifying the drive,
- directory compiler, and linker to which temporary files should be
- written, %TMP% causes the following error message:
-
- Fatal-Error C1042: cannot open intermediate file -- no
- such file or directory.
-
- This message occurs because the TMP variable should specify only one
- directory.
-
- %TMP% appends any TMP directories already defined at that location.
- Generally, it is best not to have any %<environmental variable>%
- symbols in AUTOEXEC.BAT because it should be the first place the
- environment is defined.
-
-
- 250. Error L1126, Error L2043
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
- Last Modified: 19-DEC-1988 ArticleIdent: Q38979
-
- The information below describes linker-error messages L1126 and L2043.
-
- The following error is from "Linker Error Messages" in (1) the manual
- "CodeView and Utilities", Section C.2, Page 366, and in (2) the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.4, Page 374.
- It is also in (3) the file ERRMSG.DOC on Compiler Disk 1 for Microsoft
- C Version 5.10 and on the Setup Disk for Microsoft C Version 5.00,
- also in the file README.DOC on Disk 1 for Microsoft Macro Assembler
- Version 5.10, also in the file CVREADME.DOC on the CodeView for MS-DOS
- disk for Microsoft FORTRAN Version 4.10:
-
- (1)
- L1126 starting address __aulstart not found
-
- You tried to create a Quick library without linking with
- the required LIB library.
-
- (2)
- L2043 starting address __aulstart not found
-
- When you build a Quick library using the /Q option, the
- linker expects to find the symbol __aulstart defined as a
- starting address.
-
- (3)
- L2043 Quick Library support module missing
-
- When creating a Quick library, you did not link with the
- required QUICKLIB.OBJ module.
-
- Fatal errors cause the linker to stop execution. Fatal error messages
- have the following format:
-
- location : fatal error L1xxx: messagetext
-
- Nonfatal errors indicate problems in the executable file. LINK
- produces the executable file. Nonfatal error messages have the
- following format:
-
- location : error L2xxx: messagetext
-
- In these messages, location is the input file associated with the
- error, or LINK if there is no input file. If the input file is an OBJ
- or LIB file and has a module name, the module name is enclosed in
- parentheses.
-
-
- 251. Error U1188 Cannot Write to VM
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_util s_error
- Last Modified: 21-DEC-1988 ArticleIdent: Q39018
-
- The information below describes library-error message U1188.
-
- The following error is from "LIB Error Messages" in (1) the manual
- "CodeView and Utilities", Section C.3, Page 373, and in (2) the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.5, Page 379:
-
- U1188 cannot write to VM
-
- (1) Note the circumstances of the failure and notify Microsoft
- Corporation by using the Product Assistance Request form
- at the back of one of your manuals.
-
- (2) Note the circumstances of the failure and notify Microsoft
- Corporation, using the Product Assistance Request form at
- the back of this manual.
-
- IMPORTANT NOTE: This error can also occur when a temporary file
- cannot be created, possibly because the disk is full.
-
- Error messages generated by the Microsoft Library Manager, LIB, have
- one of the following formats:
-
- {filename | LIB} : fatal error U1xxx: messagetext
- {filename | LIB} : error U2xxx: messagetext
- {filename | LIB} : warning U4xxx: messagetext
-
- The message begins with the input-file name (filename), if one exists,
- or with the name of the utility. If possible, LIB prints a warning and
- continues operation. In some cases errors are fatal and LIB terminates
- processing.
-
-
- 252. Error U2157 Filename : Cannot Access File
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_util s_error
- Last Modified: 21-DEC-1988 ArticleIdent: Q39019
-
- The following error is from "LIB Error Messages" in the manual
- "CodeView and Utilities", Section C.3, Page 374, and in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.5, Page 380:
-
- U2157 filename : cannot access file
-
- LIB was unable to open the specified file.
-
- Error messages generated by the Microsoft Library Manager, LIB, have
- one of the following formats:
-
- {filename | LIB} : fatal error U1xxx: messagetext
- {filename | LIB} : error U2xxx: messagetext
- {filename | LIB} : warning U4xxx: messagetext
-
- The message begins with the input-file name (filename), if one exists,
- or with the name of the utility. If possible, LIB prints a warning and
- continues operation. In some cases errors are fatal and LIB terminates
- processing.
-
- A hyphen (dash, - ) in a subdirectory name in the path can cause this
- error; this error occurs because of a problem in LIB.
-
-
- 253. Error U2155 Modulename : Module Not In Library; Ignored
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_util s_error
- Last Modified: 21-DEC-1988 ArticleIdent: Q39020
-
- The following error is from "LIB Error Messages" in the manual
- "CodeView and Utilities", Section C.3, Page 374, and in the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.5, Page 380:
-
- U2155 modulename : module not in library; ignored
-
- The specified module was not found in the input library.
-
- Error messages generated by the Microsoft Library Manager, LIB, have
- one of the following formats:
-
- {filename | LIB} : fatal error U1xxx: messagetext
- {filename | LIB} : error U2xxx: messagetext
- {filename | LIB} : warning U4xxx: messagetext
-
- The message begins with the input-file name (filename), if one exists,
- or with the name of the utility. If possible, LIB prints a warning and
- continues operation. In some cases errors are fatal and LIB terminates
- processing.
-
- A hyphen (dash, - ) in a subdirectory name in the path can cause this
- error; this error occurs because of a problem in LIB.
-
-
- 254. Error U1005 Syntax Error: Colon Missing
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_make s_error
- Last Modified: 15-JAN-1990 ArticleIdent: Q39037
-
- The following error is from "MAKE Error Messages" in the manual
- "CodeView and Utilities", Section C.4, Page 376, and in the "Microsoft
- QuickC Compiler Programmer's Guide," Section D.6, Page 382:
-
- U1005 syntax error : colon missing
-
- A line that should be an outfile/infile line lacked a
- colon indicating the separation between outfile and
- infile. MAKE expects any line following a blank line to be
- an outfile/infile line.
-
- Note: MAKE expects a blank character or tab(s) after the colon between
- outfile and infile. If such a space is missing, this error occurs.
-
- Error messages displayed by the Microsoft Program Maintenance Utility,
- MAKE, have one of the following formats:
-
- {filename | MAKE} : fatal error U1xxx: messagetext
- {filename | MAKE} : warning U4xxx: messagetext
-
- The message begins with the input-file name (filename), if one exists,
- or with the name of the utility. If possible, MAKE prints a warning
- and continues operation. In some cases, errors are fatal and MAKE
- terminates processing.
-
- This problem can also be caused by using a NMAKE compatible make file
- with MAKE.
-
-
- 255. Error R6006 Bad Format on exec
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 21-DEC-1988 ArticleIdent: Q39045
-
- The following error is from "Run-Time Library Error Messages" in the
- "Microsoft C Optimizing Compiler User's Guide," Section E.4.1, Page
- 283, and in the "Microsoft QuickC Compiler Programmer's Guide,"
- Section D.3.2, Page 362:
-
- R6006 bad format on exec
-
- The file to be executed by one of the exec functions was
- not in the correct format for an executable file.
-
- These messages may be generated at run time when your program has
- serious errors. Run-time error-message numbers range from R6000 to
- R6999. A run-time error message takes the following general form:
-
- run-time error R6nnn
- - messagetext
-
- Errors R6005 through R6007 occur when a child process spawned by one
- of the exec library routines fails, and DOS could not return control
- to the parent process. This error indicates that not enough memory
- remained to load the program being spawned.
-
-
- 256. Error R6007 Bad Environment on exec
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 21-DEC-1988 ArticleIdent: Q39046
-
- The information below discusses the run-time error message R6007.
-
- The following error is from "Run-Time Library Error Messages" in the
- "Microsoft C Optimizing Compiler User's Guide," Section E.4.1, Page
- 283, and in the "Microsoft QuickC Compiler Programmer's Guide,"
- Section D.3.2, Page 362:
-
- R6007 bad environment on exec
-
- During a call to one of the exec functions, DOS determined
- that the child process was being given a bad environment
- block.
-
- These messages may be generated at run time when your program has
- serious errors. Run-time error-message numbers range from R6000 to
- R6999. A run-time error message takes the following general form:
-
- run-time error R6nnn
- - messagetext
-
- Errors R6005 through R6007 occur when a child process spawned by one
- of the exec library routines fails, and DOS could not return control
- to the parent process. This error indicates that not enough memory
- remained to load the program being spawned.
-
-
- 257. Error R6008 Not Enough Space for Arguments
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 11-JAN-1990 ArticleIdent: Q39047
-
- The information below discusses the run-time library error message
- R6008.
-
- The following error is from "Run-Time Library Error Messages" in (1)
- the "Microsoft C Optimizing Compiler User's Guide," Section E.4.1,
- Page 283, and in (2) the "Microsoft QuickC Compiler Programmer's
- Guide," Section D.3.2, Page 363:
-
- R6008 not enough space for arguments
-
- (1) See explanation under error R6009.
-
- (2) (no description given)
-
- These messages may be generated at run time when your program has
- serious errors. Run-time error-message numbers range from R6000 to
- R6999. A run-time error message takes the following general form:
-
- run-time error R6nnn
- - messagetext
-
- The following is the description for R6009 in the "Microsoft C
- Optimizing Compiler User's Guide":
-
- Errors R6008 and R6009 both occur at start-up if there is
- enough memory to load the program, but not enough room for
- the argv vector, the envp vector, or both. To avoid this
- problem, rewrite the _setargv or _setenvp routines (see
- Section 5.2.2, "Suppressing Command-Line Processing," for
- more information).
-
-
- 258. Error R6013 Illegal Far Pointer Use
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_error
- Last Modified: 21-DEC-1988 ArticleIdent: Q39050
-
- The information below explains the run-time library error message
- R6013.
-
- The error below is from "Run-Time Library Error Messages" in the
- "Microsoft QuickC Compiler Programmer's Guide," Section D.3.2, Page
- 363. It is not documented in the "Microsoft C Optimizing Compiler
- User's Guide" or in ERRMSG.DOC for Versions 5.00 and 5.10.
-
- The following is the error:
-
- R6013 Invalid far pointer reference
-
- An out-of-range far pointer was used in the program.
-
- This error occurs only if pointer checking is in effect
- (that is, if the program was compiled with the Pointer
- Check option in the Compile dialog box, the /Zr option on
- the QCL command line, or the pointer_check pragma in
- effect).
-
- These messages may be generated at run time when your program has
- serious errors. Run-time error-message numbers range from R6000 to
- R6999. A run-time error message takes the following general form:
-
- run-time error R6nnn
- - messagetext
-
- According to the README.DOC found on the Product Disk for Microsoft
- QuickC Version 1.00 and on the Setup Disk for QuickC Version 1.01, the
- run-time error message R6013 has changed as follows:
-
- R6013 illegal far pointer use
-
-
- 259. C1004: Unexpected EOF
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 12-DEC-1988 ArticleIdent: Q39088
-
- The fatal-compiler error "C1004: Unexpected EOF" can be caused by
- failing to end a line with a <CR>. On pure C language statements the
- compiler ignores white space, but on statements with directives a <CR>
- is needed.
-
- This will occur if the following include file is used in a program:
-
- #include <stdio.h><CR>
- #define YES 1<CR>
- #define NO 0
-
- Without the <CR> after the third line, error C1004 will be produced by
- the compiler.
-
-
- 260. Using _gettextposition and printf.
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 12-DEC-1988 ArticleIdent: Q39089
-
- When the C graphic routines are being used in a program, they should
- be used for all output to the screen, including text output. Other C
- run-time functions for output should not be used.
-
- If a C program uses the run-time function _gettextposition, the
- function _outtext should be used to output text to the screen. Using
- the function printf will cause overwritting of text or blank lines to
- be inserted on the video screen.
-
- The following program will result in unpredictable output:
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <graph.h>
-
- main()
- {
- struct rccoord rcoord;
- system("cls");
- printf("11\n");
- printf("22222222\n");
- printf("333333\n");
- printf("fourth line\n");
- printf("fifth line\n");
-
- rcoord=_gettextposition();
-
- printf("6666\n");
- printf("77777777\n");
- }
-
- The work around is use _outtext instead of printf.
-
-
- 261. Pattern Format for _setfillmask
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | _getfillmask
- Last Modified: 29-DEC-1988 ArticleIdent: Q39215
-
- The _setfillmask function sets a background pattern using repeated
- 8-by-8 pixel patterns. The mask consists of an 8-byte character array.
-
- The following example illustrates a pixel pattern:
-
- Powers of 2
-
- decimal: 128 64 32 16 08 04 02 01
- hex: 80 40 20 10 08 04 02 01
- --------------------------------
- byte 1 | 1 1 1 1 = 0x66
- byte 2 | 1 1 1 1 = 0x66
- byte 3 | = 0x00
- byte 4 | 1 = 0x08
- byte 5 | 1 1 = 0x18
- byte 6 | 1 1 = 0x81
- byte 7 | 1 1 = 0x42
- byte 8 | 1 1 1 1 = 0x3C
-
- The character array for this particular fill mask would be declared in
- a C program as follows:
-
- unsigned char *maskarray = "\x66\x66\x00\x08\x18\x81\x42\x3C";
-
- When the fill mask above is used with _setfillmask and a graphics
- function such as _rectangle or _ellipse, the pattern will create
- a continuous field of faces.
-
-
- 262. Opening Files Using Command Line Arguments.
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 29-DEC-1988 ArticleIdent: Q39216
-
- File names may be specified as command line arguments to a C
- program. The example below uses the first command line argument as
- the name of the input file and the second as the name of the output
- file. The parameter argv, which is declared by main(), is used to
- access the command line arguments.
-
- In the example below, the following occurs:
-
- 1. argv[0] will contain a full path to the source (exe) file
-
- 2. argv[1] will contain the first argument, which is the input file
- name
-
- 3. argv[2] will contain the second argument, which is the output file
- name
-
- The following program opens a file for reading and writing and
- also prints argv[0], argv[1], and argv[2]. Note that argc is checked
- to make sure that two argument strings were actually passed and that
- the file pointers are checked to make sure that the files were
- actually opened.
-
- #include <stdio.h>
-
- main (argc,argv)
- int argc;
- char *argv[];
- {
- FILE *in, *out;
-
- if (argc < 3) { /* enough arguments? */
- puts("Usage: demo infile outfile");
- exit(1);
- }
-
- printf("%s\n", argv[0]);
- printf("%s\n", argv[1]);
- printf("%s\n", argv[2]);
-
- in = fopen (argv[1],"r");
- out = fopen (argv[2],"w");
-
- if (in == NULL || out == NULL) {
- puts("Could not open both files");
- exit(2);
- }
- puts("Opened both files OK");
- exit(0);
- }
-
- The command line: "C:\>demo infile outfile" produces the
- following output if infile and outfile can be opened:
-
- C:\demo.exe
- infile
- outfile
- Opened both files OK
-
-
- 263. Example of C Calling a MASM Procedure
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | h_masm
- Last Modified: 29-DEC-1988 ArticleIdent: Q39309
-
- The sample code below demonstrates a C program calling a MASM
- procedure. The C code declares an integer and passes the integer to
- the MASM procedure called mixed(). The mixed() function has an integer
- return value. The C code is compiled in the large-memory model and the
- MASM code is assembled with the /ML option.
-
- The following is the code:
-
- #include <stdio.h>
-
- int retval, value, foo;
- extern int mixed(int);
-
- main() {
- value = 35;
- foo = 25;
- retval = 0;
- retval = mixed(foo);
- printf("%d\n%d\n",retval,value);
- }
-
- DOSSEG
- .MODEL LARGE C
- .STACK 100h
- .DATA
- Dw 0
- .FARDATA
- EXTRN _value:WORD
- .CODE
- PUBLIC _mixed
- _mixed PROC
- push bp
- mov bp,sp
- ; access and change _value
- mov ax, seg _DATA
- mov ds,ax
- mov ax,SEG _value
- mov es,ax
- mov es:_value,10h
- ; return the passed variable
- mov ax,[bp+6]
- pop bp
- ret
- _mixed ENDP
- END
-
-
- 264. Selective Initialization of Array Elements Not Allowed
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 29-DEC-1988 ArticleIdent: Q39310
-
- The ANSI C standard does not allow selective initialization of
- array elements with the following syntax:
-
- char MyArray[10] = {'a','b',,'d',,'f','g',,'i','j'};
-
- This attempt at selective initialization is illegal and will generate
- a "Syntax Error" at compile time. The following two declarations will
- compile and are valid declarations for Microsoft C Version 5.10:
-
- 1. The initialization of all the elements of the array is as follows:
-
- char MyArray[10] = {'a','b','c','d','e','f','g','h','i','j'}
-
- 2. The initialization of the front characters in the array is as
- follows:
-
- char MyArray[10] = {'a','b','c','d','e'}
-
-
- 265. Use 0x80 to Access Drive C when Calling _bios_disk
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QUICKC
- Last Modified: 29-DEC-1988 ArticleIdent: Q39311
-
- Question:
-
- I am using the _bios_disk function to access my fixed disk. I have
- initialized the drive parameter to 2 to specify my fixed-disk drive.
- This function does not seem to be accessing my fixed disk. What am I
- doing wrong?
-
- Response:
-
- The first floppy drive in a computer is identified as drive 0 with
- additional floppy drives numbered sequentially. However, the first
- fixed disk is identified as drive 0x80 (128 decimal) with additional
- partitions numbered sequentially. Therefore, call _bios_disk with the
- drive parameter set to 0x80 to access the first fixed disk.
-
- The following is an example:
-
- Logical Drive diskinfo.drive
- A 0
- B 1
- C 0x80
- D 0x81
- E 0x82
- . .
- . .
- . .
-
-
- 266. Commenting Out Blocks of Code and Comments for Debugging
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 29-DEC-1988 ArticleIdent: Q39312
-
- The C language does not support the use of nested comments. This might
- appear to be a limitation in cases where it is necessary, perhaps for
- debugging purposes, to comment out a block of code which contains
- comments. However, this situation can be overcome by using the
- much more powerful preprocessor commands #if and #endif.
-
- The #if preprocessor command evaluates a constant expression to either
- true (which has the value 1) or false (which has the value 0) to
- perform conditional compilation. If the expression equates to true,
- the code segment will be compiled. If it equates to false, it will be
- ignored by the compiler. Therefore, if the syntax below is used,
- the enclosed block of code will be forever ignored by the compiler
- giving a convenient method of effectively commenting out a block of
- code.
-
- Since the expression in the #if can be any constant expression, you
- can make complicated tests. You can even use the /Dconst=value
- switch on the CL command line to set a preprocessor symbol which will
- include or exclude the debugging code when you compile. This
- technique is described more fully on pages 75-77 of the Microsoft C
- Optimizing Compiler User's Guide.
-
- The following is a simple example:
-
- #define OUT 0
-
- #if OUT /* will always equate to "false" */
-
- /* code and comments that you wish to remove are here */
-
- #endif
-
-
- 267. #pragma pack() Affects Declarations, not Definitions
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 5-JAN-1989 ArticleIdent: Q40027
-
- Question:
-
- I need to use the preprocessor directive "#pragma pack()" to control
- how structure data are "packed" into memory. However, I don't know
- where to stick it. Should I place it before a declaration (creating a
- type) or before a definition (allocating space)?
-
- Response:
-
- The pack pragma affects declarations; not definitions. Place #pragma
- pack() prior data declarations.
-
- The following program demonstrates usage of #pragma pack():
-
- /* Elements of variables of type struct x will be byte-aligned. */
- #pragma pack(1)
- struct x { int a; char b; int c; };
-
- /* Elements of variables of type struct y will be word-aligned. */
- #pragma pack(2)
- struct y { int a; char b; int d; };
-
- /* The pragma below does NOT affect the definitions that follow. */
- #pragma pack(4)
-
- struct x X;
- struct y Y;
-
- void main (void)
- { /* dummy main */ }
-
-
- 268. Error C2001: Newline in Constant for a String on Multiple Line
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 9-JAN-1989 ArticleIdent: Q40160
-
- If the program below, which contains a string literal that is
- incorrectly split over multiple lines, is compiled, the following
- error will occur:
-
- error C 2001: newline in constant
-
- The incorrect program is as follows:
-
- #include <stdio.h>
- main() {
- printf("\n %s
- %s
- %s",
- "this", "is", "it");
- }
-
- As indicated on Page 23 of the "Microsoft C for the MS-DOS Operating
- System: Language Reference" for Version 5.10, there are two methods to
- form a string that takes up more than one line.
-
- The best method is to change the format string as in the following
- example (this work because strings separated only by spaces, tabs,
- and/or newlines are concatenated):
-
- #include <stdio.h>
- main() {
- printf("\n %s"
- "%s"
- "%s",
- "this", "is", "it");
- }
-
- The older and less-prefered method is to use continuation lines by
- typing a backslash followed by a carriage return at the end of a line,
- as in the following example:
-
- printf("\n %s\
- %s\
- %s",
- "this", "is", "it");
-
- This is not as good as the previous example because the spaces at the
- beginning of the continuation line become part of the string, unlike
- example one.
-
-
- 269. Simple Example Using _bios_serialcom
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 29-DEC-1988 ArticleIdent: Q39501
-
- Below is an example of using the C run-time library function
- _bios_serialcom to transmit and receive a single character over the
- serial-communications port COM1:.
-
- The _bios_serialcom routine simply calls the PC's ROM BIOS routines.
- On most PC's, these routines are not interrupt-driven nor buffered.
- As a result, characters may be lost when receiving very high-speed
- transmissions and/or if a significant amount of processing occurs
- between status checks and reads. Although Microsoft does not provide
- interrupt-driven serial I/O routines with our C compilers, there are
- several third-parties which do. A partial listing is available in
- the Language Support Directory which comes with the compiler.
-
- For additional information about ROM BIOS calls, please refer to "IBM
- ROM BIOS" by Ray Duncan, published by Microsoft Press. For examples of
- serial communication programs written in assembler, please refer to
- the MS-DOS Encyclopedia.
-
- The following program is a simple example which sends and receives one
- character to/from COM1:
-
- #include <stdio.h>
- #include <bios.h>
-
- void main(void)
- {
- unsigned com1_status;
- unsigned com1_send;
- unsigned com1_rec;
- unsigned com1_init;
- int result, mask;
-
- /* open serial port at 1200 baud, 8 data bits,
- ** No parity, 1 stop bit */
- com1_init = _bios_serialcom(_COM_INIT, 0,
- _COM_CHR8 | _COM_NOPARITY | _COM_STOP1 | _COM_1200);
- printf("Init status: 0x%4.4X\n", com1_init);
-
- /* send an '*' to com1 */
- com1_send = _bios_serialcom(_COM_SEND, 0, '*');
- printf("Send status: 0x%4.4X\n", com1_send);
-
- mask = 0x6100;
- /* value used to mask:
- * bits 0-7 are related to modems,
- * bits 8-15 are for port status,
- * check to see that the following bits are set:
- * 8 (data ready)
- * 13 (Transmission-hold register empty)
- * 14 (Transmission-shift register empty)
- */
-
- /* check the status */
- com1_status = _bios_serialcom(_COM_STATUS, 0, 0);
- printf("COM1 status: 0x%4.4X\n", com1_status);
-
- /* wait until a character is ready */
- do {
- /* check the status */
- com1_status = _bios_serialcom(_COM_STATUS, 0, 0);
-
- /* mask off the low order byte of com1_status */
- com1_status = com1_status & 0xFF00;
- } while( (mask & com1_status) == 0);
-
- /* get a character */
- com1_rec = _bios_serialcom(_COM_RECEIVE, 0, 0);
- printf("Read status: 0x%4.4X\n", com1_rec);
-
- /* print the character we just received */
- result = com1_rec & 0x00FF;
- printf("Character: 0x%2.2X = %c\n", result, (char)result);
- }
-
-
- 270. Wrong Syntax for fopen Mode Argument Gives NULL Return Value
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 29-DEC-1988 ArticleIdent: Q39602
-
- In the second argument to the fopen function, if the specification of
- the mode character t (text) or b (binary) is before the file-access
- type r (read), w (write), or a (append), no compilation errors occur.
- However, at run-time, fopen fails to open the file and returns NULL.
-
- Page 275 of the "Microsoft C Run-Time Library Reference" states that
- the mode character is to be appended to the character string for the
- type argument. If, instead, the mode character is placed before the
- beginning of the type argument, then fopen fails. An example follows.
-
- Please note that the string which is passed as the second parameter
- to fopen could be a variable string as well as a constant string.
- Since the variable string could be constructed at run-time, it is
- impossible to check for this error at compile time.
-
- Also note that strings of the form below are explicitly prohibited on
- page 275 of the C Runtime Library Reference.
-
- The program below demonstrates this behavior. It prints "failed"
- and does not open a file. If the second argument to fopen is changed
- to "wt", then it prints "succeeded" and the file is opened.
-
- The following is the program:
-
- #include <stdio.h>
- FILE *s;
- void main(void);
- void main(void)
- {
- if ((s = fopen("test.dat","tw")) == NULL)
- printf("fopen failed\n");
- else
- printf("fopen succeeded\n");
- }
-
-
- 271. Example of Using Formatting with _outtext
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QUICKC
- Last Modified: 29-DEC-1988 ArticleIdent: Q39783
-
- When programming with the Microsoft graphics library, the printf
- function can be used, but it is not recommended. Instead, to do any
- desired formatting, the _outtext function should be used with a prior
- call to sprintf. You should not mix printf() calls with _outtext()
- calls.
-
- The user-defined _outtextf function demonstrated in the program below
- performs formatting and printing in one function. This function
- simplifies conversion of non-Microsoft C graphics-compatible source
- code to Microsoft-compatible code. An intelligent text editor could
- simply do a global search and replace "printf" to "_outtextf".
-
- This following program defines and demonstrates the function "_outtextf":
-
- #include <stdio.h>
- #include <graph.h>
- #include <stdarg.h>
-
- int _outtextf (char *format,...);
- void main (void);
-
- void main (void)
- { /* Clear the screen and display "Hello, world #87!" */
- _clearscreen (_GCLEARSCREEN);
- _outtextf ("Hello, %s #%d!","world",87);
- }
-
- int _outtextf (char *format,...)
- { va_list arglist;
- char buffer[150]; /*Must be large enough to hold formatted string*/
- int retval;
-
- va_start (arglist,format);
- retval = vsprintf(buffer,format,arglist);
- va_end (arglist);
-
- _outtext (buffer);
- return (retval);
- }
-
-
- 272. "D" Incorrectly Defined as a printf/scanf Format Specifier
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 29-DEC-1988 ArticleIdent: Q39784
-
- On Page 80 of the "Microsoft C 5.1 (and 5.0) Quick Reference Guide"
- (spiral bound), the capital letter "D" is incorrectly defined as a
- printf/scanf format specifier representing a signed long-decimal
- integer. The printf/scanf format specifier for a long-decimal integer
- is "ld". Using %D will print/return garbage characters.
-
-
- 273. Using _getvideoconfig for Analog Monitors
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q43536
-
- In the Microsoft C 5.10 Optimizing Compiler Run-Time Library, the
- function _getvideoconfig does not make a distinction between an analog
- color monitor and an analog monochrome monitor. For both of these
- configurations, it puts the value _ANALOG in the "monitor" field of
- the struct "videoconfig." _ANALOG is a manifest constant defined in
- the include file GRAPH.H to be 0x0018.
-
- The function _getvideoconfig is enhanced in QuickC Version 2.00 so
- that it recognizes analog monitors as being color or monochrome.
- There are two additional manifest constants defined in the new
- GRAPH.H: _ANALOGCOLOR (defined to be 0x0010) and _ANALOGMONO
- (0x0008).
-
-
- 274. Time Functions Calculate for Daylight Savings Time
-
- Product Version(s): 5.00 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 30-DEC-1988 ArticleIdent: Q39908
-
- The Microsoft time functions calculate for daylight savings time. In
- particular, mktime will set the hour ahead or back one hour according
- to the rules of daylight savings time. The only way to change the
- dates that the time functions use in calculating daylight savings time
- is to get the run-time library source code available for the time
- functions and modify the routine _isindst() in the file tzset.c.
-
-
- 275. _scanf and _cscanf always Echo to the Screen
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 30-DEC-1988 ArticleIdent: Q39909
-
- The following is on Page 177 of the "Microsoft C 5.1 Optimizing
- Compiler Run-Time Library Reference" manual:
-
- Note:
- While scanf normally echoes the input character, it will not
- do so if the last call was to ungetch.
-
- This process does not appear to work correctly. The following code
- sample uses _getch() to get a character from the keyboard, then calls
- _ungetch(ch) to disable echoing to the screen before calling _cscanf.
- The keyboard input echoes to the screen regardless of the call to
- _ungetch. If _cscanf is replaced with _scanf, it still echoes to the
- screen.
-
- The following program calls _ungetch, then echoes the filename to
- the screen when it is read by _scanf; although, according to the
- documentation, it should not echo:
-
- ------------------------------------------------------------
- #include <conio.h>
- #include <stdio.h>
- #include <ctype.h>
-
- int result; /* return value from _scanf */
- char buff2[20]; /* buffer for filename */
- int ch; /* character returned by _getch*/
-
- main() /* begin executable code */
-
- {
- ch = getch(); /* read a keyboard character */
-
- cprintf ("please enter file name");
- ungetch(ch); /* call to _ungetch */
- result = scanf("%19s", buff2); /* call _scanf */
- printf ("\n Number of correctly matched input"
- "items = %d\n", result); /* print # of input items */
- }
-
-
- 276. C4047 Error Message when Initializing Unions
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 30-DEC-1988 ArticleIdent: Q39910
-
- If an attempt is made to initialize the second element of a union at
- declaration time (rather than in the code), the following warning
- is generated:
-
- C4047:'initialization' - different levels of indirection
-
- This error conforms to the ANSI standard, which assumes that the
- initialization is directed at the first element of the union, and
- reports, therefore, that the initializing values are of an incorrect
- type. If an attempt is made to initialize both the first and second
- element at declaration time, the same warning results.
-
- The following program demonstrates this error:
-
- -----------------------------------------------------------------
- union TEST {
- struct{
- int a;
- int b;
- int c;
- } one; /* union element #1 */
- struct {
- char *ptr1;
- char *ptr2;
- char *ptr3;
- char *ptr4;
- } two; /* union element #2 */
- }u;
-
- char ch1[10], ch2[10], ch3[10],ch4[10] ;
-
- union TEST test ={{1,2,3}, /* initialize element #1*/
- {ch1,ch2,ch3,ch4} /* attempt to initialize #2 */
- };
-
- main()
- {
- }
- ----------------------------------------------------------------
-
- The above program fails with the error C4047. The following
- initialization also fails with the same error:
-
- union TEST test = {ch1,ch2,ch3,ch4}
-
- However, an attempt to initialize the first element of the union will
- be successful, as follows:
-
- union TEST test = {1,2,3}
-
- If it is necessary to initialize the second element of a union, we
- suggest that you change the order of your union members, so that the
- element that requires initialization appears as the first element of
- the union.
-
-
- 277. C 5.10 Setup Gives U1203 Error under DOS Versions 2.x
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 30-DEC-1988 ArticleIdent: Q39911
-
- When running the setup program for C Version 5.10 under DOS Versions 2.x,
- the following error is generated:
-
- U1203 : invalid object module
-
- This error occurs because the library manager, LIB.EXE, is bound.
- Under DOS Versions 2.x, bound programs can only be run from within the
- current working directory. Giving an fully qualified path will cause
- the error.
-
- Moving LIB.EXE into the current directory may avoid this problem.
-
- More information will be posted as it becomes available.
-
-
- 278. Misleading Information about Linker Options with /link
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 30-DEC-1988 ArticleIdent: Q39915
-
- Pages 120-123 of the "Microsoft C 5.1 Optimizing Compiler User's
- Guide" describe options that can be used with the linker. The manual
- states that these options have equivalent options that can be used on
- the compiler command line. This subject can be confusing.
-
- If you are compiling and linking through the CL driver, then compile
- options are available to pass options to the link command line. For
- example, the /Fm option passes the /MAP option to the linker and a
- map file is produced.
-
- If a compiler option is not available for the linker option you want
- to pass to the link command line, the /link compile option can be
- used. The linker option can be given after /link option on the CL
- command line.
-
-
- 279. Using _dos_findfirst to Get the Time and Date
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 30-DEC-1988 ArticleIdent: Q39916
-
- The code below illustrates how to extract the time and the date out of
- the C run-time function _dos_findfirst. The program prints out the
- time and the date of the creation of the file "test".
-
- This information also applies to QuickC.
-
- The time at which the file was last written is returned as a binary
- value in a word formatted as follows:
-
- Bits Meaning
-
- 0-4 Number of seconds DIVIDED BY TWO
- (to find actual number of seconds, multiply by two)
- 5-10 Minutes
- 11-15 Hours, based on a 24-hour clock
-
- The date at which the file was last written is returned as a binary
- value in a word formatted as follows:
-
- Bits Meaning
-
- 0-4 Day of the month
- 5-8 Month (1 = January and so on)
- 9-15 Number of the year minus 1980
-
- The following is a sample code:
-
- #include <dos.h>
- #include <stdio.h>
-
- struct {
- unsigned biseconds: 5; /* in units of TWO seconds */
- unsigned minutes: 6;
- unsigned hours: 5;
- } *ptime;
-
- struct{
- unsigned day: 5;
- unsigned month: 4;
- unsigned year: 7;
- } *pdate;
-
- struct find_t c_file;
-
- main()
- {
- _dos_findfirst ("test", _A_NORMAL, &c_file);
-
- system("cls");
-
- ptime = &c_file.wr_time;
- pdate = &c_file.wr_date;
-
- printf ("Created at %u:%u:%u",\
- ptime->hours, ptime->minutes, ptime->seconds * 2);
- /* NOTE: seconds are divided by two when stored,
- so we have to multiply by two to get
- the proper value.... */
-
- printf ("on %u-%u-%u.",\
- pdate->month, pdate->day, pdate->year);
- }
-
- The program might produce the following output (depending on when the
- file "test" was created):
-
- Created at 10:32:28 on 12-19-8
-
- Note that the seconds field of the time will always be even.
-
- For more information on function _dos_findfirst, see "Microsoft C 5.1
- Optimizing Compiler Run-Time Library Reference," starting on Page 194.
-
-
- 280. Open() Will Not Ignore Append Path
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 9-JAN-1989 ArticleIdent: Q40183
-
- DOS allows you to set an APPEND path to locate data files. Microsoft C
- library functions such as open and fopen will not ignore the APPEND
- statement, even if a full pathname is given to the specific function.
- This is expected behavior. If you wish to have the APPEND path
- ignored, you will have to write your own low-level open function, or
- ensure that the APPEND path is removed before your program is run.
-
-
- 281. LINK4 Is Not Included in C 5.10 or MASM 5.10 Packages
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | h_masm PMWIN
- Last Modified: 13-JAN-1989 ArticleIdent: Q40236
-
- LINK.EXE, the incremental linker provided with the Windows Software
- Development Kit for DOS, is not included with C Version 5.10 or MASM
- Version 5.10, contrary to the statement on Page 82 of the January 1989
- issue of the "Microsoft Systems Journal."
-
- A bound linker, LINK.EXE Version 5.01.20, which may be used under DOS
- or OS/2, comes with MASM Version 5.10 as well as the real-mode linker
- Version 3.64 for DOS only. The C Version 5.10 retail package comes with
- the bound linker Version 5.01.21 and the real-mode linker Version
- 3.65.
-
- To link under OS/2, use the bound linker with the latest version
- number you have available. To prepare for incremental linking with the
- ILINK.EXE utility under OS/2, use LINK.EXE with the option /INC. See
- the C Version 5.10 "Update (CodeView and Utility)" section of the
- "Microsoft C 5.1 Optimizing Compiler CodeView and Utilities" manual,
- or the "Microsoft Macro Assembler 5.1 Updates and Microsoft Editor"
- manual for more information on incremental linkage and the ILINK.EXE
- utility.
-
- LINK with /INC and ILINK have failed to work correctly for Windows
- program development under DOS, contrary to our documentation. DOS
- Windows developers should use LINK4, which comes with the Windows SDK.
-
- The ILINK utility should only be used under OS/2 for creating OS/2
- programs.
-
-
-
- 282. Accessing I/O Ports under OS/2 Protected Mode
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | COM1 COM2 serial communication
- Last Modified: 5-JAN-1989 ArticleIdent: Q39973
-
- Problem:
-
- I am trying to use the inp(), inpw(), outp(), and outpw() routines in
- the Microsoft C Version 5.10 run-time library. Every time I run my
- program I get the following message:
-
- SYS1943: A program caused a protection violation.
-
- Response:
-
- To read from or write to ports under OS/2 protected mode you must have
- a .DEF module-definition file that gives IOPL (input/output privilege)
- to the _IOSEG segment. Also, if the intrinsic (/Oi) switch is used
- during compilation, the segments that contain the port functions must
- be given IOPL. You can check the .MAP file for the associated segment
- name or compile with the /NT switch to manually name the segment.
-
- The following must be in your .DEF file if /Oi was not used:
-
- SEGMENTS
- _IOSEG CLASS 'IOSEG_CODE' IOPL
-
- If /Oi was used, the following must be in your .DEF file:
-
- SEGMENTS
- (segment name) IOPL
-
- Note: Segments that have IOPL cannot make system calls. If you do,
- you will generate a GP fault, a general protection violation. This
- behavior is discussed on Page 239 of Letwin's "Inside OS/2."
-
-
- 283. Error C2177: Constant Too Big
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 9-JAN-1989 ArticleIdent: Q39974
-
- The code below produces compiler error "C2177 : constant too big,"
- even though variable p is an unsigned long. The compiler does not
- generate this error if the number is 2,147,483,647 (maximum signed
- long possible) or less. Casting p to an unsigned long or putting L
- (for long) on the end of the number had no effect.
-
- This information also applies to QuickC.
-
- The following example demonstrates the error:
-
- #include <stdio.h>
- main()
- {
- unsigned long p;
- p = 4294967295; /* maximum unsigned long */
- printf("%lu is the maximum unsigned long.",p);
- }
-
- According to the include file limits.h, to declare something as
- unsigned long, one must use the hexadecimal form if the number will be
- greater than 2,147,483,647. The code should be changed to the following:
-
- #include <stdio.h>
- main()
- {
- unsigned long p;
- p = 0xffffffff;
- printf("%lu is the maximum unsigned long.",p);
- }
-
- The code will produce the following output:
-
- 4294967295 is the maximum unsigned long.
-
-
- 284. Dynamic Allocation for Two Dimensional Arrays
-
- Product Version(s): 4.00 5.x | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 4-JAN-1989 ArticleIdent: Q39976
-
- Question:
-
- How can I dynamically allocate memory for a two dimensional array?
-
- Response:
-
- The best method depends on the flexibility needed and the amount of
- information concerning the array known at coding time. The examples
- below set up two dimensional arrays of characters. Any element can be
- accessed with double sub-scripts, such as array[i][j]. Symbols in
- uppercase are constants, while those in lowercase are variables.
-
- If one of the dimensions of the array is known, either of the
- following two methods can be used. The first example creates more
- overhead due to the number of malloc calls, but it is more flexible
- because each malloc can be of a different size.
-
- The following is the first example:
-
- char *array[DIM_ONE];
- int i;
-
- for (i = 0; i < DIM_ONE; i++) {
- array[i] = (char *)malloc(sizeof(char) * dim_two);
- if (array[i] == NULL) {
- printf("Not enough memory for columns in row %d!\n", i);
- exit(1);
- }
- }
-
- The following is the second example:
-
- char *array[DIM_ONE];
- int i;
-
- array[0] = (char *)malloc(sizeof(char) * DIM_ONE * dim_two);
- if (array[0] == NULL) {
- printf("Not enough memory for columns!\n");
- exit(1);
- }
- for (i = 1; i < DIM_ONE; i++) {
- array[i] = (array[0] + (i * dim_two));
- }
-
- If neither of the dimensions is known at coding time, one of the
- following two methods can be used. The pros and cons of each example
- are the same as those for the previous examples.
-
- The following is the third example:
-
- char **array;
- int i;
-
- array = (char **)malloc(sizeof(char *) * dim_one);
- if (array == NULL) {
- printf("Not enough memory for rows!\n");
- exit(1);
- }
- for (i = 0; i < dim_one; i++) {
- array[i] = (char *)malloc(sizeof(char) * dim_two);
- if (array[i] == NULL) {
- printf("Not enough memory for columns in row %d!\n", i);
- exit(1);
- }
- }
-
- The following is the fourth example:
-
- char **array;
- int i;
-
- array = (char **)malloc(sizeof(char *) * dim_one);
- if (array == NULL) {
- printf("Not enough memory for rows!\n");
- exit(1);
- }
- array[0] = (char *)malloc(sizeof(char) * dim_one * dim_two);
- if (array[0] == NULL) {
- printf("Not enough memory for columns!\n");
- exit(1);
- }
- for (i = 1; i < dim_one; i++) {
- array[i] = (array[0] + (i * dim_two));
- }
-
-
- 285. Chmod() on an Open File
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 16-MAY-1989 ArticleIdent: Q40349
-
- When a file has been opened, it is not valid to perform a chmod() on
- the file. Although some operating systems (for example, UNIX) allow a
- program to change the permission of a file while it it open, MS-DOS
- requires the file to be closed before performing this function.
- Unusual results can occur, particularly when SHARE.EXE is installed,
- if an attempt is made to chmod() on an open file. One of the results
- is an error indicating the file is full, when only 1 byte is written
- to an empty file.
-
-
- 286. _getimage Buffer May Be Huge (Larger than 64K)
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 16-JAN-1989 ArticleIdent: Q40350
-
- The graphics functions _getimage and _putimage may be used to store
- and display graphic images that require a buffer size larger than 64K.
- Even though these functions specify that the storage buffer is a far
- pointer, _getimage and _putimage internally treat the buffer as huge
- and do 32-bit address arithmetic.
-
- The following program demonstrates using the image functions on a huge
- image.
-
- /********************************************************************
- * Example program to demonstrate using the functions _getimage and *
- * _putimage on a huge image. *
- ********************************************************************/
-
- #include <stddef.h>
- #include <malloc.h>
- #include <process.h>
- #include <graph.h>
-
- void main (void)
- { long size;
- char far *image;
-
- /* Put the display in a VGA mode and allocate a huge buffer. */
- if (_setvideomode(_VRES16COLOR)==0)
- { _outtext ("Video mode not supported!\n");
- exit (0);
- }
-
- /* In _VRES16COLOR, size is 153604. */
- size = _imagesize(0,0,639,479);
-
- if ( (image=halloc(size,1)) == NULL)
- { _outtext ("Not enough memory for buffer!\n");
- exit (0);
- }
-
- /* Draw a couple shapes and capture the screen. */
- _ellipse (_GBORDER,0,0,639,479);
- _rectangle (_GBORDER,0,0,639,479);
- _getimage (0,0,639,479,image);
-
- /* Clear the screen and redraw the image. */
- _clearscreen (_GCLEARSCREEN);
- _putimage (0,0,image,_GOR);
-
- hfree (image);
- }
-
-
- 287. Call _setvideomode before Calling _imagesize
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 16-JAN-1989 ArticleIdent: Q40351
-
- Problem:
-
- I am using the _imagesize function to determine the size required to
- store a graphics image. However, this function is not returning the
- expected result.
-
- Response:
-
- The _imagesize function calls _getvideoconfig to determine the number
- of bits required to store a pixel given the CURRENT video mode. If you
- are calling _imagesize prior to calling _setvideomode, an unexpected
- result is returned by _imagesize.
-
- In summary, do the following in order:
-
- 1. _setvideomode
-
- 2. _imagesize
-
- 3. _getimage and putimage
-
-
- 288. Operation of scanf When Using the Width Option in the Format
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-MAY-1989 ArticleIdent: Q40357
-
- The scanf run-time library function under Microsoft C allows the
- specification of the width that you would like to read in from the
- input device. Some examples of this width formatting are as follows:
-
- scanf ("%10s", buffer); /* read ten chars into buffer[] */
- scanf ("%5d", &i); /* read five digits of a number into i */
-
- When using width parameters in the format, the first n digits are read
- into the address specified.
-
- When used with a character string, the width parameter performs as
- follows:
-
- char buffer[15];
- scanf ("%10s", buffer);
-
- The first 10 characters are read, and a NULL terminator is added to
- the end of the string.
-
- When used with an integer or float, scanf always reads the first n
- characters (including decimal if in a float) specified with the width
- format. Entering Invalid characters (e.g. a decimal in an integer, any
- alphabetic character) causes the termination and failure of the read.
-
-
- 289. Bit-Shift Function in C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 16-MAY-1989 ArticleIdent: Q40358
-
- Question:
-
- How do I rotate, rather than shift, bits in a word? I don't want to
- lose any bits as happens when I shift.
-
- Response:
-
- Use the _rotl and _rotr functions in the C Runtime Library. These
- are described in the "Microsoft C Run-Time Library Reference."
-
-
- 290. Turning the Scroll Lock On
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 16-JAN-1989 ArticleIdent: Q40359
-
- The following code illustrates how to turn the Scroll Lock on in
- your program. Note: This code is only for use under DOS. Running
- it under OS/2 will cause a protection violation. Use the OS/2
- FAPI function KbdSetStatus to set the status of shift flags when
- writing programs which will run under OS/2 or be bound to run under
- both DOS and OS/2.
-
- #include <stdio.h>
- main()
- {
- /* Get the address of the keyboard status byte */
- char far *kbdstat=0x00000417L;
-
- char scrollmask=0x10;
-
- /* OR *kbdstat with scrollmask to set bit 4 in the
- keyboard status byte to 1 */
-
- *kbdstat= *kbdstat | scrollmask;
- }
-
- Additional information on keyboard status can be found in the Peter
- Norton "Programmer's Guide to the IBM PC and PS/2." The above information
- also applies to QuickC.
-
-
- 291. Incomplete Memory Model Switch in User's Guide Example
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 16-MAY-1989 ArticleIdent: Q40375
-
- The following compile command line given on Page 158, Section 6.7, of
- the "Microsoft C 5.1 Optimizing Compiler User's Guide" is incorrect:
-
- CL /As /Au /ND DATA1 PROG1.C
-
- This line should read as follows:
-
- CL /AS /Au /ND DATA1 PROG1.C
-
- If a program is compiled with /As rather than /AS, the following error
- will be issued:
-
- Command line error : D2013 incomplete model specification
-
- This error occurs because the data pointer size has not been
- specified.
-
-
- 292. Warning C4051 Generated by Clock Function in C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_QuickC docerr
- Last Modified: 16-MAY-1989 ArticleIdent: Q40376
-
- The example on Page 167 of the "Microsoft C 5.1 Optimizing Compiler
- Run-Time Library Reference" that shows how to use the run-time library
- function clock produces a warning C4051 : data conversion. The warning
- is generated because the variable tm is defined as an integer while
- clock_t is defined as a long in the include file time.h.
-
- As a result, warning C4051 is generated on the following line:
-
- if ((tm=clock()) != (clock_t)-1)
-
- To eliminate this warning, declare variable tm as a long.
-
- Also, if you want to see the elapsed time as real numbers, the
- following line should be changed:
-
- printf("Processor time equals %d second\n", tm/CLK_TCK)
-
- The line above should be changed to the following:
-
- printf("Processor time equals %fsecond\n",tm/(float)CLK_TCK)
-
-
- 293. Problems with Using the Digital Output of a VGA Adapter
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QUICKC
- Last Modified: 16-MAY-1989 ArticleIdent: Q40573
-
- Problem:
-
- When I run programs, such as GRDEMO, that call the graphics function
- _setvideomode, a border is displayed around my monitor. Also, the
- functions _remappalette and _remapallpalette do not seem to work
- correctly.
-
- Response:
-
- Some VGA display adapters have analog- and digital-output
- capabilities. The above behavior occurs when the digital output of a
- VGA display adapter is connected to the monitor.
-
- When the digital output is connected to an ECD (EGA monitor), a green
- border is observed. When the digital output is connected to a
- multisync class monitor, a gray border is observed. In either case,
- remapping the palette does not function. When the analog output is
- connected to a multisync or VGA monitor, the correct behavior is
- observed.
-
- The problem is that the graphics adapter is rightfully determined to
- be VGA class -- although for practical purposes it is really EGA
- class. At this point, the C graphics library treats the display
- incorrectly as VGA. Connecting a digital monitor to the digital output
- of a VGA adapter is a non-standard hardware configuration (the digital
- output of a VGA graphics adapter is non-standard). The behavior of a
- non-standard hardware configuration is unpredictable.
-
-
-
- 294. You Cannot Trap CTRL+ALT+DEL in OS/2
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q40580
-
- In OS/2, you cannot trap the CTRL+ALT+DEL. This key sequence is caught
- by the keyboard driver and never makes it into the input steam, so you
- have no access to it.
-
-
- 295. Overlays and BINDing Are Not Compatible
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 25-MAY-1989 ArticleIdent: Q40581
-
- Question:
-
- I have written a large program that needs to be overlaid to run in
- DOS. Is there a way I can compile it for OS/2, then BIND it to run in
- DOS with overlays so that I only have a single executable for both
- OS/2 and DOS?
-
- Response:
-
- You cannot do this; to BIND a program to run in DOS, you need a
- protected-mode executable. However, protected-mode executables do not
- understand overlays. As a result, there is no way to BIND a program
- that needs overlays in DOS. You have to have two different
- executables.
-
- Note: The two executables could be combined into one large executable
- by creating the real-mode executable and naming it in the STUB
- statement in the .DEF file when linking the OS/2 application. There is
- no real advantage to this; however, the new .EXE file will be a little
- larger than the two separate files. The STUB statement is documented
- by the C 5.10 utilities update in the LINK section.
-
-
- 296. Floating-Point Routines Are Not Reentrant
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 25-MAY-1989 ArticleIdent: Q40587
-
- Even if you only want simple arithmetic operations, the 80x87 chip
- doesn't provide a means for saving and restoring all of its registers.
- Microsoft wrote its library routines for DOS, which for the most part
- handle single-process routines, and therefore do not provide the
- routines necessary for achieving this effect with the coprocessor
- chip.
-
- If you want to develop a program that requires the coprocessor to be
- reentrant, you must provide your own routines that save and restore
- the registers of the coprocessor.
-
-
- 297. Search Order for Include Files When Using APPEND Command
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | append include
- Last Modified: 25-MAY-1989 ArticleIdent: Q40588
-
- A data file path can be specified in DOS by using the APPEND command.
- DOS searches for a data file using the APPEND path. A file included by
- a C program can be in a directory that is in the data file path. The C
- compiler searches for the include file in the following order:
-
- 1. Current directory
-
- 2. Directories specified by the INCLUDE environment variable
-
- 3. Directories specified by the APPEND command
-
- Please refer to your DOS documentation for specific information about
- using the APPEND command.
-
- Note: The APPEND command can cause other problems during
- compilation, linking, and execution. Microsoft recommends not using
- the APPEND command when developing C programs.
-
-
- 298. The Definition of Reentrancy
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | re-entrant reentrant
- Last Modified: 16-MAY-1989 ArticleIdent: Q40589
-
- Question:
-
- What is reentrancy?
-
- Response:
-
- Reentrancy is the ability of code to be executed simultaneously by
- more than one process. It requires that the code not change the state
- of any global object, such as global variables or hardware. Any code
- compiled by the C compiler that uses only automatic variables will be
- reentrant only if the library functions used by the code are also
- reentrant.
-
- Note: Most library routines are not reentrant, nor is DOS or BIOS.
-
-
- 299. Operator sizeof Returns Type size_t Defined as Unsigned int
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 11-JAN-1990 ArticleIdent: Q40590
-
- The sizeof operator returns a value that is of type size_t. The
- definition of size_t is implementation dependent, according to the
- ANSI standard. In Microsoft C, the size_t type is defined in STDDEF.H
- and in MALLOC.H as an unsigned int. This is documented on Pages 38 and
- 98 of the "Microsoft C Optimizing Compiler Run-Time Library Reference"
- manual.
-
- The reference manual describes the sizeof operator on Pages 120-121,
- Section 5.3.4, but does not give the return type.
-
- The index entry for "size_t type" incorrectly lists Pages 38 and 97;
- it should say 38 and 98.
-
-
- 300. Misspelling "Default" Gives No Error
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q40593
-
- It has been reported that when the keyword "default" is misspelled as
- "defualt", the C compiler does not generate an error and the
- executable code does not execute the "defualt" branch in any case.
-
- This is not a problem with the C compiler. When the keyword "default"
- is spelled incorrectly, it is treated as a label. You may use a goto
- statement to reference the label.
-
- Note: It is not a good programming practice to jump to a label that is
- within a switch statement from outside the switch statement.
-
-
- 301. Accessing the COM3: or COM4: Port
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q40594
-
- If the DOS, the ROM BIOS, and the hardware all support COM3: and COM4:
- as valid devices, then the DOS mode command may possibly be used to
- redirect communication to access the ports from within Microsoft C.
- For example, to redirect COM3: to COM1:, give the following command:
-
- mode COM3:=COM1:
-
- Note: This process has not been tested by Microsoft and is offered
- only as a suggestion.
-
- Versions of DOS earlier than MS-DOS Version 3.30 do not recognize the
- COM3: and COM4: ports. Versions beginning with MS-DOS Version 3.30
- allow some systems to access the ports, but the ROM BIOS also must
- support the extra communications port hardware.
-
-
- 302. C memcpy and Large Model
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G881031-5486
- Last Modified: 16-MAY-1989 ArticleIdent: Q40738
-
- Question:
-
- I normally compile a certain program with the /Ox switch. Inside a few
- modules, I use the #pragma function(memcpy) statement, to force the
- use of the function version of memcpy, which is required because I use
- memcpy with some huge pointers.
-
- This works correctly, until I want to use CodeView. At that time, I
- recompile with the switches /Od /Zi. This produces the following error
- message:
-
- Error C2164: 'memcpy': intrinsic was not declared
-
- Editing each module to remove the #pragma function(memcpy), which is
- not required in the /Od case, eliminates the error message. Editing
- the pragma in and out is a lot of work, however.
-
- Why is this required?
-
- Response:
-
- The C2164 error message is listed in ERRMSG.DOC, which is supplied
- with the compiler. (It's a good idea to print out all the .DOC files
- for reference; there's a lot of important information there that
- doesn't appear in the manuals.) When you don't use the -Oi or -Ox
- option, you need to declare a function prototype before you can use
- the function or intrinsic pragmas. An easy way to do this is to
- include the appropriate .H file: in this case, either STRING.H or
- MEMORY.H will do. This will work with or without intrinsics.
-
-
- 303. How to Pass a Far Pointer from Parent to Spawned Child in C
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G881208-7649
- Last Modified: 25-MAY-1989 ArticleIdent: Q40774
-
- Question:
-
- Is it possible to hand over a far pointer from a parent process to a
- child process? My parent process is doing a memory allocation that it
- fills with data. I'd like to be able to access this data in the child
- process.
-
- Response:
-
- The best way to pass a pointer to a child is to convert the pointer to
- an ASCII string using sprintf, spawn the child with the string on the
- command line, and convert the string back to a pointer with sscanf.
- Below is a sample program that does this. Note that the program and
- the child process must be compiled separately. Be sure to pass a far
- (segment and offset) pointer rather than a near (offset only)
- pointer. Attempting to pass a near pointer will not work.
-
- It is also possible to leave the pointer in an agreed-upon memory
- area. Frequently, unused interrupt vectors are used for this purpose.
- We do not recommend this method because it could cause conflicts with
- other software using the same memory. The method described above
- is much safer.
-
- A sample parent program and child program follow:
-
- /**************** parent process ****************/
- #include <process.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <stdio.h>
- #include <string.h>
-
- char buffer[80]; /* buffer to be passed to child */
- char ascptr[20]; /* holds ASCII version of ptr. */
-
- void main(void)
- {
- int ret;
-
- /* initial string */
- strcpy(buffer, "Main1");
- printf("Beginning main1...\nString is: %s\n", buffer);
-
- /* convert address to ASCII */
- sprintf(ascptr, "%p", buffer);
- printf("ASCII version of pointer is: %p\nSpawning main2...\n\n",
- ascptr);
-
- /* spawn, passing ASCII address on
- command line */
- ret = spawnlp(P_WAIT, "main2.exe", "main2", ascptr, NULL);
- printf("\nBack to main1--spawnlp returned %d\n", ret);
-
- /* Show that string is changed */
- printf("String is now: %s\nAll done", buffer);
- exit(0);
- }
- /* end of program number one*/
-
- /**************** child process--compile seperately! *************/
- #include <process.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
-
- char far *ptrstuff;
-
- void main(int argc, char **argv)
- {
- int ch;
-
- printf("In main2: argv[1] is %s\n", argv[1]);
- if (argc != 2) { /* error in argument list */
- printf("Error in argument list to main2\n");
- exit(1);
- }
-
- /* retrieve pointer value from string */
- sscanf(argv[1], "%p", &ptrstuff);
- printf("\nPointer is actually set to: %p\n", ptrstuff);
-
- /* check to see that it's right */
- printf("Pointer points to: %s\n", ptrstuff);
-
- /* change string (CAREFULLY!!!!!) */
- printf("Warning: modifying the string incorrectly could hang "
- "your system...\n");
- printf("\007Should I modify this string? ");
- ch = getchar();
- if (toupper(ch) == 'Y') {
- strcpy(ptrstuff, "2nd main");
- printf("Changed string to: %s\n", ptrstuff);
- }
- else printf("String not changed....\n");
-
- printf("Exiting main2...\n");
- exit(0);
- }
- /* end of child process */
-
-
- 304. Using /ND to Put Uninitialized Data in a Named Segment
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q40777
-
- Question:
-
- When I compile the example below with the /NDsegname switch, why don't
- the variables a and b end up in the segname_BSS segment?
-
- #include <stdio.h>
-
- int a,b,c=2;
-
- main()
- {
-
- }
-
- How do I get my uninitialized global data and static data to go into
- the named data segment (namely segname_BSS)?
-
- Response:
-
- Variables that are declared outside of a function and not initialized
- are communal. The BTDATA_BSS segment is for uninitialized static data.
- So, when compiling with /ND:
-
- int a; /* goes to FAR_BSS */
- int b = 5; /* goes to STUFF */
- static c; /* goes to STUFF_BSS */
-
- The reason that "int a;" is treated in this way is that it's legal to
- have such declarations in several modules as long as at most one of
- the declarations contains an initializer. The linker combines all
- these definitions into one. If it were subject to the /ND switch, the
- variable could be in different segments in different modules, which
- would be impossible to link.
-
- So, to put the variable in the STUFF group, either declare the
- variable static or initialize it (like either b or c above).
-
-
- 305. Assembly Listing Doesn't Match Generated Code in C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 25-MAY-1989 ArticleIdent: Q40783
-
- Microsoft has received several reports that the listings generated by
- the /Fc, /Fl, and /Fa options do not match the actual code in the
- .OBJ or .EXE file, as viewed by CodeView.
-
- In these cases, we have found that the file has been compiled using
- different options when creating the listing than when producing the
- CodeView file. In particular, adding the /Zi option causes some
- changes in the generated code. As we document, /Zi turns off
- optimizations that move code.
-
- If the listing was generated without /Zi, but the .EXE being viewed in
- CodeView was compiled with /Zi, there often are differences between
- the CodeView listing and the printed listing.
-
- Be sure to use EXACTLY the same options when comparing listing files
- with the actual code.
-
-
- 306. Available Memory in C with More Than 20 Files and PC-DOS 3.30
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q40785
-
- Question:
-
- Following the directions in the C 5.10 README.DOC file, I have
- modified the CRT0DAT.ASM file to increase the number of file handles
- from 20 to 30. I have a simple program (below) that checks the amount
- of available memory. When I link it with the modified CRT0DAT and
- execute the program, the amount of available memory is significantly
- less (approximately 64K) if I am running PC-DOS 3.30 than it is if I
- am running MS-DOS 3.30.
-
- Note: If I do not link in the CRT0DAT, then the difference in the
- available memory between MS-DOS 3.30 and PC-DOS 3.30 is negligible.
-
- All memory models will produce results similar to those described
- above.
-
- How can I eliminate this inconsistency between the two versions of
- DOS?
-
- Response:
-
- The only workarounds are to not link with a modified CRT0DAT.ASM, or
- to use MS-DOS instead of PC-DOS.
-
- Microsoft is researching this problem and will post more information
- as it becomes available.
-
- The following program, compiled with "cl /W3 /c", demonstrates the
- problem:
-
- #include <stdio.h>
- #include <dos.h>
-
- void main(void)
- {
- unsigned size;
- unsigned segment;
-
- printf("Checking memory:\n");
- size = 0xffff;
- if (_dos_allocmem (size, &segment))
- printf("Available paragraphs: %u\n",segment);
- else
- printf("Memory allocated.\n");
- }
-
-
- 307. C Compiler Error: (compiler file '@(#)code.c1.46, line 393)
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q40786
-
- The code below generates the following error when compiled with any
- /A?f? option:
-
- fatal error C1001 Internal Compiler Error
- (compiler file '@(#)code.c1.46, line 393)
-
- To work around the problem, use a different memory model, use only one
- register variable, or simplify the assignment with temporary
- variables.
-
- Sample code that demonstrates the problem follows:
-
- int main()
- {
- char *buff;
- char *ptr[8];
-
- register int k;
- register int i;
-
- *ptr[i]++ = buff[k++];
- }
-
-
- 308. _edata and _end Are Defined by LINK
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_LINK
- Last Modified: 16-MAY-1989 ArticleIdent: Q40810
-
- Question :
-
- In the map file generated by Microsoft LINK, there are two symbols:
- _edata and _end. What are they?
-
- Response:
-
- When the /DOSSEG (default) option is used with the LINK command, these
- two symbols are created by LINK and are used in the C startup code as
- markers. They are only meaningful for the Microsoft C and FORTRAN
- Compilers.
-
- This information is explained on Page 273 of the "Microsoft CodeView
- and Utilities Software Development Tools for the MS-DOS Operating
- System" manual for C Version 5.00 or 5.10 in the LINK section. The
- note on this page states that the _edata points to the beginning of
- the BSS segment; _end points to the end of the BSS segment and the
- beginning of the STACK segment.
-
- These two symbols can be found in the startup source code file
- CRT0.ASM. The startup source code is included in the Microsoft C
- Optimizing Compiler for Versions 5.00 and 5.10.
-
-
- 309. Maximum Number of Include Directories Is 15
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | limits
- Last Modified: 31-JAN-1989 ArticleIdent: Q40837
-
- There is a maximum number of directories you can set in both the
- compile line and the INCLUDE environment variable. The combined
- maximum is 15. Exceeding the maximum can cause the error U1013 or
- U1077 in a MAKE file.
-
- No error message is given if the compile line is typed in directly
- from the DOS prompt. The program just fails to compile. This maximum
- applies to both DOS and OS/2.
-
- Note: If you have 14 directories in your include environment variable
- and added several others at the command line (with one /I, as opposed
- to using a /I for every directory), you could break this boundary.
- However, you should normally avoid using more than 15 directories.
-
-
- 310. FATAL: Internal Stack Failure, System Halted
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QUICKC S_PASCAL H_FORTRAN H_MASM
- Last Modified: 16-MAY-1989 ArticleIdent: Q41024
-
- For DOS Version 3.20 or later, the following message is issued by DOS
- when too many interrupts occur too quickly and the pool of internal
- stack frames is exhausted:
-
- FATAL: Internal Stack Failure, System Halted
-
- Increasing the number of stacks allocated for use by interrupt
- handlers in the STACKS command in CONFIG.SYS usually corrects the
- problem.
-
- The syntax is as follows:
-
- STACKS=n,s
-
- n = number of stacks, ranging from 8 to 64, with 9 as the as the default
- s = size of each stack, ranging from 32 to 512 bytes, default of 128
-
- For more information about the STACKS command, see Page 805 of the
- "MS-DOS Encyclopedia."
-
- This error can occur if network cards, laboratory measurement
- instruments, and other devices are in use. They may generate many
- hardware interrupts thus exhausting the DOS stack resources.
-
- Note: For MS-DOS Version 3.30 on an IBM-PC, IBM-XT, or
- IBM-PC-Portable, the default for n is 0 and s is 0 .
-
-
-
- 311. Libraries Added by the Comment pragma Appear After Default
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 11-SEP-1989 ArticleIdent: Q41104
-
- Page 12 of the "Microsoft C for MS OS/2 and MS-DOS Operating Systems:
- Version 5.1 Update" manual states that when using the library option
- of the comment pragma, the specified library name will be inserted
- before the default library name in the object module. This is not the
- case; the given library name appears after the default library name.
- This agrees with the next statement in the documentation that states
- that using this pragma is the same as giving the library to LINK on
- the command line.
-
- If the order of the default library and an added library is important,
- compiling with the /Zl switch will prevent the default library name
- from being placed in the object module. A second comment pragma then
- can be used to insert the name of the default library after the added
- library. The libraries listed with these pragmas will appear in the
- object module in the same order they are found in the source code.
-
-
- 312. C Versions 3.00, 4.00 Do Not Require Semicolon in Structure
-
- Product Version(s): 3.00 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q41158
-
- Microsoft C Versions 3.00 and 4.00 do not require a semicolon to be
- put after each field in the structure declaration. The following piece
- of code does not produce any errors in C Versions 3.00 and 4.00:
-
- struct one
- {
- int i
- };
-
- Microsoft C Versions 5.00 and 5.10 do require a semicolon after each
- field and will generate the following error if the semicolon
- is not there:
-
- error C2143
- syntax error: missing ';' before '}'
-
- Note: According to the Kernighan and Ritchie, semicolons are required
- after each field in the structure declaration.
-
-
- 313. rewind(stdin) Clears Keyboard Buffer
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 16-MAY-1989 ArticleIdent: Q41159
-
- Problem:
-
- I am trying to clear the keyboard buffer. It seems that using the
- function "fflush" on stream "stdin" does not have any effect.
-
- Response :
-
- The function "fflush" clears the buffers that C programs use for
- stream level I/O. It doesn't clear the device buffer.
-
- To clear the keyboard buffer, use the function "rewind" with the
- stream "stdin", which is associated with the keyboard by default.
- The function is prototyped in "stdio.h".
-
- The following is an example to demonstrate the usage:
-
- #include <stdio.h>
- void main(void)
- {
- int ch ;
-
- ch = getchar() ; /* input more than one character
- ** to see the effect of rewind(stdin) */
- putchar(ch) ;
- putchar('\n') ;
-
- rewind(stdin) ;
- ch = getchar() ; /* will wait for new input even the first input
- ** has more than one character */
- putchar(ch) ;
- }
-
-
- 314. Getpid under DOS Is Not Functional
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q41160
-
- Under DOS versions earlier than Version 4.00, the getpid() function
- returns the current time rather then the process ID as expected.
-
- DOS is a single-tasking operating system, so it does not generate a
- process ID and the Getpid function should not be used. Getpid is
- intended to be used with OS/2 and serves no purpose under DOS.
-
-
- 315. How ungetch() Works with getch() and getche()
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 16-MAY-1989 ArticleIdent: Q41198
-
- The Microsoft C run-time function ungetch() pushes back a character
- to be read in by the next call to getch() or getche().
-
- The character is pushed back to a special memory buffer defined in
- getch(). The function getch() or getche() checks the special buffer
- before it calls the DOS interrupt function to read input from the real
- keyboard buffer. If the special buffer is not empty, it returns the
- value in the buffer without calling the interrupt 21h function.
-
- ungetch() does not put the character back to the keyboard buffer.
-
- Pushing a character back to the keyboard buffer can be done on some
- machines by calling BIOS keyboard service, interrupt 16H function 05H
- with scan code in the register CH and the character's ASCII code in
- the register CL.
-
- Note: This BIOS function does not exist on many machines -- be sure to
- check the machine you're running on before you try to use this
- function.
-
-
- 316. getch() Misbehaves on Keyboard Inputs ALT+Q, ALT+R
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q41203
-
- Problem:
-
- The sample program below accepts all the keyboard inputs normally,
- including most of the ALT combination keys. But it appears to behave
- incorrectly on two keyboard inputs: ALT+Q and ALT+R.
-
- Response:
-
- This is not a problem with the Microsoft C Optimizing Compiler
- run-time function getch(). The problem is caused because DOS uses the
- values of these two ALT combination keys for other control purposes.
-
- In this case, the second scancode of ALT+Q is 16 and the second
- scancode of ALT+R is 19 (both decimal). DOS uses scancode 16 to mean
- "echo subsequent output to the printer" and scancode 19 to mean "pause
- output." These are equivalent to CTRL+P and CTRL+S. When a printer is
- not connected to the computer, the PRINT SCREEN key has to wait for
- time out. For the SCREEN PAUSE key, another key has to be pressed to
- activate the screen again.
-
- We recommend using the _bios_keybrd() function rather than getch()
- when you might press ALT+R or ALT+Q.
-
- Usually the ALT combination keys generate 2 bytes in the keyboard
- buffer. The program below checks if the first byte is zero. If it is
- zero the program reads in the next byte, which has the value for that
- particular ALT combination key.
-
- The following is a code example:
-
- /* sample program */
- #include <stdio.h>
- #include <conio.h>
- void main(void)
- {
- int ch, scan;
-
- do {
- ch = getch(); /* 1st getch() gets ASCII code */
- printf("Character is %d\n", ch);
- if (ch == 0) { /* if ASCII code was zero */
- scan = getch(); /* 2nd getch() gets "scan code" */
- printf("\tExtended character: scan is %d\n", scan);
- }
- } while (ch != 27); /* exit loop on ESC */
- }
-
- To read the combination keys successfully, use the function
- _bios_keybrd(). The following is an example that works in a similar
- manner to the example above. Note: Because _bios_keybrd() returns
- both the scan code and the ASCII value in the high and low bytes of
- the return value, only one call to _bios_keybrd() is necessary for
- each keystroke.
-
- The following is a code example:
-
- #include <stdio.h>
- #include <bios.h>
-
- void main(void)
- {
- unsigned scan_asc;
- int ch, scan;
-
- do {
- scan_asc = _bios_keybrd(_KEYBRD_READ);
- ch = scan_asc & 0xff; /* character in low byte */
- scan = scan_asc >> 8; /* scan code in high byte */
- printf("Character is %d\n", ch) ;
- if (ch == 0) {
- printf("\tExtended character: scan is %d\n", scan) ;
- }
- } while (ch != 27) ; /* exit loop on ESC key */
- }
-
-
- 317. Prototypes Must Be Used Before Intrinsic or Function Pragmas
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G881031-5486
- Last Modified: 16-MAY-1989 ArticleIdent: Q41212
-
- Question:
-
- I normally compile a certain program with the /Ox switch. Inside a few
- modules, I use the #pragma function(memcpy) statement to force the
- use of the function version of memcpy, which is required because I use
- memcpy with some "huge" pointers.
-
- This works correctly until I want to use CodeView. At that time, I
- recompile with the switches /Od /Zi. This produces the following error
- message:
-
- Error C2164: 'memcpy': intrinsic was not declared.
-
- Editing each module to remove the #pragma function(memcpy), which is
- not required in the /Od case, eliminates the error message. However
- this is time consuming. Why is this required?
-
- Note: Error C2164 is not listed in the "Microsoft C for MS-DOS
- Operating System: User's Guide."
-
- Response:
-
- When you don't use the -Oi or -Ox option, you need to declare a
- function prototype before you can use the function or intrinsic
- pragmas. One method is to include the appropriate .h file -- for this
- function, either string.h or memory.h will work correctly.
-
- The C2164 error message is listed in errmsg.doc, which is supplied
- with the compiler. (It's a good idea to print out all the .doc files
- for reference; there's a lot of important information there that
- doesn't appear in the manuals.)
-
-
- 318. How to Trap CTRL+C
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | appnote softlib CTRLC.ARC S12319.EXE
- Last Modified: 25-JUL-1989 ArticleIdent: Q45497
-
- An application note is available that demonstrates how to trap the
- CTRL+C and CTRL+BREAK key combinations. This application note is
- available from Microsoft Product Support Services by calling (206)
- 454-2030. This application note is also available from the Microsoft
- PSS System Languages group.
-
- This information is also available in the Software/Data library by
- searching on the keyword CTRLC, the Q number of this article, or
- S12319. CTRLC was archived using the PKware file-compression utility.
-
- The file provided is fully tested; however, it is not regularly
- released with the Microsoft C Version 5.10 Compiler. Consequently, it
- will not be maintained and any problem reported against it will not
- result in a patch or any other immediate repair. Problems experienced
- with this file should be reported to Microsoft Product Support
- Services.
-
- CTRLC contains the following files:
-
- README.NOW - Brief description of program and Microsoft
- disclaimer
-
- CTRL.C - Code example for trapping the CTRL+C and CTRL+BREAK
- key combinations
-
-
- 319. Alleged Problems with Listing Options (/Fc, /Fl, /Fa)
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# S881208-32 errors
- Last Modified: 25-MAY-1989 ArticleIdent: Q41217
-
- Microsoft has received reports that the assembly listing options (/Fc,
- /Fl, /Fa) produce listings that don't accurately reflect the code
- generated.
-
- We have determined that this problem is caused
- because different compiler options are being used when compiling to
- produce the listing, than when compiling to produce an executable. An
- especially common situation is to use /Zi for compiling the executable
- and to leave it off when compiling to produce a listing.
-
- The /Zi option DOES in fact cause slightly different code to be
- generated because optimizations that would move code are suppressed.
- Therefore, it is perfectly normal for the CodeView listing of a
- program compiled with /Zi to differ somewhat from the listing produced
- when compiled without /Zi.
-
- If you find a case in which the listing is different from the
- generated code when both are compiled with EXACTLY the same options,
- please report the problem to Microsoft.
-
-
- 320. Program Hangs the Second Time It Is Run Using an 80287
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-MAY-1989 ArticleIdent: Q41220
-
- When compiling a program that uses signal() with an 80287 coprocessor,
- the first time the program runs, everything works correctly. But if
- run a second time, it hangs the computer.
-
- This problem has been confirmed to be with the old 80287 coprocessors
- and has been corrected in newer 80287 chips.
-
- The example program in the "Microsoft C for the MS-DOS Operating
- System: Run-Time Library Reference" manual on Page 280 locks up on the
- second time the program is executed with an old 80287. The following
- is an example:
-
- #include <stdio.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <float.h>
-
- int fphandler ();
- jmp_buf mark;
- double a = 1.0, b = 0.0, c;
-
- main()
- {
- if(signal(SIGFPE, fphandler) == (int(*) () ) -1)
- abort();
-
- if(setjmp(mark) == 0)
- {
- c = a/b;
- printf("Should never get here\n");
- }
-
- printf("Recovered from floating-point error\n");
- }
-
- int fphandler (sig, num)
- int sig, num;
- {
- printf("signal = %d subcode = %d\n", sig, num);
- _fpreset();
- longjmp(mark, -1);
- }
-
-
- 321. Use Huge Pointers If Object Is Larger Than 64K Boundary
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | SR# G890201-11081
- Last Modified: 16-MAY-1989 ArticleIdent: Q41247
-
- Question:
-
- I'm declaring a pointer that points into an array by saying the
- following:
-
- char huge carray[70000];
- char *pchar = carray;
-
- I compile the program using large-memory model.
-
- When I access the array using carray, everything work correctly.
- However, when I use the pointer pchar, I can't seem to access the
- array past the 64K boundary. What's wrong?
-
- Response:
-
- The problem is caused by using a far pointer in a situation where you
- need a huge pointer.
-
- There are three types of data pointers in Microsoft C: near, far, and
- huge. Near pointers represent offsets within DGROUP (the default data
- segment) and are stored in 2 bytes. Far and huge pointers contain both
- a segment address/selector and an offset and therefore take 4 bytes.
-
- Although far and huge pointers are identical in format, the algorithms
- used to do addressing calculations involving these two types of
- pointers are very different. Far pointers are assumed to point to a
- data item that does not cross a segment boundary (in other words, the
- size of the item must be less than 64K). As a result, the compiler
- ignores the segment part of the pointer in all calculations except for
- "equals" and "not equals" tests. This gives a considerable (more than
- 2 times) savings in execution time for these operations. In fact,
- calculations involving far pointers are almost as fast as calculations
- involving near pointers.
-
- Huge pointers may point to items that are larger than 64K. The
- addressing arithmetic work on both the segment and the offset, if
- necessary. Huge pointer arithmetic is therefore considerably slower
- than far arithmetic, but it has the advantage of working when the data
- item is larger than 64K.
-
- Your code should work correctly if you declare pchar to be a huge
- pointer rather than a far (default for large-memory model) pointer. If
- you didn't want to add the huge keyword to the declaration, you could
- compile with the /AH option. It is recommended to use the huge keyword
- rather than /AH because it allows you to control when huge arithmetic
- is performed -- if you use /AH, then ALL pointers are huge.
-
-
- 322. Number of Serial Ports under OS/2
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | SR# G890121-10245
- Last Modified: 16-MAY-1989 ArticleIdent: Q41255
-
- The number of serial ports that can be supported under OS/2 is
- dependent on how your OS/2 vendor set up the device drivers
- shipped with the operating system. Most are set up with two ports for
- AT-type machines and three for PS/2 type machines. Each vendor writes
- its own communications device drivers, so it really depends on what
- the vendor is doing.
-
- Note: Both original and third-party vendors can support additional
- ports (essentially, as many as they like) if they write or modify
- device drivers to do so.
-
-
- 323. ROMable Code Using Microsoft C
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890121-10245 appnote
- Last Modified: 31-MAY-1989 ArticleIdent: Q41256
-
- Question:
-
- How can I use the Microsoft C Compiler to produce code that will be
- put into ROM?
-
- Response:
-
- The best way is to use a third-party package designed to produce
- ROMable code using Microsoft C. The linker supplied with our compiler
- only produces code designed to run under the DOS and OS/2
- environments. CodeView only runs under DOS or OS/2. Third-party
- packages typically include an alternate linker and debugger.
-
- You can find out more about these third-party packages by obtaining a
- copy of a technically oriented PC magazine or by talking with a dealer
- who sells such packages. Microsoft also provides an application note
- called "Writing ROMable Code in Microsoft C," which can be obtained
- from Microsoft Product Support Services by calling (206) 454-2030.
-
-
- 324. What Is the Format of an .EXE File?
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890118-9899
- Last Modified: 16-MAY-1989 ArticleIdent: Q41257
-
- Question:
-
- What is the format of an .EXE file?
-
- Response:
-
- The .EXE file format is documented in a number of places, including
- the "MS-DOS Programmer's Reference." Probably the best documentation
- you'll find is in the MS-DOS Encyclopedia, starting on Page 119. There
- is also an appendix on the new segmented format used by Windows in the
- back of this reference.
-
- The MS-DOS Encyclopedia is an incredibly valuable reference for
- systems programmers. The format is too long and complicated to
- reproduce here.
-
-
- 325. Calculating Available Memory in Large Model
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890215-12018
- Last Modified: 16-MAY-1989 ArticleIdent: Q41345
-
- Question:
-
- I am using large-memory model (C Version 5.10). My program makes a
- call to the _memavl() function to see how much memory is remaining. I
- get back some number (e.g. 29320 bytes). Then I malloc some buffers
- for linked lists, data structures and place another call to _memavl. I
- get the same number back.
-
- Shouldn't the number get smaller after I have malloc'd memory?
-
- Is there a way for me to find out how much free memory (total) is
- available?
-
- Response:
-
- There are actually two memory-allocation heaps when you're using large
- model. The near heap is the unused portion of the 64K DGROUP segment.
- The far heap is the unused memory above your program. malloc() uses
- the near heap for small and medium models and the far heap for
- compact, large, and huge models. (You can choose which heap to use by
- using _fmalloc() for the far heap and _nmalloc() for the near heap.)
-
- The _memavl() function only measures the amount of memory available
- on the near heap. Because the near heap is not used in far model until
- the far heap is exhausted, _memavl() shouldn't change.
-
- To measure the amount of memory available on the far heap, you can
- use the _dos_allocmem() function. (This function calls the DOS
- memory-allocation function.) Pass the function 0xFFFF for the number
- of 16-byte paragraphs to allocate (which is 1 megabyte more memory
- than the machine has) and the address of an unsigned int. When the
- function returns, the unsigned int whose address you passed will
- contain the paragraph size of the largest contiguous block in the far
- heap. To find the number of bytes, multiply this by the 16L, which is
- the size of a paragraph. (Use 16L rather than 16 so that the
- multiplication will be done using long math, avoiding possible
- overflow.)
-
- The total memory available is the sum of the amount available on the
- far and near heaps. For best accuracy, you should do this calculation
- immediately after your program begins.
-
- There are a few traits of the malloc() allocation you should be aware
- of, as follows:
-
- 1. malloc() does NOT call DOS for each small allocation. Instead, it
- asks DOS for an 8K block (this size can be set by setting the
- global variable _amblksiz, as described on Page 33 of the
- "Microsoft C Run-Time Library Reference"), then allocates from this
- block. If the requested allocation is more than than 8K, malloc
- allocates enough 8K blocks to fulfill the allocation. Before
- malloc() asks DOS for memory, it first tries to allocate the
- request from memory it already has.
-
- 2. free() NEVER returns memory to DOS. So, if you allocated a block,
- checked the far heap space using _dos_allocmem(), free()'d the
- block and checked again, the amount of memory available to DOS
- would NOT increase on the second call. You can get a better idea of
- how much memory is available by using _fheapwalk() to find out how
- much memory is available to malloc() but not to DOS.
-
- Note: halloc() calls DOS directly and frees directly to DOS.
-
- A program that calculates an estimate of the total amount of free
- memory follows:
-
- #include <malloc.h>
- #include <dos.h>
- #include <stdio.h>
-
- void main(void)
- {
- long totalavail;
- unsigned farparaavail;
-
- _dos_allocmem(0xFFFF, &farparaavail);
-
- totalavail = (long)farparaavail * 16L + _memavl();
-
- printf("Total memory available is about %ld bytes\n", totalavail);
-
- }
-
-
- 326. Run-Time Library Reference vfprintf Documentation Error
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr s_quickc
- Last Modified: 16-MAY-1989 ArticleIdent: Q41369
-
- Page 636 of the "Microsoft C 5.10 Optimizing Compiler Run-Time Library
- Reference" and the "Microsoft QuickC Run-Time Library Reference"
- contains an error. In the example listed, the line
-
- error("Error: line %d, file filename);
-
- should read
-
- error("Error: line %d, file %s\n", line, filename);
-
-
- 327. _Setvideomode _ERESCOLOR Only Supports 16 Colors
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc docerr langdoc
- Last Modified: 16-MAY-1989 ArticleIdent: Q41373
-
- The manifest constant _ERESCOLOR is incorrectly shown as providing 64
- colors on Page 539 of the "Microsoft C Optimizing Compiler Version
- 5.10 Run-Time Library Reference" manual, Page 539 of the "Microsoft
- QuickC Run-time Library Reference" manual, and Page 197 of the
- "Microsoft QuickC Version 2.00 Graphics Library Reference" manual.
- According to the "Programmer's Guide to PC & PS/2 Video Systems," Page
- 448, and the "MS-DOS Encyclopedia," Page 1513, the correct number of
- colors in 640 x 350 EGA is 16 colors. The include file graph.h
- correctly shows 16 colors.
-
-
- 328. Assignment of Void Pointer Does Not Give Warning Message
-
- Product Version(s): 5.10 | 5.00 5.10
- Operating System: OS/2 | MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 16-MAY-1989 ArticleIdent: Q41374
-
- The code below shows an inconsistency with the way that the Microsoft
- C and QuickC compilers deal with pointer checking. The ANSI Standard
- is unclear as to whether an assignment to a void pointer should be
- checked to see if it is being assigned a nonpointer variable. The code
- below shows that character pointers are checked while void pointers
- are not; the code will generate a warning message at the default
- warning level:
-
- Warning C4017 : '=' different levels of indirection
-
- int i; /* includes float,double,char,long,unsigned */
- char * p;
- void * v;
-
- main() {
- p = i; /* this will give a warning message */
- v = i; /* this will not give a warning message */
- }
-
-
- 329. Documentation Error Page 136 _bios_equiplist
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc docerr
- Last Modified: 16-MAY-1989 ArticleIdent: Q41441
-
- Page 136 of the "Microsoft C 5.10 Run-Time Library Reference" manual
- incorrectly documents the return values for _bios_equiplist. In the
- list of return values, it states that bit 13 is as follows:
-
- True (1) if and only if a serial printer is installed.
-
- This is only true if you have an IBM PCjr. On PC XT type machines,
- this value reports regardless of whether or not you have an internal
- modem installed.
-
- As a result, for PC XT machines, this line should read as follows:
-
- True (1) if and only if an internal modem is installed.
-
- This error also exists in the QuickC Versions 1.00 and 1.01 run-time
- library reference manuals and in the QuickC Version 2.00 on-line help.
-
-
- 330. Macros max and min Incorrectly Listed as Functions
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 16-MAY-1989 ArticleIdent: Q41610
-
- Page 181, section 8.3.2 of the "Microsoft C 5.1 Optimizing Compiler
- User's Guide" incorrectly lists max and min as functions that have
- intrinsic forms.
-
- As correctly noted in the "Microsoft C 5.1 Optimizing Compiler
- Run-Time Library Reference" on Pages 413 and 429, max and min are
- macros defined in the include file stdlib.h.
-
-
- 331. Documentation on Global Variable _osversion Is Incomplete
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 16-MAY-1989 ArticleIdent: Q41689
-
- Page 36 of the "Microsoft C 5.10 Optimizing Compiler Run-Time Library
- Reference" states the global variable _osversion "provides the
- complete version number" of DOS the program is running under. This
- information is correct, but the format of _osversion is not mentioned.
-
- The high-order byte of _osversion is the "minor" version number, or
- _osminor. The low-order byte is the "major" version number, or
- _osmajor.
-
- If you were to write out these values in hex on a system running DOS
- Version 3.30 your output would be as follows:
-
- _osversion = 1e03
- _osminor = 1e (30 in decimal)
- _osmajor = 03
-
- See the C run-time library reference guide, Page 36 for more
- information.
-
-
- 332. Using ANSI Escape Sequences in Microsoft C
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 17-MAY-1989 ArticleIdent: Q41701
-
- Question:
-
- How can I control the screen display using ANSI.SYS escape sequences
- in my C program? For example, how can I clear the screen using the
- escape sequences?
-
- Response:
-
- The easiest way to use ANSI escape sequences is to use them in the
- printf statement, as follows:
-
- #include <stdio.h>
-
- /* ESC[2J escape sequence clears the screen;
- \033 represents the octal code for ESC */
-
- #define CLEAR "\033[2J"
- main()
- {
- printf ("%s screen is now cleared",CLEAR);
- }
-
- The best source of information on different escape sequences is "The
- MS-DOS Encyclopedia," Pages 731-738.
-
- Note: For escape sequences to work correctly, ANSI.SYS must be
- installed.
-
-
- 333. Missing Closing ")" on Macro Causes C1004 Unexpected-EOF Error
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 16-MAY-1989 ArticleIdent: Q42019
-
- The Microsoft C Version 5.10 Optimizing Compiler generates the
- following error message when the compiler encounters an incomplete
- macro invocation:
-
- fatal error C1004: unexpected EOF
-
- A macro in the program missing a closing-right parenthesis causes this
- error to occur. The Microsoft Quick C Compiler Version 2.00 also
- generates this error. Microsoft C Versions 5.00 and 4.00 and QuickC
- Version 1.01 generate the following error:
-
- C1057 unexpected EOF in macro expansion ( missing ')'? )
-
- Now the macro expander uses the same code to read characters when
- looking for an actual as it does to read any character. When we get
- the EOF, we cannot distinguish between a macro or the end of the code.
- This is correct behavior for C Version 5.10.
-
- The following is a sample piece of code that demonstrates this error:
-
- #include <stdio.h>
- #define add(wx, wy) (wx) + (wy)
- void main(void)
- {
- int i;
- i = add( 1, 2 );
- printf( "i = %d\n", i );
-
- i = add( 1, 2 ; /* Causes C1004: unexpected EOF */
-
- printf( "Hello World\n" );
- for( i = 0; i < 10; i++ )
- {
- printf( "i + 10 = %d\n", add( i, 10 ) );
- }
- }
-
-
-
- 334. Incorrect Usage of /o Switch in "Peter Norton's Inside OS/2"
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | docerr
- Last Modified: 16-MAY-1989 ArticleIdent: Q42072
-
- "Peter Norton's Inside OS/2" book written by Peter Norton and Robert
- Lafore, published by Brady, contains examples of OS/2 programming that
- were written and compiled using the Microsoft C Optimizing compiler
- Version 5.10. Page 536 of the book states the following:
-
- The -o option prevents the compiler from thinking that the global
- variables have been defined more than once.
-
- This is incorrect. The /o option is an undocumented compiler switch
- that allows you to name the executable file. It is the same as the /Fe
- compiler switch.
-
-
- 335. Second fscanf Is Skipped During Run Time
-
- Product Version(s): 5.00 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 25-MAY-1989 ArticleIdent: Q42075
-
- Question:
-
- I am using fscanf to read from the keyboard. Why is the second fscanf
- is skipped in the program below during run time?
-
- Response:
-
- The following is stated in the "Microsoft C 5.1 Optimizing Compiler
- Run-Time Library Reference" on Page 503 (in the description of the
- char format specifier):
-
- White-space characters that are ordinarily skipped are read when %c
- is specified; to read the next non-white-space character, use %1s.
-
- Note: You need an array of two characters for %1s because scanf will
- also put a terminating null in the string.
-
- Thus, after the first character is read in the example below, the
- following newline (e.g. linefeed, 0A hex) that is still in the C file
- buffer for stdin is read by the second fscanf (or scanf), causing the
- "second" prompt to be skipped during run time. The following is an
- example:
-
- #include <stdio.h>
- main()
- {
- char a,b[2];
- do
- {
- fprintf (stdout, "\n Enter first single character\n");
- fscanf (stdin, "%c", &a);
-
- fprintf (stdout, "second\n");
- fscanf (stdin, "%c", b); /*this will get the new-line*/
- }
- while (b != 'y');
- }
-
- To work around this problem, use the format specifier %1s instead of
- %c. Don't forget to pass scanf an array of two characters.
-
- Alternately, the fflush() function may be used to flush all characters,
- including white space, out of the specified buffer after each fscanf or
- scanf, or flushall() may be used to flush all file buffers. However, using
- these functions wouldn't leave any characters in the file buffer for
- later scanfs.
-
-
- 336. Getting 43-line Mode for C and QuickC Graphics
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1990 ArticleIdent: Q42079
-
- The Microsoft C Version 5.10 Optimizing Compiler README.DOC file
- states the following:
-
- The graphics library new functions correctly in 43-line mode on an
- EGA, and in 43-line, 50-line, and 60-line modes on a VGA.
-
- This information is correct; however, it does not state that you must
- write your own interrupt routine to set the video mode to support
- this.
-
- The following program demonstrates using Int 10H, Function 11H,
- Subfunction 23H to set an EGA system into 43-line mode. The interrupt
- call must be made BEFORE the call to _setvideomode(). If the routine
- is called after _setvideomode(), the text height is changed, but the
- program uses only the first 25 lines of the screen.
-
- The same procedure also works with the QuickC Version 2.00
- Presentation Graphics package, for placing additional text (with
- _outtext) around the chart. It does not change any of the default text
- (which already has the text height of 43-line mode), or change the
- appearance of the chart, but it allows additional text to be added
- around the chart in the smaller font to create a uniform appearance.
-
- The following is a sample program that demonstrates 43-line mode:
-
- /* program line43.c */
-
- #include <conio.h>
- #include <stdio.h>
- #include <graph.h>
- #include <dos.h>
- #include <process.h>
-
- union REGS inregs, outregs;
- struct SREGS segregs;
- int result;
-
- void main(void)
- {
- inregs.h.ah = 0x11; /*load Function # into AH register */
- inregs.h.al = 0x23; /*load SubFunc # into AL register */
- inregs.h.bl = 0x03; /*load constant for 43-line mode into BL */
- /*For 50-line mode, use */
- /* inregs.h.bl=0x00; */
- /* inregs.h.dl=0x32; */
-
- int86x(0x10, &inregs, &outregs, &segregs); /* call interrupt */
-
- _setvideomode(_ERESCOLOR); /* 640x350 EGA graphics mode */
- /* For VGA w/50 lines, change to: */
- /* _setvideomode(_VRES16COLOR); */
- _settextposition(30,30);
- _outtext("this should be tiny text!");
- while(!kbhit());
- _setvideomode(_DEFAULTMODE); /* restore to default mode */
-
- Note: The "IBM ROM BIOS" quick-reference guide states that this
- function should be used only AFTER a _setvideomode command. However,
- this does not work effectively with the C graphics library.
-
-
- 337. Clarification of fcvt() Function
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q42453
-
- This article is meant to clarify the description of the fcvt()
- function in the "Microsoft C for the MS-DOS Operating System: Run-Time
- Library Reference," Pages 251-252.
-
- The fcvt() function converts a floating-point number to a
- null-terminated character string. The number of digits converted
- depends on the second parameter passed. This second parameter is
- called "count" for the remainder of this article.
-
- The function is designed to return all the digits to the left of the
- decimal point, and then count digits to the right. Once the string is
- converted, all leading zeros are removed unless the number passed was
- zero (see Example 4 below). The string will be terminated with the
- "/0" character. The decimal point is not included in the string, and
- its position can be obtained from the third parameter (see the
- documentation).
-
- Based on this description, the following examples apply. In all cases,
- count = 8. The examples are as follows:
-
- 1. Number passed: 3.667 String returned: "366700000\0"
-
- Nine digits are returned: one for the number to the left of the
- decimal point, eight more because of the count parameter.
-
- 2. Number passed: 3.67E-08 String returned: "3\0"
-
- In this case, only "3" is returned because after the number is
- converted, all the leading zeros are removed.
-
- 3. Number passed: 1.023E-12 String returned: "\0"
-
- In this case, a NULL string is returned because only zeros are left
- after the conversion, and these are all removed from the resulting
- string. If error checking were being performed, this would indicate
- a conversion underflow.
-
- 4. Number passed: 0 String returned: "00000000\0"
-
- This is the only "special" case. Eight zeros are returned so that
- error checking can be performed easily.
-
-
- 338. C Function _dos_setdrive Returns "5" Drives in the System
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | QuickC
- Last Modified: 17-MAY-1989 ArticleIdent: Q42461
-
- Question:
-
- Why does the C function _dos_setdrive always return "5", indicating
- that I have five drives in my system, when in fact I only have two?
-
- Response:
-
- The run-time function _dos_setdrive takes two arguments, as follows:
-
- void _dos_setdrive (drivenum, drives)
-
- The drives argument indicates the total number of drives in the
- system. This means that it will return the number of possible drives
- in the system. The system call Int 21 function 0x0E that _dos_setdrive
- uses to get this information will return a value of either five drives
- in the system or the drive code corresponding to the LASTDRIVE entry
- in CONFIG.SYS, whichever is greater. Without setting
- lastdrive="character" in your CONFIG.SYS, the default "lastdrive" is
- E, which corresponds to five drives possible. This is why
- _dos_setdrive will return "5" when you do not have five physical
- drives in the system.
-
- For example, the following line in CONFIG.SYS will cause a return of
- 26, indicating that 26 drives are present in the system:
-
- lastdrive=z
-
- Therefore, the function _dos_setdrive is working correctly; it is the
- system call 0x0E that is returning such information.
-
- Note: The above information applies only to DOS Versions 3.x and 4.x.
- Under DOS 2.x, the actual number of drives present in the system will
- be reported.
-
-
- 339. Inconsistent Warnings: C4049 and C4024 in C and QuickC
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_QuickC
- Last Modified: 1-JUN-1989 ArticleIdent: Q42562
-
- When compiled with warning level one or higher, the following code
- produces a single warning under the C 5.10 compiler and an additional
- warning under QuickC 2.00:
-
- /* Inconsistent warning example
- */
- void fozzy( short foo, short *spud );
- void winky( int foo, int *spud );
-
- void main( void )
- {
- short sTest;
- short sPoint;
-
- fozzy( sTest, &sPoint );
- winky( sTest, &sPoint );
- }
-
- The warning emitted by both compilers is as follows:
-
- warning C4049: 'argument' : indirection to different types
-
- QuickC also produces the following warning:
-
- warning C4024: 'winky' : different types : parameter 2
-
- In both cases, the compilers dislike the second parameter in the call
- to winky. Winky is prototyped as accepting a pointer to an integer and
- is being passed a pointer to a short.
-
- These warnings are inconsistent because the compiler is not upset
- about winky being passed a short as its first parameter, when it has
- been prototyped as accepting an integer. If the compiler considers a
- short and an integer to be the same for the first parameter, pointers
- to these types should be considered the same for the second parameter.
-
- These generated warnings are expected behavior for both C and QuickC.
- Although integers and shorts are the same under Microsoft's
- implementation of C, they should not be considered to be the same. The
- only restriction on the size of the short given by the ANSI standard
- is that it not be longer than an integer. Code should be written with
- this in mind to maintain ANSI compatibility and prevent problems with
- future compilers, where integers might not be the same size as shorts.
-
-
- 340. Using Near Addresses in Interrupt Handlers in C
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 17-MAY-1989 ArticleIdent: Q42597
-
- When the Microsoft C Compiler compiles the sample program below for
- the small or medium memory model, it gives the following warning:
-
- warning C4058: address of frame variable taken, DS != SS
-
- The sample program is as follows:
-
- /* sample program */
- void interrupt far handler (void) ;
- void foo (char *) ;
-
- void interrupt far handler (void)
- {
- char ch ;
- foo (&ch) ;
- }
-
- void foo (char * ptr) /* a trivial function */
- {
- *ptr = 'a' ;
- }
-
- The warning is generated because the Microsoft C Compiler assumes that
- DS is equal to SS. Because the stack segment SS could possibly be
- changed in an interrupt service routine, the compiler gives a warning
- when a near address that refers to a stack location is passed to a
- function.
-
- In general, in the small and medium memory models, data pointers are
- defaulted to be near unless the "far" keyword is used. In the example
- above, the function "foo" is expecting a near address that is a 16-bit
- offset. A function such as "foo" has no way to tell if the near
- pointer passed to it is an offset relative to the data segment or the
- stack segment. Therefore, the C compiler makes the assumption that an
- offset by itself is always relative to the default data segment. This
- is not a problem in the normal case, where we can depend on the
- assumption that the C compiler makes SS equal to DS. However, in the
- example above, the stack segment could be changed in the interrupt
- handling routine; therefore, the compiler warns you that the code may
- not work correctly.
-
- If the memory model is large or compact, or if the "far" keyword is
- used when foo's formal parameter is declared, the compiler will not
- give any warnings. When "foo" is called, an address with the stack
- segment and the offset will be passed to the function automatically.
- Declaring the stack variable "ch" as static will also avoid the
- problem. The corrected source code is as follows:
-
- /* sample program */
- void interrupt far handler (void) ;
- void foo (char *) ;
-
- void interrupt far handler (void)
- {
- static char ch ;
- foo (&ch) ;
- }
-
- void foo (char * ptr) /* a trivial function */
- {
- *ptr = 'a' ;
- }
-
-
- 341. _imagesize Formula Documented Incorrectly for Some Video Modes
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc docerr
- Last Modified: 17-MAY-1989 ArticleIdent: Q42600
-
- The formula given on Page 362 of the "Microsoft C for the MS-DOS
- Operating System: Run-Time Library Reference" for Optimizing C Version
- 5.x and QuickC Version 1.x, and on Page 133 of the "Microsoft QuickC
- 2.00 Graphics Library Reference" is incorrect for most color EGA and
- VGA video modes. The formula given is as follows:
-
- xwid = abs(x1-x2)+1;
- ywid = abs(y1-y2)+1;
- size = 4+((long) ((xwid*bits_per_pixel+7)/8)*(long)ywid);
-
- This formula is accurate only for the following modes:
-
- _MRES4COLOR
- _MRESNOCOLOR
- _HRESBW
- _VRES2COLOR
- _MRES256COLOR
- _HERCMONO
- _ORESCOLOR
-
- However, for most EGA and VGA color graphics modes, the correct
- formula is as follows:
-
- xwid = abs(x1-x2)+1;
- ywid = abs(y1-y2)+1;
- size = 4 + ((bits_per_pixel * (long) ((xwid+7)/8)) * ywid);
-
- This formula should be used exclusively for modes that utilize bit
- planes. These modes are as follows:
-
- _MRES16COLOR
- _HRES16COLOR
- _ERESCOLOR
- _VRES16COLOR
-
- Either formula is accurate for the following modes:
-
- _HRESBW
- _VRES2COLOR
- _HERCMONO
- _ORESCOLOR
-
- A call to _getvideoconfig will determine the current video mode. This
- call is also necessary to determine the bits_per_pixel value.
-
- The following is an example of values that will yield an incorrect
- result in _VRES16COLOR mode:
-
- x1 = 0; y1 = 0;
- x2 = 4; y2 = 5;
-
- Note that for all cases, _imagesize does return the correct value.
- Only the formula given in the reference manuals is incorrect.
-
- The formula used internally by the _imagesize function is as follows:
-
- xwid = abs(x1-x2)+1;
- ywid = abs(y1-y2)+1;
- size = 4+(bits_per_plane*(long) ((xwid*linear_bits_per_pixel+7)/8)*ywid);
-
- This formula is useful only for lending understanding of how the two
- prior formulas are derived. It cannot be used in a C program for the
- following reasons:
-
- 1. In this formula, linear_bits_per_pixel is the actual number of
- linear bits required to store a pixel. In the color EGA and VGA
- modes listed, this is not equivalent to the bitsperpixel field of
- the videoconfig structure. There is no way to determine this value
- within C.
-
- 2. There is no way to determine the bits_per_plane value within C.
-
- The formula given on Page 392 of the run-time library reference is
- correct for CGA, single-color, and _MRES256COLOR modes because bit
- planes are not utilized in storing graphic images. That is,
- bits_per_plane is equal to 1. Therefore, this factor may be simplified
- out of the equation.
-
- The formula given on Page 392 of the run-time library reference fails
- on the listed EGA and VGA modes because bit planes are implemented in
- storing graphics images under those modes. That is, bits_per_plane is
- greater than 1. Also, linear_bits_per_pixel is not equivalent to the
- bitsperpixel field of the videoconfig structure.
-
- In elaborating on the bitsperpixel field of the videoconfig structure,
- this value is as follows:
-
- vc.bitsperpixel = linear_bits_per_pixel * bits_per_plane;
-
- For more information on bit planes and pixel maps, refer to the
- "Programmer's Guide to PC & PS/2 Video Systems" by Richard Wilton,
- Pages 87-91.
-
-
- 342. Not Including MALLOC.H in Compact, Large Model Causes Problems
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 30-MAY-1989 ArticleIdent: Q42756
-
- It is vital in the compact- and large-memory models that the malloc()
- function be prototyped as returning a four-byte type (preferably a far
- pointer, of course). The proper method in Microsoft C is to include
- the header file MALLOC.H. This prototypes malloc() as returning a void
- pointer.
-
- The default data-pointer size in the compact and large models is 32
- bits. The default return type of any function, including malloc, when
- it is not prototyped is a 16-bit short integer. Thus, the segment
- portion of a far address will be destroyed unless the compiler knows
- it is dealing with a 32-bit type.
-
- If you attempt to use the Unix style of including MEMORY.H rather than
- MALLOC.H, you will encounter problems at run time. MEMORY.H does not
- prototype any of the memory allocation functions; it only prototypes
- memory copy and move functions. In a segmented architecture that can
- have data and code pointers of different sizes, this may have serious
- ramifications. In the case of a large- or compact-model program such
- as the following, the call to malloc() will produce the following code
- fragment:
-
- #include <memory.h>
- main()
- {
- char *addr;
- size_t nbytes = 100;
-
- addr = (char *) malloc( nbytes );
- }
-
- The call to malloc() produces the following code fragment:
-
- push Word Ptr [nbytes]
- call _malloc
- add sp, +02
- cwd
- mov Word Ptr [addr], AX
- mov Word Ptr [bp-06], DX
-
- If MALLOC.H had been included, then the CWD (Convert Word to Double)
- instruction would not be present. CWD sign extends the AX register
- into the DX register in an attempt to convert the 16-bit integer in AX
- to a 32-bit data pointer. This trashes the segment returned by
- malloc() in DX. The resultant pointer will typically point to segment
- 0x0000, meaning that in DOS the interrupt table will be trashed and in
- OS/2 the program will GP fault when an assignment is made to the
- allocated memory.
-
- Note: The compiler will also produce data conversion warnings at
- warning level 1 or higher when such a program is compiled. Paying
- attention to these warnings generally eliminates problems in
- converting C programs from other systems.
-
-
- 343. Use /Op to Avoid Floating-Point Optimization Problem
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G890216-12181
- Last Modified: 17-MAY-1989 ArticleIdent: Q42761
-
- The program below fails when compiled without an /O? option, but works
- if compiled with /Od. The problem seems to be in the conversion of the
- double to int -- the rounding seems to be done incorrectly.
-
- When the code is optimized, the result of the division is kept on the
- floating-point stack rather than being stored into memory and reloaded
- onto the stack. This causes precision problems because the numbers on
- the stack are stored in extended (10- byte) precision while doubles in
- memory are stored using 8 bytes.
-
- Note that the constant 23.31 cannot be represented exactly in the
- binary floating-point scheme used by Microsoft C. The fact that it is
- represented slightly small and then multiplied by 100 (magnifying the
- error) contributes to this problem.
-
- To avoid this problem, use the /Op option when compiling. The /Op
- switch forces in-memory storage of intermediate results. /Op can be
- combined with other optimizations (for instance, /Oxp).
-
- Program Example
-
- /*
-
- When the following program is compiled using default optimization,
- the program prints 2330 instead of 2331 (as it is supposed to.)
- Also, if the commented line is uncommented, the program works
- correctly with default optimization.
-
- */
-
- #include <stdio.h>
- void main(void)
- {
- int a;
- double f;
- f = 23.31;
- f = f * 100;
- /* printf(">%g<\n", f); */
- a = (int)f;
- printf(">%d<\n",a);
- return;
- }
-
-
- 344. Patches of Floating-Point Instructions at Run Time Are Normal
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890217-12193
- Last Modified: 30-MAY-1989 ArticleIdent: Q42762
-
- Question:
-
- I have noticed that memory overwrites occur in the library routine
- i8_input. While debugging the program under CodeView with the
- assembler listing, I noticed that after executing into the code, the
- first 2 bytes of each instruction beginning with a hex CD are
- overwritten. The C statement that generated the assembler code with
- the problem in it was an "fscanf" function call.
-
- Below is an listing example of what is occurring:
-
- Before
- ------
-
- 7E1F:4266 CD35C0 INT 35 ; FLD ST(0)
- 7E1F:4269 CD35E1 INT 35 ; FABS
- 7E1F:426C CD372E7425 INT 37 ; FLD TByte Ptr [__chbuf+5C (2574)]
-
- After
- -----
-
- 7E1F:4266 90 NOP
- 7E1F:4267 D9C0 FLD ST(0)
- 7E1F:4269 90 NOP
- 7E1F:426A D9E1 FABS
- 7E1F:426C 90 NOP
- 7E1F:426D DB2E7425 FLD TByte Ptr [__chbuf+5C (2574)]
-
- Response:
-
- The behavior you describe is quite normal and nothing to worry about.
- Our floating-point package works by generating the INT instructions
- you noticed. When these instructions are executed, the routine they
- call replaces the INT instructions with the either library calls to
- the emulator library or the actual 80 x 87 floating-point
- instructions, depending on whether or not a coprocessor is installed.
-
- When the instructions are executed again, there is no overhead for
- determining whether on not a coprocessor is installed: the proper
- instructions have been patched into place already. This patching
- occurs even if the -FPi87 option has been selected.
-
- You can force in-line 8087 instructions to be put into your code.
- For information on this technique, query on the following keywords:
-
- in-line 8087 instructions
-
- There is no need to do this if your code is going to run under DOS or
- OS/2. Although this article mainly discusses FORTRAN, it applies to C
- as well because the two languages use the same floating-point library.
-
- This code modification occurs only under DOS. Under OS/2, coprocessor
- instructions (such as in the second listing) are always generated. If a
- coprocessor is not present at execution, the instructions cause
- exceptions that are handled by the floating-point emulator software.
-
- Note: Such code modification is impossible under OS/2 because there is
- no way to dynamically change a code segment under OS/2, although it is
- possible to cause a data segment to be executed.
-
-
- 345. Opening a C File When Disk Is Write Protected
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q42773
-
- With the run-time library in the Microsoft C Optimizing Compiler, a
- program can open an existing file for both read and write when the
- floppy disk is write protected. The following statement may be used to
- open the file:
-
- handle = open ("a:test.dat", O_RDWR | O_TRUNC) ;
-
- No error condition is returned and no hard error occurs. However,
- later, when the program tries to write to the file handle or even to
- close the file without writing, a hard error will occur with the
- following message:
-
- Writing protect error writing drive A:
- Abort, Retry, Fail?
-
- This is not a problem with the open() function in the Microsoft C
- run-time library. The low-level DOS function call that is used to
- implement open() does not check for a write-protect error. When the
- file is to be closed by close(), the internal buffer has to be flushed
- to the disk. No low-level DOS function can close a file without
- flushing its associated buffer.
-
- Workaround
-
- There is no direct way to detect the write-protect condition. An
- indirect workaround is to open a file with the mode to be O_CREAT, as
- follows:
-
- open ( "a:chk00000.xxx", O_CREAT, S_IWRITE | S_IREAD) ;
-
- A hard error will occur, which can be captured by a user-implemented
- and installed hard-error handler. This handler will override the
- printing of the hard-error message on the user screen. The open()
- function does return -1 when it regains the control from the
- hard-error handle. If the file was opened successfully, it may be
- removed at the end of the program.
-
- The following sample program demonstrates checking of a
- write-protected disk:
-
- /* sample program */
- #include <fcntl.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include <io.h>
- #include <stdio.h>
- #include <dos.h>
- void far handler ( unsigned, unsigned, unsigned far * ) ;
-
- #define PROTECTED 1
- #define OTHER 2
-
- int Flag = 0 ;
-
- char * ChkName = "a:qwlbqwsi.ufp" ; /* dummy file name */
-
- /* Note:
- ** If the file happens to exist, the hard error will not occur.
- ** The program will output "Disk is not write-protected."
- */
-
- void main(void)
- {
- int FileHandle;
-
- _harderr ( handler ) ; /* set up hard error handler */
-
- FileHandle = open ( ChkName, O_CREAT, S_IWRITE | S_IREAD ) ;
-
- if ( FileHandle == -1 ) /* check write-protect */
- {
- switch ( Flag ) { /* may be set by the handler */
- case PROTECTED :
- puts ( "Disk in drive A: is write-protected." ) ;
- break ;
- case OTHER :
- puts ( "A another hard error has occurred." ) ;
- break ;
- default :
- puts ( "Error opening file (non hard error.)" ) ;
- }
- }
- else {
- puts ( "Disk is not write-protected." ) ;
- close ( FileHandle ) ;
- remove ( ChkName ) ; /* delete the file */
- }
- }
-
- /*
- Hard error routine should be as short as possible
- */
- void far handler ( unsigned deverror, unsigned errcode,
- unsigned far *devhdr )
- {
- if ( errcode == 0 )
- Flag = PROTECTED ;
- else
- Flag = OTHER ; /* like drive door is open */
-
- _hardretn ( 0 ) ;
- }
- /* end of sample */
-
- Note: The argument 0 to _hardretn() is not significant in this
- program. Please refer to Page 351 of the "Microsoft C for the MS-DOS
- Operating System: Run-Time Library Reference" for Version 5.10 for
- more specific information regarding the _hardretn() function.
-
-
- 346. C Compiler: _control87() and Modifying the Control Word
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 25-MAY-1989 ArticleIdent: Q42781
-
- Question:
-
- I want to mask off invalid arithmetic operation interrupts
- (EM_INVALID) from the math coprocessor using the _control87()
- function. However, after masking invalids with _control87() and
- confirming its value, invalids continue to be unmasked.
-
- Can I adjust the control word myself, or does the math package depend
- on a certain state of the control word?
-
- Response:
-
- You cannot mask or unmask certain bits with _control87(), even though
- it will report that it was successful. Also, modifying certain bits of
- the control word yourself (with the 80X87 instruction FLDCW) will
- corrupt all subsequent floating-point C run-time operations.
-
- The documentation in FPEXCEPT.DOC (which is contained in the C 5.10
- package) does state that denormals are always masked off and that
- invalids are never masked. It also states that bits 7, 6, 1, and 0 in
- the control word cannot be modified. It is true that these bits cannot
- be modified with the function _control87(); however, if you look at
- the control word with an assembly routine, you will see that the
- control word does not hold the same value as the C run time would have
- you believe.
-
- Invalid exceptions cannot be masked because the C run time uses them
- internally to handle extending the 80 x 87 floating-point stack beyond
- eight stack elements. If you try to mask invalid with the C run time,
- you will be told that you were successful, but the control word will
- not be changed at all. No invalid exceptions will ever reach you. If
- you try to mask invalid and an invalid exception occurs (which doesn't
- have anything to do with stack overflow or underflow), the C run time
- will check to see if you tried to mask invalid. If you did, the
- floating point routines will simply ignore the mask. If you mask
- invalid by setting the control word from an assembly routine with
- FLDCW, the run time will have stack problems.
-
- As for denormals, the denormal exception is never masked internally
- because every time the 80 x 87 encounters a denormal number, the
- emulator will try to convert it to a normalized number. This is the
- masked behavior on an 80387. Because this should not be changed (since
- it will break our math routines), you should treat denormals as if
- they are always masked. Thus, denormals always appear to be masked;
- you will never see a denormal exception, since they are all handled
- internally by the emulator.
-
- Therefore, denormals always appear to be masked unless you look at the
- control word on the chip directly, by using an FSTCW or CodeView. Also,
- it will appear that invalids can be masked, unless you look at the
- chip directly. If you do look at the chip directly, you will see that
- nothing has changed when trying to mask an invalid with _control87.
- Therefore, the code is functioning as expected. Both invalid and
- denormal are unmasked. If you look at the control word with FSTCW, you
- will see that the default control word is 1370h, instead of the 1332h
- returned by _control87. Also, if you send _control87(0x00ff,0x00ff),
- this function will tell you that the control word is set to 13FFh;
- however, FSTCW will reveal that the control word is really set to
- 137Ch.
-
- Because the run time depends on certain settings of the control word,
- we do not want the run time to modify those settings. You can easily
- write an assembly routine to set the control word to anything you
- like, using FLDCW. It would not be to anyone's advantage to provide a
- floating-point function that would nullify all subsequent
- floating-point run time.
-
- We do not support the modification of the control-word bits mentioned
- above.
-
- For additional information on floating point exceptions, please refer
- to the file FPEXCEPT.DOC contained in the C 5.10 package.
-
-
- 347. Fatal Error C1059: Out of Near Heap Space
-
- Product Version(s): 5.00 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-MAY-1989 ArticleIdent: Q42793
-
- Using the /Zg compiler option to generate function declarations from
- the function definitions can cause the following error:
-
- Fatal error C1059: Out of near heap space.
-
- You may be able to free more space on the near heap by invoking the
- compiler in two passes, as follows:
-
- cl /P filename.c
- cl /Zg /c /Tc filename.I
-
- The first pass processes the preprocessor statements and produces an
- intermediate file. The second pass generates the function declarations
- from the intermediate file.
-
- Both the preprocessor and the compiler /Zg option use the near heap.
- The preprocessor uses the near heap to evaluate macro expansions. The
- compiler /Zg option uses the near heap while producing the function
- declaration listing.
-
-
- 348. Background Colors Limited to 0 Through 7 in Text Mode
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1990 ArticleIdent: Q42796
-
- The function _setbkcolor() displays only colors "0" through "7" when
- in text mode. This is a limit of the hardware, not the library
- function.
-
- Two bytes are allocated for each character displayed on a text 80 x 25
- screen. The first byte is the ASCII code of the character; the second
- is the attribute byte.
-
- The attribute byte contains the information about the foreground and
- background attributes of the character. Four bits of this byte are
- allocated for the foreground color. The most significant bit of the
- foreground color is set aside for intensity or highlight. However, of
- the 4 bits allocated for the background color, the most significant
- bit is reserved to indicate a blinking or a nonblinking state.
-
- The layout of the attribute bytes is as follows:
-
- 7 6 5 4 3 2 1 0
- +----+------------+---+------------+
- | BL | background | I | foreground |
- +----+------------+---+------------+
-
- Since only 3 bits are used to indicate the background color, only
- numbers from 0 through 7 can be represented. For this reason, only
- colors 0 through 7 are available as background colors for
- _setbkcolor().
-
- On most display adapters, you can set the adapter such that the blink
- bit becomes a background intensity bit. See your hardware technical
- reference or the "Programmer's Guide to PC and PS/2 Video Systems"
- (Richard Wilton, Microsoft Press) for more information.
-
-
- 349. Exception #13 at xxxx:xxxx Error Code 0 Caused by QEMM
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QUICKC H_MASM B_QUICKBAS B_BASCOM
- Last Modified: 25-JUL-1990 ArticleIdent: Q42830
-
- A call to Quarterdeck Office Systems has confirmed that their
- Quarterdeck Expanded Memory Manager (QEMM) driver is responsible for
- the following error message reported by several customers:
-
- Exception #13 at xxxx:xxxx
- Error code 0
- Terminate, Reboot or Continue?
-
- This message indicates that an error was detected by the Quarterdeck
- memory manager. This error is essentially the same as a general
- protection fault in OS/2 and typically indicates that a stray pointer
- is involved.
-
- The error may occur either while the program is executing or after
- execution has ended and the program is returning to DOS. A technician
- at Quarterdeck stated that they generally use CodeView to track down
- such errors, and that while the address printed in the error
- diagnostic does not necessarily indicate the precise location of the
- error, it does indicate the location at which the error was first
- detected.
-
-
- 350. Near Const Data Placed in _DATA in C 5.10
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-MAY-1989 ArticleIdent: Q42850
-
- Question:
-
- I have a program which was originally written in Microsoft C Version
- 5.00. From the combined source-object code listing, I notice that the
- near constant data items are placed in the _CONST segment of DGROUP.
- In C Version 5.10, these same data items are placed in the _DATA
- segment. Is there a reason for this, and can I specify the items to
- remain in _CONST?
-
- Response:
-
- In C 5.00, near constant data was placed in _CONST because it was
- constant and produced more easily ROMable code. Unfortunately, the /Gt
- and /ND switches would not affect it. C Version 5.10 reverted to the C
- Version 4.00 convention of putting such data in _DATA. The /Gm switch
- is provided to specify the C Version 5.00 convention instead.
-
- For more information see the Update section, Page 51, of the
- "Microsoft C 5.10 Optimizing Compiler User's Guide."
-
-
- 351. Limit of 40 Files with LLIBCMT.LIB and LLIBCDLL.LIB
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 25-JUL-1990 ArticleIdent: Q42929
-
- Start-up source code is provided for the real- and protected-mode
- standard C run-time libraries. This code can be modified to allow more
- file handles and stream pointers to be opened by a process.
-
- This start-up code is not designed for LLIBCMT.LIB or CRTLIB.DLL.
- These are the protected-mode libraries for multithreaded applications
- and DLLs. The file and stream limits on both of these libraries are
- hard coded at 40.
-
- Handles 0, 1, and 2 are opened by C for stdin, stdout, and stderr,
- while handles 3, 7, and 8 are opened by different OS/2 subsystems.
- With these file handles taken, 34 files can be opened at once.
-
- Note: This restrictin has been removed from the C 6.0 version of these
- libraries. In fact, even with C 5.10, the open file count could be
- bumped up using DosSetMaxFH(). The problem was with the streams. In C
- 6.0, the readme.doc file details how to increase the file stream count
- also.
-
-
- 352. Passing Two-Dimensional Arrays between C and FORTRAN
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | H_FORTRAN
- Last Modified: 18-MAY-1989 ArticleIdent: Q43000
-
- When passing two-dimensional arrays from FORTRAN to C and vice versa,
- it is important to note that the indexing conventions for the two
- languages are different.
-
- C arrays are indexed row followed by column; or, the second index
- varies the quickest. However, FORTRAN is indexed just the opposite: in
- FORTRAN, two-dimensional arrays are indexed with the first indice
- varying the quickest. Thus, passing two-dimensioned arrays requires
- modification to either the C code or the FORTRAN code.
-
- For more information regarding passing arrays between C and FORTRAN,
- please see Page 127, Section 9.1.2, "Array Declaration and Indexing,"
- in the "Microsoft Mixed-Language Programming Guide for the MS-DOS
- Operating System."
-
- The following code samples define an array in a common block in
- FORTRAN, then use C to print the arrays to the screen:
-
- c program mix_for.for
- c
- c
- c this is to be used with mix_c.c......
- c
- subroutine test ()
- common/cblock/array(0:8,0:1)
- integer*4 i,j
-
- do 20 i = 0,8,1
- do 30 j = 0,1,1
- array(i,j) = i
- write(6,*)'the value of (',i,':',j,') is ',array(i,j)
- 30 continue
- 20 continue
- end
-
- /* program mix_c.c
-
- this program is to be used with mix_for.for......
- */
-
- #include <stdio.h>
-
- struct common_blk{
- float array[2][9]; /* note that the subscripts
- of the array are inverted */
- };
-
- extern void fortran test (void);
-
- extern struct common_blk fortran cblock;
-
- main()
- {
- int i,j;
- test();
- for(i=0;i<=8;i++)
- for(j=0;j<=1;j++)
- printf("\nthe value of %d:%d is %f"
- ,i,j,cblock.array[j][i]);
- }
-
-
- 353. Return Values for _remapallpalette and _remappalette
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC docerr
- Last Modified: 17-MAY-1989 ArticleIdent: Q43002
-
- The function _remapallpalette returns (short) -1 when successful and
- (short) 0 on error.
-
- The function _remappalette returns (long) previous color number of the
- pixel on success and (long) -1 on error.
-
- Their return values are incorrectly stated on Page 488 in the
- "Microsoft C for the MS-DOS Operating System: Run-Time Library
- Reference" for both C Version 5.10 and QuickC Version 1.01, the C 5.10
- README.DOC, and QuickC 2.00 Advisor (on-line help screens titled
- "Help: _remapallpalette" and "Help: _remappalette).
-
-
- 354. Reading Extended Keyboard Characters with C
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QUICKC
- Last Modified: 17-MAY-1989 ArticleIdent: Q43007
-
- Question:
-
- How do I read from the extended keyboard with the C _bios_keybrd
- routine? It does not seem to recognize the scan codes for the
- additional keys of the extended keyboard.
-
- Response:
-
- The _bios_keybrd function uses INT function 16H to access the keyboard
- services. The _bios_keybrd function is based on the original PC BIOS
- INT 16H, which does not support the extended keyboard. The BIOS for
- AT's and PS/2's has been updated to support the extended keyboard. The
- updated BIOS has three addition services: 10H reads a character from
- the extended keyboard, 11H gets the extended-keyboard status, 12H gets
- the extended-keyboard flags.
-
- To allow the C function _bios_keybrd to use these updated keyboard
- services, add the following manifest constants to the bios.h include
- file:
-
- /* manifest constants for BIOS enhanced keyboard services */
-
- #define _EXT_KEYBRD_READ 0x10 /* read character */
- #define _EXT_KEYBRD_READY 0x11 /* check if key waiting */
- /* check status of shift keys*/
- #define _EXT_KEYBRD_SHIFT_STATUS 0x12
-
- To read keys from the extended keyboard, use these new constants in
- place of the manifest constants described on Page 138 of the
- "Microsoft C for the MS-DOS Operating System: Run-Time Library
- Reference" for Version 5.10.
-
- The following program uses the enhanced services of INT function 16H
- to determine if the UP ARROW or DOWN ARROW keys on the extended
- keyboard were pressed:
-
- #include <bios.h>
- #include <stdio.h>
-
- main()
- {
- unsigned key;
-
- key = _bios_keybrd(EXT_KEYBRD_READ);
- if ( key == 0x48e0)
- printf("up arrow key was pressed\n");
- if ( key == 0x50e0)
- printf("down arrow key was pressed\n");
- }
-
-
- 355. Switching from Reading to Writing Files Can Garble Data
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc sequence locate position
- Last Modified: 17-JAN-1990 ArticleIdent: Q43072
-
- When switching from reading to writing of C Version 5.10 files, it is
- necessary to do an fsetpos, fseek, or rewind. If you do not use one of
- these library functions, the file pointer may not be updated and you
- could get some erroneous results. This also applies when switching
- from writing to reading. This is documented on Page 275 of the
- "Microsoft C Run-Time Library Reference" manual.
-
- The following program will attempt to read in the first character of a
- file and to write it out as the second character:
-
- #include <stdio.h>
- void main(void)
- {
- FILE *fp;
- char a;
-
- if (( fp = fopen("text.fil","r+")) != NULL)
- {
- fscanf(fp,"%c",a); /* read one character */
- fprintf(fp,"%c",a); /* write to the next location */
- fclose(fp);
- }
- }
-
- The above program will fail because there is no fseek, fsetpos, or
- rewind between the fscanf and fprintf. The following program will
- perform the desired operation:
-
- #include <stdio.h>
- void main(void)
- {
- FILE *fp;
- char a;
- fpos_t loc; /* storage for the current location */
-
- if (( fp = fopen("text.fil","r+")) != NULL)
- {
- fscanf(fp,"%c",a); /* read one character */
- fgetpos(fp,&loc); /* get current file pointer pos */
- fsetpos(fp,&loc); /* set current file pointer pos */
- fprintf(fp,"%c",a); /* write to next location */
- fclose(fp);
- }
- }
-
-
- 356. The Function fopen Accepts Filenames with Embedded Spaces
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q43073
-
- The Microsoft run-time library functions fopen and open do not screen
- for invalid filenames. These functions will accept a filename string
- with an embedded space. For example, the following program will create
- the file "he llo.dat" (without the quotation marks):
-
- #include <stdio.h>
- FILE *fh;
- void main(void) {
- fh = fopen ("he llo.dat", "w+);
- }
-
- This error is not the result of a problem with fopen or open. The
- functions fopen and open should not be expected to screen filenames.
- This activity should be handled by the program using these routines.
- Filename screening is not specified in the "Microsoft C for the MS-DOS
- Operating System: Run-Time Library Reference" manual; this applies to
- both MS-DOS and OS/2.
-
- However, the creation of this file could cause some difficulties under
- DOS. The simplest way to delete such a file would be "del *.dat"
- (without the quotation marks).
-
-
- 357. C: Using the _dos_findfirst and _dosfindnext Functions
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS_DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q43144
-
- Question:
-
- Why do all my files show up in addition to the subdirectories when
- using the _dos_findfirst and _dos_findnext functions to find all the
- subdirectories in my working directory?
-
- Response:
-
- When the attribute argument to the _dos_findfirst and _dos_findnext
- functions is either _A_RDONLY, _A_HIDDEN, _A_SYSTEM, or _A_SUBDIR, the
- functions will return all normal-attribute files. A normal-attribute
- file is any file that does not have a read-only, hidden, system, or
- directory attribute.
-
- Thus, the following function call will return either a normal file or
- a subdirectory:
-
- _dos_findfirst( "*.*", _A_SUBDIR, &c_file )
-
- To verify that the returned c_file is a subdirectory, check the
- attribute field of the c_file to determine whether the _A_SUBDIR bit
- is set. If so, then it is a subdirectory. This process may be
- accomplished by bitwise-ANDing c_file.attrib with _A_SUBDIR and
- checking for a nonzero result.
-
- The following program illustrates the use of these functions:
-
- #include <dos.h>
- #include <stdio.h>
-
- main()
- {
- struct find_t c_file;
-
- _dos_findfirst( "*.*", _A_SUBDIR, &c_file );
-
- if( c_file.attrib & _A_SUBDIR )
- printf( "Directory listing %s\n", c_file.name );
-
- while (_dos_findnext(&c_file) == 0)
- if( c_file.attrib & _A_SUBDIR )
- printf( "Directory listing %s\n", c_file.name );
- }
-
-
- 358. C: How Stack Checking Is Done
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 22-MAY-1989 ArticleIdent: Q43166
-
- Microsoft C does stack checking to check for stack overflow. The stack
- for an application program grows from high memory to low memory. The
- lowest memory location to which the stack can grow is determined in
- Microsoft C as follows:
-
- &end + STACKSLOP /* in assembly: OFFSET _end + STACKSLOP */
-
- The _end symbol is created by Microsoft LINK which assigns it the
- address of the lowest memory location of the STACK segment.
-
- STACKSLOP is a manifest constant. For DOS, STACKSLOP = 256 (decimal);
- for OS/2, STACKSLOP = 512 (decimal).
-
- At runtime, the function _chkstk is called, on entry to each function,
- to check the stack. If the current value of the SP register minus the
- total size of the local variables is less than the sum of &end plus
- STACKLOP, _chkstk prints the following error message and terminates
- the program:
-
- R6000 stack overflow
-
- Otherwise, _chkstk will update the value of SP according to the total
- size of the local variables.
-
- The source code for the function _chkstk is included in the startup
- source code in the Microsoft C Optimizing Compiler Version 5.10.
-
- The value of the SP register is not updated if the stack overflow
- condition is detected.
-
- Stack checking can be manually disabled with either the compile line
- option /Gs, or with the pragma; #pragma check_stack(off). In that
- case, SP will be updated even if a stack overflow occurs.
-
- For more information on _end, query on _edata.
-
-
- 359. Critical Error during Spawn Will Lose Parent
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q43537
-
- A critical error occurs when spawning another program using one of the
- C Version 5.10 run-time library's spawn functions that can prevent the
- child program from returning to the parent process. A sample program
- is shown below.
-
- This is not a problem with the run-time library, but is a limitation
- of the spawn family of functions.
-
- A workaround is to attempt to open the .EXE file before the spawn. The
- critical error will occur on the open and allow DOS and the run-time
- library to handle any problems encountered in a more elegant fashion.
-
- The following program can be used to demonstrate the situation:
-
- #include <stdio.h>
- #include <process.h>
-
- void main( void )
- {
- spawnlp( P_WAIT, "a:\\test.exe", "a:\\test.exe", NULL );
- }
-
- If Drive A is ready, TEST.EXE will be spawned correctly and return to
- the parent. However, if the drive door is open, the following prompt
- will be produced by the DOS critical error handler "Abort, Retry,
- Fail?".
-
- If the drive door is closed and "Retry" is selected, TEST.EXE will run
- but not return to the parent, hanging the system. An assembly language
- program that simply calls DOS interrupt 4B to do the same thing will
- work correctly under the same conditions.
-
-
- 360. C: Cannot Bind Programs with Increased File Handles
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-MAY-1989 ArticleIdent: Q43271
-
- Microsoft C defaults to making 20 file handles available to an
- application. This is the case for both OS/2 and DOS. This number can
- be increased by modifying the start-up source code provided with
- Optimizing C Version 5.10 and linking in the resulting OBJs. This is
- documented in the README.DOC (search for _NFILE_).
-
- However, it is not possible to bind a program that is linked to these
- modified OBJs. This is because the protect-mode start up makes a call
- to DOSSETMAXFH after being modified. This function is not FAPI (dual
- mode) and is not bindable.
-
- To give a program more than 20 file handles under both OS/2 and DOS,
- you must create separate EXEs for each environment.
-
- An attempt to bind a program that is linked with modified start up will
- produce the following error:
-
- LINK : error L2029: Unresolved externals:
-
- DOSSETMAXFH in file(s):
- BV3.OBJ(bindv3)
-
- The start-up files that must be modified to increase the number of
- available file handles are CRT0DAT.ASM and _FILE.C.
-
-
- 361. Printing ASCII Characters Greater Than 127 Fails in CGA Mode
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q43272
-
- When a CGA graphics card is in any CGA graphics mode it will not
- display ASCII characters greater than 127 when Microsoft C text-output
- routines are used. Garbage characters will be displayed instead.
-
- This is expected behavior. The default character-definition table for
- CGA graphics cards contains only the first 128 ASCII characters. To
- print ASCII characters 128 to 255, a separate character-definition
- table must be set up and accessed through interrupt vector 1FH. The
- MS-DOS utility GRAFTABL leaves such a table and hooks the interrupt
- 1FH vector to point to it.
-
- For more information, see Richard Wilton's book "Programmer's Guide to
- PC & PS/2 Video Systems," Page 269, which is available from Microsoft
- Press.
-
-
- 362. C: Spawned Program Accessing Parent's Functions
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 18-MAY-1989 ArticleIdent: Q43318
-
- It is possible for a program spawned with the P_WAIT modeflag to
- successfully call functions within its parent. The functions must be
- set up in such a way that CPU registers are preserved and the data
- segment register is loaded as necessary. It is also vitally important
- that all necessary start-up code and C run time are present whenever
- the parent functions are called.
-
- Warning: This procedure is neither recommended nor supported. This
- article is for informational purposes only.
-
- The programs below, PARENT.C and CHILD.C, demonstrate this technique.
- This method of sharing functions may be useful as a primitive form of
- overlaying when there is a need for a common set of functions to be
- accessed by a sequence of spawned child processes. The method of
- communication from the parent to the child is through command-line
- arguments. In the parent, a far pointer to the function that will be
- called is converted to a string and passed as a parameter through a
- spawn. In the child, it is then converted back into a far pointer.
-
- There are several considerations to be made when writing code of this
- nature.
-
- For any variables in the parent to be accessed, the routines to be
- called must use the _loadds keyword. Not loading DS for the called
- function results in the child's DS being used rather than the DS
- associated with the function in the parent.
-
- Even if _loadds is used, however, DS will not be equal to SS, since
- the child's stack is the one that is used and there is no mechanism in
- C for changing stacks. It is necessary to ensure that the functions
- called by the child do not blow out the child's stack.
-
- Many of the run-time library routines rely on SS equaling DS;
- therefore, one must obviously avoid those routines.
-
- Preservation of the child's state can be accomplished by using the
- _saveregs keyword. This is not necessary when calling C from C;
- however, it may be vital if C is being called from MASM.
-
- All calls must be far since the parent and child were loaded
- separately. Different memory models may be used for parent and child.
-
- This process obviously produces a general-protection fault in OS/2.
- Use dynamic link libraries to duplicate this functionality with
- greater ease, portability, and safety.
-
- The following is the parent program:
-
- /*
- * PARENT.C
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <process.h>
-
- int far _saveregs _loadds foo( void );
- void main( void );
-
- int k = 0,
- l = 0; /* Globals to be accessed inside foo */
-
- int far _saveregs _loadds foo()
- {
- int i, /* Return value */
- j; /* Indexing */
-
- for( j = 1; j < 10; j++ )
- {
- k = k + j;
- l = k * j;
- }
- i = k + l;
- return( i );
- }
-
- void main()
- {
- int (far _saveregs _loadds *fooaddr)(); /* foo() pointer */
- char address[16]; /* address to pass */
-
- printf( "Now inside parent main().\n" );
- fooaddr = foo;
- ultoa( (unsigned long)fooaddr, address, 10 );
- printf( "Address of foo(): %s\n", address );
-
- spawnlp( P_WAIT, "child.exe", "child.exe", address, NULL );
- printf( "Back inside parent main().\n" );
- }
-
- The following is the child program:
-
- /*
- * CHILD.C
- */
-
- #include <stdio.h>
- #include <stdlib.h>
-
- void main(
- int argc,
- char **argv )
- {
- int (far *fooaddr)(); /* Pointer to parent's function */
- int i; /* Function return value */
-
- printf( " Now in child.\n" );
- fooaddr = (void far *)atol( argv[1] );
- printf( " Received: %ld\n", fooaddr );
- printf( " Calling foo().\n" );
- i = fooaddr();
- printf( " Result of foo(): %d\n", i );
- printf( " Leaving child.\n" );
- }
-
-
- 363. C: exec and spawn (P_OVERLAY) Will Fail When Bound
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | O_OS2SDK
- Last Modified: 15-JAN-1990 ArticleIdent: Q43319
-
- The Microsoft C run-time library functions exec and spawn (with a
- P_OVERLAY attribute) do not work correctly when executed in a bound
- application under DOS. This is briefly documented on Page 24 of the
- "Microsoft C for MS OS/2 and MS-DOS Operating Systems: Version 5.1
- Update" manual. The execution will fail with the program returning the
- following error message:
-
- run-time error R6006
- - bad format on exec
-
- This occurs only when the dual-mode program is running under DOS. A
- spawn with the P_WAIT attribute will work properly.
-
- Examining the DosExecPgm() API reveals that there is no option to
- overlay the currently executing program. OS/2's protection scheme does
- not support overwriting the code segment; therefore, to exec another
- program, it is necessary to actually spawn the program in a different
- area of memory and terminate the current process.
-
- To create a bound program that uses overlays, not only would a
- remapping of the FAPI function be necessary, but also a complete
- reprogramming to allow for loading over the current code segment. At
- this time, BIND does not support this.
-
- The following functions do not work properly when executed under DOS
- in a bound application:
-
- execl execle execlp execlpe execv execve execvp
- execvpe spawnl spawnl spawnle spawnlp spawnlpe spawnv
- spawnve spawnvp spawnvpe
-
- Note: The spawn functions fail only with the P_OVERLAY attribute.
-
- The following program will fail to spawn PROG.EXE from DOS:
-
- /* Program: spawn.c */
- /* */
- /* Compile and bind from OS/2 with: */
- /* */
- /* cl /Lp spawn.c */
- /* bind spawn /c/lib/api.lib /c/lib/doscalls.lib */
-
- #include <stdio.h>
- #include <process.h>
-
- void main(void)
- {
- spawnl(P_OVERLAY,"c:\\tmp\\prog.exe","prog",NULL);
- }
-
-
- 364. How to Use _remappalette in EGA Modes
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q43330
-
- When attempting to remap the palette in the EGA modes, follow the
- required format to form the argument passed to the remapping
- functions. This article uses _remappalette as an example. What is said
- about lColor (see function prototype below) also applies to the
- element of the array slColors for _remapallpalette.
-
- The function prototypes are as follows:
-
- short far _remappalette (nPixel, lColor) ;
- short nPixel ;
- long lColor ; Color number to assign nPixel to
-
- short far _remapallpalette (slColors) ;
- long far * slColors ; Color array
-
- lColor is a long int formed by the following four bytes:
-
- 00, blue byte, green byte, red byte
-
- The four bytes are arranged from the most significant byte to the
- least significant byte (left to right). The most significant byte is
- always "0" (zero). Each of the remaining three bytes can have the
- value of either 00, 2a, 15, or 3f. (In VGA mode, each byte can take
- any value between 00 and 3f.) Combinations of different values in the
- three bytes form the complete palette of 64 colors for the EGA
- graphics modes.
-
- The manifest constants for the EGA modes are _MRES16COLOR,
- _HRES16COLOR, and _ERESCOLOR, which are used with the function
- _setvideomode.
-
- Please refer to the include file "GRAPH.H" for the default values of
- the 16 colors in an EGA mode.
-
- An algorithm is provided in this section to convert a color
- represented by an arbitrary number from 0 - 63 to the required format.
- A sample program is included that implements the algorithm.
-
- Suppose the color is represented by a byte, as follows:
-
- bit7 , bit6 , bit5 , bit4 , bit3 , bit2 , bit1 , bit0
-
- 1. bit7 and bit6 can be ignored, because the byte is always less than
- 64.
-
- 2. The remaining bits are grouped in the following three pairs, where
- the order of the two bits in the pair is significant:
-
- bit3 , bit0 ;
- bit4 , bit1 ;
- bit5 , bit2 ;
-
- 3. Each pair is mapped to 00, 2a, 15, or 3f, according to the
- following table:
-
- bitX bitY MappedXY
- 0 0 00
- 0 1 2a
- 1 0 15
- 1 1 3f
-
- 4. Mapped30 (from pair bit3, bit0) goes to the blue byte.
- Mapped41 (from pair bit4, bit1) goes to the green byte.
- Mapped52 (from pair bit5, bit2) goes to the red byte.
-
- The order (from high to low) of the three bytes is as follows:
-
- blue byte , green byte , red byte
-
- 5. Example:
-
- Color 43 has bit pattern 0 0 1 0 1 0 1 1. This pattern is
- transformed to three pairs : 11, 01, 10. The three pairs are mapped
- to 3f, 2a, 15. The mapped color represented in long integer format
- is 0x3f2a15.
-
- The following program uses _remappalette to remap the color "0" (which
- defaults to black) to the 64 different colors:
-
- // file : palette.c
-
- #include <stdio.h>
- #include <graph.h>
- #include <conio.h>
-
- #define NUMCOLOR 64
- #define MASK 0x0001
-
- unsigned long ConvertColNum (unsigned int) ;
-
- unsigned char ConvertArr [4] = { 0x00, 0x2a, 0x15, 0x3f } ;
-
- void main (void)
- {
- unsigned short nColor = 0 ;
- unsigned int i ;
- unsigned long lMappedColor ;
-
- if (!_setvideomode (_ERESCOLOR))
- return ;
-
- puts ("Press any key to continue ...") ;
- getch () ;
-
- for (i = 0 ; i < NUMCOLOR ; i++)
- {
- lMappedColor = ConvertColNum (i) ;
- if (_remappalette (nColor, lMappedColor) == -1L)
- puts ("\x007Mapping color failed : ") ; // beep if fails
-
- printf ("Color number = %u, lMappedColor = %08lx\n", i,
- lMappedColor);
- if (getch () == 'q')
- break ;
- }
-
- _setvideomode (_DEFAULTMODE) ;
- }
-
- unsigned long ConvertColNum (unsigned int nOrgColor)
- {
- unsigned long lColor, lTemp ;
- int j, temp ;
-
- lColor = 0L ;
- for (j = 0 ; j < 3 ; j++)
- {
- // get the pair
- temp = ((nOrgColor >> (j + 3) & MASK) << 1 ) |
- (nOrgColor >> j & MASK) ;
- lTemp = (unsigned long) ConvertArr [ temp ] ;
- lColor |= lTemp << ((2-j) << 3) ; // (2-j) * 8
- }
-
- return (lColor) ;
- }
-
-
- 365. Changing System Time or Date Will Temporarily Pause Clock
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q43331
-
- The system clock temporarily pauses when the time or the date is set.
- This feature prevents cases in which the date or time may need to be
- updated during the actual time change. For example, an attempt to set
- the system date exactly at midnight using _dos_setdate would not
- produce the desired effect if the system changed the date at the same
- time it was being set. Therefore, the system clock pauses.
-
- The effects of such a pause can be seen in the sample program that
- follows. If you run this program, you will find upon exit that the
- system time is the same as when the program was started.
-
- The following is the sample program:
-
- /* Note - this code takes a couple of minutes to run */
- #include <stdio.h>
- #include <dos.h>
-
- struct dosdate_t Date;
- struct dostime_t Time;
- unsigned long loop;
-
- void main(void) {
- _dos_getdate(&Date); /* Show time when starting */
- _dos_gettime(&Time);
- printf ("Today's date is %d-%d-%d\n", Date.month, Date.day,
- Date.year);
- printf ("Start time = %d:%d\n", Time.hour, Time.minute);
-
- Date.year = 1988;
- for (loop = 1; loop <= 200000; loop++) {
- _dos_setdate(&Date);
- }
-
- _dos_getdate(&Date); /* Show time after loop */
- _dos_gettime(&Time);
- printf ("Date is now %d-%d-%d\n", Date.month, Date.day, Date.year);
- printf ("End time = %d:%d\n", Time.hour, Time.minute);
- }
-
-
-
- 366. Handling Floating-Point Errors in C
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-MAY-1989 ArticleIdent: Q43391
-
- You can set up a floating-point error-handling routine by using the
- signal() function. Do not use the return() function to return to the
- calling process. If return() is used, the floating-point state is left
- undefined.
-
- Instead, use the function setjmp() to save the stack environment
- before each section of the calling process code that may potentially
- generate a floating-point error. In the error handler, use _fpreset()
- to reinitialize the floating-point package and longjmp() to return to
- the calling process.
-
- The sample program on Page 280 of the "Microsoft C Run-time Library
- Reference" demonstrates the use of setjmp(), _fpreset(), and longjmp()
- to handle a floating-point error.
-
- The function setjmp() saves the environment (bp, si, di, sp, and ds
- registers) and return address in a buffer. The buffer is used by
- longjmp() to restore the environment.
-
-
- 367. C: Clarification of the "g" Format Specifier
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q43392
-
- The output format resulting from the printf() format specifier "g"
- does not exactly match the output format resulting from either format
- specifier "e" or "f." Page 459 of the "Microsoft C Run-Time Library
- Reference" states that "g" will use either the "f" or "e" format,
- whichever is more compact.
-
- The precision value is interpreted differently in "g" format than in
- "f" format. Table R.3 on Pages 461-2 states the difference. The
- precision for "f" specifies the number of digits after the decimal
- point. The precision for "g" specifies the maximum number of
- significant digits printed.
-
- The following example demonstrates the difference:
-
- #include <stdio.h>
-
- void main (void)
- {
- printf ("%.4g\n", 4.0/3.0); /* Outputs: 1.333 */
- printf ("%.4f\n", 4.0/3.0); /* Outputs: 1.3333 */
- }
-
- The results of the above program are correct.
-
-
- 368. C: _bios_timeofday Documentation Error
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 14-APR-1989 ArticleIdent: Q43396
-
- On Page 146 of the "Microsoft C 5.1 Optimizing Compiler Run-Time
- Library Reference" manual and the "Microsoft QuickC Run-Time Library
- Reference" manual, the second parameter of _bios_timeofday is
- incorrectly stated as a long integer, as follows:
-
- long timeval;
-
- The corrected declaration is a pointer to a long integer, as follows:
-
- long *timeval;
-
-
- 369. Incorrect Reference to Preprocessor Directives in User's Guide
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 14-APR-1989 ArticleIdent: Q43398
-
- Section 3.3.9 on Page 75 of the "Microsoft C 5.1 Optimizing Compiler
- Users' Guide" has a documentation error at the bottom of the second
- paragraph.
-
- The paragraph refers to Section 8 of the "Microsoft C Quick Reference
- Guide"; however, Section 8 does not exist. The actual location of the
- information is in Part 2 on Pages 30-32 of the Quick Reference Guide.
- This section contains a listing of the preprocessor directives.
-
-
- 370. How to Test for an Error When Using _bios_serialcom Service
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc docerr
- Last Modified: 14-APR-1989 ArticleIdent: Q43401
-
- Problem:
-
- I am using the _COM_RECEIVE function of _bios_serialcom to read data
- from a communications port. How do I determine if an error has
- occurred?
-
- Response:
-
- Referring to the table on Page 144, Page 145 of the "Microsoft
- Optimizing C Run-Time Library Reference" and the "Microsoft QuickC
- Run-Time Library Reference" states the following:
-
- If an error occurs, at least one of the high-order bits will be
- set.
-
- While this is correct, it is misleading. It is true that at least one
- of the high-order bits will be set if an error occurs. However, it is
- not true that if ANY high-order bit is set, an error has occurred. An
- error has occurred if, and only if, any of the following four bits are
- set:
-
- Bit Meaning if Set
-
- 15 Timed out
- 11 Framing error
- 10 Parity error
- 9 Overrun error
-
- The sentence quoted above would be more accurate if it read as
- follows:
-
- If an error occurs, any of bits 9, 10, 11, or 15 will be set.
-
- This information is explained on Page 431 of "Advanced MS-DOS" by
- Ray Duncan.
-
-
- 371. The Storage of Environment Variables
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 17-MAY-1989 ArticleIdent: Q43428
-
- Question:
-
- How can I find out where the environment variables (PATH, LIB, etc.)
- are being stored?
-
- Response:
-
- The environment variables are stored in the near heap, which is part
- of DGROUP. The ENVIRON variable is an array of pointers to the strings
- that constitute the process environment. The C start-up code takes the
- environment information and initializes the ENVIRON variable to point
- to the environment table. The function getenv() uses the ENVIRON
- variable to access the environment table. ENVIRON can be used to
- obtain the environment table address directly.
-
- The following program will print out the address of the beginning of
- the environment table and the PATH environment variable:
-
- #include <stdlib.h>
- #include <stdio.h>
-
- char *path;
-
- void main (void)
- {
- path = getenv( "PATH" );
- printf( "path: %s\nenviron: %x\n", path, environ );
- }
-
-
- 372. Why _setvideomode() May Fail to Set Some Modes
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QUICKC setvideomode _setvideomode
- Last Modified: 25-MAY-1989 ArticleIdent: Q43587
-
- The following are possible reasons that _setvideomode() might fail
- when attempting to set a video mode:
-
- 1. Some of the older IBM EGA (enhanced graphics adapter) cards only
- have 64K of video memory. As such, they cannot display the
- 640 x 350 16 (_ERES16COLOR) color EGA mode. However,
- lower-resolution modes may work correctly because they don't
- require that much memory.
-
- 2. There are EGA cards that have dip-switch settings to set the card
- into high- or low-resolution modes. Some BIOS ignore these dip
- switches and set the mode to high resolution. However, the
- _setvideomode() function does its own checking and may honor the
- dip-switch settings depending on the particular card. Setting the
- dip switches properly for the high-resolution modes should resolve
- the problem.
-
- 3. The video card may not support the requested mode. If the card does
- not support the mode, then _setvideomode() cannot set it into that
- mode.
-
- 4. Many VGA cards have non-standard extended modes that are unique to
- those cards. _setvideomode() supports only standard video modes
- and, thus, will not recognize the extended modes.
-
-
- 373. C: Loop Optimization Causes Internal Compiler Error
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 26-SEP-1989 ArticleIdent: Q43700
-
- The two programs shown below demonstrate the following internal
- compiler error. The error occurs in the Microsoft C Optimizing
- Compiler Version 5.10, when compiled with loop and alias relaxation
- optimization enabled, and either the compact or large-memory models.
-
- fatal error C1001 : Internal Compiler Error
- (compiler file '@(#)regMD.c:1.117', line 1861)
- Contact Microsoft Technical Support
-
- An easy workaround is to not use the /Oal combination, or use a
- different memory model.
-
- The first program is as follows:
-
- int flags = 0; /* change to int j, flags = 0 */
- void main(int argc, char *argv[])
- {
- int i,j; /* change to int i; */
- for (i=1; i<argc; i++)
- switch(argv[i][0]) {
- case '-':
- for (j=1; argv[i][j]; j++)
- switch (argv[i][j]) {
- case 'a' : flags |= 0x1; break;
- case 'b' : flags |= 0x2; break;
- case 'c' : flags |= 0x4; break;
- case 'd' : case '?': default: flags = 0x8; break;
- }
- }
- }
-
- To work around this problem, move the declaration of "j" outside of
- main().
-
- The second program is as follows:
-
- typedef struct LINE {
- short l_used;
- char l_text[1];
- } LINE;
-
- typedef struct WINDOW {
- LINE *w_dotp;
- } WINDOW;
-
- extern WINDOW *curwp;
-
- void main()
- {
- int nicol;
- int c;
- int i;
-
- for (i=0; i< curwp->w_dotp->l_used; ++i) {
- c = curwp->w_dotp->l_text[i]&0xFF;
- if (c!=' ' && c!='\t')
- break;
- if (c == '\t')
- nicol |= 0x07;
- ++nicol;
- }
- }
-
- You can work around this problem by adding a new variable of type
- pointer to WINDOW and then using this pointer in the assignment to the
- variable "c". For example, you can change the for loop in the code to
- appear as follows:
-
- for (i=0; i< curwp->w_dotp->l_used; ++i) {
- WINDOW *foo1;
- foo1 = curwp;
- c = foo1->w_dotp->l_text[i]&0xFF;
-
- if (c!=' ' && c!='\t')
- break;
- if (c == '\t')
- nicol |= 0x07;
- ++nicol;
-
- Microsoft is researching this problem and will post new information as
- it becomes available.
-
-
- 374. C: srand() Sample Program Does Not Print Out the Array Values
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | DOCERR S_QuickC
- Last Modified: 22-MAY-1989 ArticleIdent: Q43808
-
- In the following manuals, the sample program given for the function
- srand() implies that it will print out random values for each of the
- array elements. Although the array is filled with random values, these
- values are not printed because the "for" loop is implemented
- incorrectly. This example is given in both the "Microsoft C for the
- MS-DOS Operating System Run-Time Library Reference" manual for
- Versions 5.00 and 5.10, and the "Microsoft QuickC Run-Time Library
- Reference" manual for Versions 1.00 and 1.10.
-
- The following source code fragment is excerpted from the sample
- program found in the "Microsoft QuickC Run-Time Library Reference"
- manual on Page 564.
-
- srand(17);
- for (x = 0; x < 20; ranvals[x++] = rand())
- printf("Iteration %d, ranvals[%d] =%d\n",x+1, x, ranvals[x]);
-
- If you execute the program as written, it produces a list of all zeros
- instead of a list of the random numbers being put into the array. To
- understand why this is so, the definition of a for loop must be
- considered. The for loop defined by Kernighan and Ritchie is as
- follows:
-
- for (expr1, expr2, expr3)
- statement;
-
- is equivalent to:
-
- expr1;
- while (expr2)
- {
- statement;
- expr3;
- }
-
- If the above sample program is substituted into this definition, then
- the program reads as follows:
-
- srand(17);
- x = 0;
- while (x < 20)
- {
- printf("Iteration %d, ranvals[%d] =%d\n",x+1,x,ranvals[x]);
- ranvals[x++] = rand();
- }
-
- This program obviously prints the array elements one step before they
- are initialized, which is why the sample program prints out all zeros
- instead of the desired random numbers.
-
- To display the correct results, you must take the call to the
- function rand() out of expr3 of the for statement. This can be
- accomplished as follows:
-
- srand(17);
- for (x = 0; x < 20; x++)
- {
- ranvals[x] = rand();
- printf("Iteration %d, ranvals[%d] =%d\n",x+1, x, ranvals[x]);
- }
-
-
- 375. Casting a Pointer to a Type Equivalent to a Multidimensional
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 17-MAY-1989 ArticleIdent: Q43703
-
- In some situations you may need to cast a pointer or an address to a
- type that is equivalent to a multidimensional array. The following
- example demonstrates such a situation:
-
- typedef char Arr2Dim [][20] ;
- void foo (Arr2Dim) ;
- char * ptr ;
- ...
- void main (void)
- {
- ...
- foo ( (Arr2Dim) ptr ) ; /* illegal */
- ...
- }
-
- Casting the variable "ptr" to the array type "Arr2Dim" is illegal. The
- Microsoft C Compiler displays the following error message:
-
- error C2067: cast to array type is illegal
-
- The correct procedure is to cast the pointer "ptr" to a pointer type
- equivalent to the array type Arr2Dim. This pointer type can be defined
- as follows:
-
- typedef char (*Ptr2Dim) [20] ;
-
- Casting "ptr" to the type of "Ptr2Dim", as follows, is legal and
- produces no warning messages when compiled at warning level 3:
-
- foo ( (Ptr2Dim) ptr ) ;
-
- The address (or pointer) passed to the function will be used
- correctly.
-
- A similar solution could be applied to the problem of dynamically
- allocating a multidimensional array. For example, the following code
- fragment will allocate a memory block, which can be used as a 10 x 20
- x 30 three-dimensional array:
-
- typedef char (*Ptr3Dim) [20][30] ;
- Ptr3Dim ptr3arr ;
- ...
- void main (void)
- {
- ...
- ptr3arr = (Ptr3Dim) malloc (10 * sizeof(char) * 20 * 30) ;
- ...
- }
-
- After the allocation, "ptr2arr" can be used as a three-dimensional
- array, as follows, provided i, j, and k are integers within the proper
- range:
-
- ptr2arr [i][j][k] = 'a' ;
-
-
- 376. Changes in scanf() and printf() for Long Types in C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 19-SEP-1989 ArticleIdent: Q43809
-
- As of Version 5.10 of the Microsoft C Optimizing Compiler and Version
- 1.00 of the QuickC compiler, the scanf() and printf() functions no
- longer support the uppercase D, O, and I type characters, which
- represented long-integer fields.
-
- Current versions of Microsoft C compilers precede the type characters
- in the format portion of the printf() and scanf() functions with an
- "l" (lowercase letter "l") to specify long-type fields.
-
- The uppercase "X" format specifier also has been changed; it now
- specifies that uppercase letters are to be used when displaying
- hexadecimal numbers in a printf() statement.
-
- The following code fragment reads an integer into a variable and then
- displays the value of the variable:
-
- int i;
- scanf( "%d", &i );
- printf( "%d", i );
-
- The following code fragment accepts and displays the value of a long
- integer variable:
-
- long i;
- scanf( "%ld", &i );
- printf( "%ld", i );
-
-
- 377. C: PUSH CS Caused by Far Call Translation
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 22-MAY-1989 ArticleIdent: Q43810
-
- Question:
-
- When I look at an assembly listing generated by the Microsoft C
- Version 5.10 Optimizing Compiler, I notice that the compiler produced
- PUSH CS instructions. Should the compiler be generating PUSH CS
- instructions?
-
- Response:
-
- One of the optimizations made by the Microsoft C 5.10 compiler is Far
- Call Translation. Far Call Translation optimization results in
- slightly faster code and smaller executable files.
-
- The compiler normally generates far calls and corresponding far
- returns for large and medium-memory-model programs. Far Call
- Translation is performed if optimizations are enabled and a call is
- being made from one function to another in the same source file. The
- usual CALL FAR LABEL is replaced with the following instruction
- sequence:
-
- PUSH CS
- CALL NEAR LABEL
-
- The called function is in the same code segment because it is located
- in the same source file, so a near call is possible in this case. The
- PUSH CS instruction allows the far return from the called function to
- retrieve CS from the stack and return to the correct location.
-
-
- 378. Fscanf() and White-Space Characters
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 30-NOV-1989 ArticleIdent: Q50116
-
- Problem:
-
- I try to read one integer on a line from a data file and then advance
- the file pointer to the next line using the following:
-
- fscanf("%d\n", &INT);
-
- However, I am unable to do this. The file pointer seems to jump to the
- next character in the data file, wherever it may be, instead of
- stopping at the first position of the next line.
-
- Response:
-
- According to the "Microsoft C for the MS-DOS Operating System Run-time
- Library Reference," Page 501:
-
- A white-space character (in the format string) causes scanf to
- read, but not store, all consecutive white-space characters in the
- input up to the next non-white-space character. One white-space
- character in the format matches any number (including 0) and
- combination of white-space characters in the input.
-
- In other words, because you have white space in your format specifier,
- "\n", after the %d, fscanf() eats up all white space AFTER the
- integer, including newline until the first nonwhite-space character is
- found.
-
- The following are possible workarounds:
-
- 1. Use the following fscanf() statement:
-
- fscanf("%d[^\n]%*c}, &INT)
-
- This tells fscanf() to read an integer and then read UNTIL it finds
- the "\n". At that point, it is necessary to read in the \n. The
- "%*c" reads, but does not store, one character.
-
- 2. Use fgets() to read in the line and then use sscanf to get the
- value, as follows:
-
- fgets( line, MAX_LINE_SIZE, stream );
- sscanf( line, "%d", &INT);
-
-
- 379. Determining the Memory Model for Conditional Compilation
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_QuickC
- Last Modified: 25-JUL-1989 ArticleIdent: Q44386
-
- There is a predefined identifier that can be used to allow the
- preprocessor to determine which memory model has been chosen for the
- current compilation. The identifier is M_I86?M, where "?" is an
- identifier for one of the following five memory models:
-
- S = Small
- M = Medium
- L = Large
- C = Compact
- H = Huge
-
- This identifier can be used with a preprocessor command to produce
- conditional compilation dependent upon the memory model. An example of
- its use is shown below. For more information, refer to the include
- file MALLOC.H, which uses the identifier to determine which variant of
- the memory allocation function "malloc" should be used in the current
- compilation.
-
- Code Example
- ------------
-
- /*
- *
- * This example demonstrates how to use the C compiler M_I86?M values.
- * It also shows other various preprocessor components. The
- * memory model is displayed using the message() pragma. If the memory
- * model is not recognized by the program, the compilation terminates
- * using the #error preprocessor directive. The identifier _MEMORY_MODEL_
- * has been chosen arbitrarily, and has no special value to the C compiler.
- *
- */
-
- #include <stdio.h>
-
- #if defined (M_I86CM)
- #define _MEMORY_MODEL_ "compact"
- #elif defined (M_I86SM)
- #define _MEMORY_MODEL_ "small"
- #elif defined (M_I86MM)
- #define _MEMORY_MODEL_ "medium"
- #elif defined (M_I86LM)
- #define _MEMORY_MODEL_ "large"
- #elif defined (M_I86HM)
- #define _MEMORY_MODEL_ "huge"
- #else
- #error "ERROR: unknown memory model!!"
- #define _MEMORY_MODEL_ "**UNKNOWN**"
- #endif
-
- #pragma message ("Using the " _MEMORY_MODEL_ " memory model...")
-
- void main(void);
-
- void main(void)
- {
- printf("hello, world\n");
- }
-
-
- 380. C: Finding the Length of Double Precision Decimals
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G890424-17022 s_quickc
- Last Modified: 22-MAY-1989 ArticleIdent: Q43913
-
- Question:
-
- Is there a straightforward way to determine how many decimal digits
- are required to fully represent the integer and fractional portions of
- a double floating-point number?
-
- Response:
-
- The most straightforward method is to convert the double to a string,
- locate the decimal point, and then calculate the length of the
- substrings before and after it.
-
- The following example demonstrates the technique:
-
- #include <stdio.h>
- #include <string.h>
- #include <ctypes.h>
-
- char str[30];
- double stuff;
- int dec_pos, places_after, places_before;
-
- ...
-
- sprintf(str, "%f", stuff);
- dec_pos = strcspn( str, "." );
- places_after = strlen( str ) - dec_pos - 1;
- places_before = dec_pos - !isdigit( str[0] );
-
- The strcspn function returns the position in str at which "." is
- found. The isdigit() function accounts for the presence or absence of
- a minus or plus sign. The sequence of steps in the string "-1253.356"
- results in the following values:
-
- dec_pos == 5
- places_after == (9 - 5 - 1) == 3
- places_before == (5 - 1) == 4
-
-
- 381. C: Text Modes Don't Return Pixel Information
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 11-JAN-1990 ArticleIdent: Q43914
-
- After a call to _getvideoconfig () from text modes, the structure
- videoconfig contains zero (0) for numxpixels, numypixels, and
- bitsperpixel. This is expected behavior because only the graphics
- modes return pixel information.
-
- Both text and graphics modes return information about the number of
- text columns and rows.
-
- The following example demonstrates the absence of pixel information
- in text modes. The name of each text mode begins with "_TEXT."
-
- #include stdio.h
- #include graph.h
-
- struct videoconfig vc; /* variable vc of type videoconfig */
-
- /* define an array of video modes and mode names
- since the numbers are not continuous */
-
- int modes[12] = {_TEXTBW40, _TEXTC40, _TEXTBW80, _TEXTC80,
- _MRES4COLOR, _MRESNOCOLOR, _HRESBW, _TEXTMONO,
- _MRES16COLOR, _HRES16COLOR, _ERESNOCOLOR, _ERESCOLOR};
-
- char *modenames[] = {"TEXTBW40", "TEXTC40", "TEXTBW80",
- "TEXTC80", "MRES4COLOR", "MRESNOCOLOR",
- "HRESBW", "TEXTMONO", "MRES16COLOR",
- "HRES16COLOR", "ERESNOCOLOR", "ERESCOLOR"};s0
- main()
- {
-
- int i;
- /* test all video modes */
- for (i=0; i<= 11; i++) {
- _setvideomode (modes[i]);
- _getvideoconfig (&vc);
- printf ("\n video mode: \t%s\n",modenames[i]);
- printf (" x pixels: \t%d\n",vc.numxpixels);
- printf (" y pixels: \t%d\n",vc.numypixels);
- printf (" text columns: \t%d\n",vc.numtextcols);
- printf (" text rows: \t%d\n",vc.numtextrows);
- printf (" # of colors: \t%d\n",vc.numcolors);
- printf (" bits/pixel: \t%d\n",vc.bitsperpixel);
- printf (" video pages: \t%d\n",vc.numvideopages);
- printf (" Hit return for next video mode");
- getchar();
- _clearscreen (_GCLEARSCREEN);
- }
- _setvideomode (_DEFAULTMODE);
- }
-
- The definition of structure videoconfig and the arguments to
- _setvideomode() are contained in the include file graph.h. The
- arguments for _setvideomode() are also present on Page 539 of the
- "Microsoft C for the MS-DOS Operating System: Run-Time Library
- Reference."
-
-
- 382. qsort(): Parameters to the Compare Function
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 22-MAY-1989 ArticleIdent: Q43971
-
- When you define or prototype a comparison function for the run-time
- library function qsort(), the formal parameters should be of type
- "pointer to the type of the array element." This is because qsort()
- passes the addresses of the array elements to the comparison function.
-
- If the declaration of the array to be sorted is
-
- ELEMENT_TYPE arr[10] ;
-
- where ELEMENT_TYPE is the type of the array elements, then the
- function for comparison should be prototyped as follows:
-
- int comp( ELEMENT_TYPE *, ELEMENT_TYPE * ) ;
-
- If arr is declared instead as an array of pointers to structure foo,
- then the declaration and prototype should be as follows:
-
- struct foo * arr[10] ;
- int comp( struct foo **, struct foo ** ) ;
-
-
- 383. How to Flush the Keyboard Typeahead Buffer
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 22-MAY-1989 ArticleIdent: Q43993
-
- To flush the BIOS keyboard typeahead buffer, the DOS function 0xC may
- be used. This function clears the keyboard typeahead buffer and then
- invokes a reading function specified in the AL register. The AL
- register can be 0x01, 0x06, 0x07, 0x08, or 0x0A to specify a valid
- reading function. If you do not intend to read after flushing the
- buffer, you may specify an invalid number in AL.
-
- Another method of flushing BIOS's buffer is to call the console I/O
- function getch() until the function kbhit() becomes false. This
- method is demonstrated in the program below and has the advantage of
- being usable under OS/2 as well as DOS.
-
- The buffer implemented by the C run-time functions for the stream
- "stdin" is different from the BIOS keyboard typeahead buffer. To clear
- the buffer for stdin, use the function fflush(). However, this method
- will not flush BIOS's buffer. To be totally flushed, you must both
- flush BIOS's buffer as described above in this article AND call fflush
- for stdin.
-
- The following sample program is provided for demonstration:
-
- // sample program
- #include <stdio.h>
- #include <time.h>
- #include <conio.h>
- #include <dos.h>
-
- void main (void)
- {
- time_t start, work ;
- char str [50] ;
-
- puts ("type for getchar(). Go to stdin's buffer.") ;
- // user can type more than one character and an Enter.
- getchar () ;
-
- puts ("Type fast, 5 seconds. Go to BIOS buffer.") ;
- // user can type anything including multiple Enters.
- time (&start) ;
- work = start ;
- while ( (work - start) < 5 ) time (&work) ;
-
- bdos (0xC, 0, 0) ; // clear BIOS keyboard buffer
-
- // Alternative method:
- // while (kbhit()) getch();
-
- fflush (stdin) ; // clear stdin's buffer
- puts ("Should be waiting again.") ;
-
- gets (str) ;
- puts (str) ;
- }
-
-
- 384. SETUP /L Does Not Create SETARGV.OBJ in C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 22-MAY-1989 ArticleIdent: Q44001
-
- Invoking C Version 5.10 SETUP with the /L command (to rebuild the
- libraries) should create xSETARGV.OBJ (where x = S,M,C,L) for each
- memory model chosen if a "C 4.00 compatible names for SETARGV.OBJ"
- option is requested during setup. However, when the Setup program is
- invoked with the /L command, it does not generate SETARGV.OBJ for any
- memory model. Setup does not even copy that file to the destination
- drive; only the setup for the whole compiler creates xSETARGV.OBJ for
- different memory models.
-
- C 4.00 has four model-specific object modules, xSETARGV.OBJ (where x =
- S,M,C,L), which you can link into a program to get wild-card expansion
- for program arguments. In C 5.10 there is only one object SETARGV.OBJ
- needed for ALL memory models. However, if you have MAKE files which
- rely on the C 4.00 convention, you may want to tell the Setup program
- to make COPIES of this file with the appropriate model-specific name.
- In fact, the modules of xSETARGV.OBJ are all identical and differ only
- in their names. Renaming SETARGV.OBJ is all that is required.
-
- Therefore, if you are using SETUP just to rebuild the libraries and
- have chosen C 4.00 compatibility, you must find SETARGV.OBJ on the
- disk labeled "Floating-Point Libraries" and you must copy/rename that
- file to suit the memory model(s) you have built.
-
-
- 385. DOS Append Interfaces with execvp() in C
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 25-MAY-1989 ArticleIdent: Q44033
-
- The versions of the exec and spawn (with P_OVERLAY) functions that
- search the path for the child program to be run, fail with run-time
- error "R6005 not enough memory on exec" if the child is not in the
- current directory and the DOS APPEND command points to the child's
- directory.
-
- The DOS Versions 3.30 and later APPEND command is used to specify
- directories for locating data files.
-
- APPEND incorrectly finds .EXE and .COM files when DOS interrupt 21
- hex, function 3D hex (open file) is called. This can cause the C
- library function sopen() to mistakenly report that it has succeeded in
- finding a .COM or .EXE file in the current directory when, in fact,
- the file is in another directory that is pointed to by APPEND.
-
- The path-searching versions of the exec and spawn (with P_OVERLAY)
- functions use sopen() to first try to open the .COM or .EXE file in
- the current working directory. If sopen() fails because the file is
- not there, successive directories specified by the PATH are prepended
- to the child's filename, and sopen() is called again until it
- successfully opens the child's file in one of the directories
- specified by the PATH.
-
- If the child is not in the current working directory, but is pointed
- to by APPEND, sopen() mistakenly reports that it has successfully
- opened the child in the current directory and the necessary path is
- not prepended to the child's filename. When the exec/spawn functions
- call DOS interrupt 21 hex, function 4B hex, subfunction 3 (load and
- execute overlay program), the child can't be found in the current
- working directory, and the exec fails. (Unlike DOS function 3D hex to
- open a file, DOS function 4B hex is not affected by APPEND.) At this
- point, the only error C exec/spawn functions are designed to report is
- that there isn't enough memory available for the child process, and
- the R6005 error is issued.
-
- The path searching exec/spawn functions that can be adversely affected
- by APPEND are execlp, execlpe, execvp, execvpe, spawnlp, spawnlpe,
- spawnvp, and spawnvpe. The spawn functions using P_WAIT are not
- affected by APPEND since they do not use sopen().
-
- The Microsoft C run-time library functions do not support the use of
- APPEND. There are no plans to do so in the future.
-
- To work around problems caused by APPEND, disabling APPEND with the
- DOS command "APPEND;" is recommended. Or, within a program, you may
- use the system() library function for this purpose (except for
- versions of DOS that support the /E APPEND option to place APPEND in
- the environment table). If your program needs to accommodate APPEND,
- you could use the _searchenv() function to obtain the path. Then
- traverse the path prepending successive drive and directory names to
- the child's filename for use with sopen() until an sopen() call
- returns a valid file handle indicating the child program has been
- found. Once you have the exact path of the .EXE or .COM file, pass
- the complete path the the appropriate exec?? or spawn?? function.
-
- Note: DON'T use one of the functions that has a "p" in its name --
- these functions search the path for the file, something you've
- already done if you've followed these directions.
-
-
- 386. Using Presentation Graphics/Fonts with C 5.00 and C 5.10
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 25-JUL-1989 ArticleIdent: Q44076
-
- It is possible to use the QuickC Version 2.00 presentation graphics
- and fonts library functions with C 5.00 or C 5.10. However, you must
- be certain that all of the header files and libraries are from the
- QuickC 2.00 package. If you attempt to compile a presentation graphics
- program with C 5.10 and keep getting "unresolved external" messages
- after carefully linking in GRAPHICS.LIB and PGCHART.LIB, reinstall the
- default library and GRAPHICS.LIB from the QuickC 2.00 distribution
- disks. Mixing the C 5.10 and QuickC 2.00 libraries results in this
- behavior.
-
- Please note that the QuickC 2.00 libraries do not support alternate
- math. The QuickC 2.00 and the C 5.10 libraries cannot be mixed.
- Therefore, there is no support for the alternate math package under C
- 5.10 when using presentation graphics or font library functions.
-
- The unresolved externals that you get when mixing libraries are not
- functions; they are the names of support routines and new variables
- that do not exist in the default library or GRAPHICS.LIB from the C
- 5.10 package.
-
-
- 387. Allocation of Variables within Blocks in C
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 23-MAY-1989 ArticleIdent: Q44078
-
- The "Microsoft C for the MS-DOS Operating System: Language Reference"
- manual in Section 3.5.2 states the following:
-
- An item with a local lifetime (a "local item") has storage and a
- defined value only within the block where the item is defined or
- declared. A local item is allocated new storage each time the
- program enters that block, and it loses its storage (and hence its
- value) when the program exits the block.
-
- This statement is true for function blocks. All nonstatic variables
- within a function, whether they are within a block or not, are
- allocated space from the stack upon entry to the function.
-
- According to the ANSI standard, the C language should support jumps
- into blocks. To ensure that variables always are allocated, regardless
- of the entry point into the block, the space for local variables
- within a block must be allocated upon entry of the function, not the
- block. Consider the following code example:
-
- int checkup (int var)
- {
- .
- .
- .
- if (var)
- goto test2;
- else
- {
- char buffer[80];
- strcpy (buffer, "This is a different test");
- test1:
- strcpy (buffer, "This is a test");
- .
- .
- .
- }
- test2:
- printf("testing stuff is coming up next");
- goto test1;
- return (0);
- }
-
- Although this is not the best way to implement this code sample, this
- method should be legal, according to the ANSI standard. If the block
- is entered through the label test1, and the array of characters has
- not been allocated on the stack previously, the strcpy after the test1
- label does not work properly. To ensure that "buffer" is allocated
- space, it is allocated stack space upon entry to the function, and not
- upon entry to the block.
-
- Note: The 80-character buffer is removed from the stack upon exit from
- the block, and not upon exit from the function.
-
-
- 388. File Buffers Are Not Allocated until First Accessed
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 22-MAY-1989 ArticleIdent: Q44178
-
- Problem:
-
- I am using _memavl() to determine the amount of free space on the near
- heap. When I use fgets(), the amount of near heap space decreases by
- 512 bytes.
-
- Response:
-
- File buffers are not allocated when the file is first opened. The
- 512-byte buffer is allocated on the near heap when the file is first
- accessed. The buffer will be used by the file until the file is
- closed. At that time, the buffer space will be freed to the system.
-
- File buffers are allocated in the near heap for small and medium
- memory models and in the far heap for compact and large memory models.
- _memavl() returns the amount of free space on the near heap only.
-
- The following program, compiled in small or medium memory model,
- illustrates this behavior:
-
- #include <malloc.h>
- #include <stdio.h>
-
- FILE *fp;
-
- void main(void)
- {
- char bufs[64];
-
- printf("Start of program \n");
- Bytes_free();
- fp=fopen("file1.txt","r");
-
- printf("file1.txt has been opened \n");
- Bytes_free();
-
- fgets(bufs,5,fp);
- printf(" file has been accessed \n");
- Bytes_free();
-
- fclose(fp);
- printf(" file has been closed \n");
- Bytes_free();
- }
-
- Bytes_free()
- {
- printf("\nHeap bytes free: %u \n", _memavl() );
- }
-
-
- 389. BIND: "Structure Error in .EXE File" Caused by Non-FAPI Call
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G890502-17544
- Last Modified: 22-MAY-1989 ArticleIdent: Q44205
-
- A possible cause of the BIND error message "Structure error in .EXE
- file" is calling a non-FAPI function from within the program to be
- bound.
-
- The solution is to be sure to call only FAPI functions or to follow
- the directions in the BIND documentation for programs that make
- non-FAPI calls.
-
-
- 390. Example for freopen Is Incorrect in C, QuickC Manuals
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC docerr
- Last Modified: 19-SEP-1989 ArticleIdent: Q44207
-
- There is an error in the sample program given on Page 295 of the
- "Microsoft C Optimizing Compiler Run-Time Library Reference" for the
- freopen() function. The first fprintf() function call should be
- changed to a printf().
-
- This error is also present in the QuickC Versions 1.00, 1.01, and 2.00
- run-time library reference manuals. The sample program has been
- changed in the QuickC 2.00 on-line help example and is correct there.
-
-
- 391. How to Use the ERROUT Utility
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | H_FORTRAN H_MASM docerr
- Last Modified: 19-SEP-1989 ArticleIdent: Q44388
-
- Question:
-
- How do I use the ERROUT utility? Examples in the "Microsoft C 5.1
- Optimizing Compiler/CodeView and Utilities" manual do not seem to
- work.
-
- Response:
-
- ERROUT divides its output into two parts: the standard output and the
- standard error output. If ERROUT is used without the /f switch, error
- output is sent to standard output. (Normally, error output is sent to
- the console regardless of where standard output is redirected.) The
- printed documentation on ERROUT is in error on this point.
-
- Therefore, you must use the ERROUT utility with DOS redirection
- operators ">" or ">>", as in the following example:
-
- ERROUT /f err.doc cl test.c > std.doc
-
- The file STD.DOC contains the standard output and the file ERR.DOC
- contains the errors. If there is no error output, the file ERR.DOC
- will be zero bytes long.
-
- To send error output and standard output to the printer, use the
- following commands:
-
- ERROUT cl test.c > PRN
-
- To send error output to the printer and standard output to the
- console, use the following commands:
-
- ERROUT /f PRN cl test.c
-
- To send error output to the console and standard output to the
- printer, use the following commands:
-
- cl test.c > PRN
-
-
- 392. Only Certain C Library Functions Have an Intrinsic Form
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 30-MAY-1989 ArticleIdent: Q44389
-
- The /Oi compiler option generates intrinsic functions instead of
- function calls only for specified run-time library functions. It does
- not generate intrinsic functions for all run-time library functions or
- for application program functions.
-
- To approximate intrinsic functions with application code, use the
- #define directive or the /D compiler option to define a macro.
-
- For more information on the /Oi option and the list of functions
- having intrinsic forms, refer to the "Microsoft C 5.1 Optimizing
- Compiler User's Guide," Pages 93-94, and the C 5.10 README.DOC, "Part
- 2: Notes for the 'Microsoft C Optimizing Compiler User's Guide.'"
-
-
- 393. How to Spawn C 5.10 Compiler Passes without CL.EXE
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890503-17633 c1.exe c2.exe c3.exe
- Last Modified: 22-NOV-1989 ArticleIdent: Q44413
-
- Question:
-
- How can I run the individual compiler passes, C1, C2, and C3, instead
- of CL.EXE? There isn't enough memory available from my editor to spawn
- to CL.EXE, but I suspect there may be enough if I call the individual
- compiler passes.
-
- Response:
-
- There are a number of problems here. First, the CL.EXE program passes
- many flags and command-line options to the various passes. You must
- get these all exactly right. The /d, /Bd, or /Bz CL command-line
- options, or the PEEK.C program below, can help show what is passed
- to the various passes. The PEEK program is easiest to use. To use it,
- we "trick" the CL driver into calling our program instead of the
- various compiler passes. For instance, to find out what is passed on
- each of the three passes, you would use the following commands:
-
- cl /B1 peek.exe /B2 peek.exe /B3 peek.exe [options] [file]
-
- When you do this, the CL driver spawns your program PEEK.EXE rather
- than the various compiler passes. The switches are too complicated to
- guess at, so either use this program or one of the /B or /d options.
- Note that no compilation will be done because you called PEEK.EXE
- rather than the three compiler passes.
-
- The second major problem is that because these command strings can
- easily exceed the DOS 128-character limit on the length of a command
- line, the CL driver uses the environment string area rather than the
- command line to pass options to the passes. To duplicate this, you
- must do one of the following two things:
-
- 1. Write a batch file that sets the environment properly and calls
- the various passes. This file fails if any of the strings are
- longer than the DOS command-line limit of 128 characters. Since
- this is likely to be the case, you'll probably need to use the
- second method.
-
- 2. Write a small C program that spawns (using one of the spawnle,
- spawnlpe, spawnve, or spawnvpe functions with the P_WAIT option)
- the three passes, setting up the environment first. This is a
- simple procedure and provides you with 30K or so in savings. This
- program is not provided here -- you must write it yourself.
-
- PEEK.C Program
- --------------
-
- #include <stdio.h>
-
- void main(int argc, char **argv, char **envp)
- {
- int i;
-
- printf("Command line arguments:\n\n");
- for (i = 0; i < argc; i++) {
- printf("argv[%d]**********\n%s\n\n", i, argv[i]);
- }
- printf("**********End of command line arguments\n\n\n");
-
- printf("Environment strings:\n\n");
- for (i = 0; envp[i]; i++) {
- printf("envp[%d]**********\n%s\n\n", i, envp[i]);
- }
- puts("**********End of environment strings\n");
- }
-
-
- 394. -Zg Won't Handle Untagged Aggregate typedef Parameters
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 1-JUN-1989 ArticleIdent: Q44452
-
- The -Zg switch causes the Microsoft C Version 5.10 Optimizing Compiler
- to generate a list of function prototypes from the input file. This is
- documented on Page 86 of the "Microsoft C for the MS-DOS Operating
- System: User's Guide."
-
- It is noted on Page 87 of the same manual that structure, enumerated,
- and union types that are used as formal parameters must be tagged.
- Using untagged aggregate types as formal parameters results in the
- following message being generated for each instance of untagged
- aggregate type parameters:
-
- warning C4032 : unnamed struct/union as parameter
-
- Typedefs are expanded in the prototype listing. If an aggregate type
- has no tag then the prototype is commented out and the type of the
- parameter is labeled, in the case of a structure, as follows:
-
- struct UNNAMED
-
- There is no way to prevent the compiler from expanding the typedefs
- and from disliking the untagged aggregate types.
-
- The program below, when compiled in the following manner
-
- cl -Zg whack.c
-
- produces the following output:
-
- extern void main(void );
- extern int Woof(struct ure a);
- /* int Heave(struct UNNAMED a); */
- whack.c(29) : warning C4032 : unnamed struct/union as parameter
-
- /* Demonstration of typedef expansion when compiling with /Zg
- */
- typedef struct ure // This one's tagged
- {
- int x;
- int y;
- } URE;
-
- typedef struct // This one's not tagged
- {
- int x;
- int y;
- } IME;
-
- void main()
- {
- URE Ok; // Tagged type variable
- IME NotOk; // Untagged type variable
-
- Woof( Ok );
- Heave( NotOk );
- }
-
- int Woof( URE a )
- {
- return( 0 );
- }
-
- int Heave( IME a )
- {
- return( 0 );
- }
-
-
- 395. Using ILINK in the Development Process in C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr S_QuickC
- Last Modified: 19-SEP-1989 ArticleIdent: Q44462
-
- The incremental linker is available with the Microsoft C Optimizing
- Compiler Version 5.10 and QuickC Version 2.00. The information below
- is excerpted from the "Microsoft CodeView and Utilities Software
- Development Tools for MS OS/2 and MS-DOS Operating Systems Update" for
- Version C 5.10, Section 9, "The ILINK Utility."
-
- Note: The incremental linker supplied with C Version 5.10 CANNOT be
- used to develop DOS applications other than Windows applications. It
- can be used for Windows applications and OS/2 applications. This
- limitation is documented at the beginning of "The ILINK Utility"
- section in the Version 5.10 utilities update.
-
- To develop a software project with ILINK when compiling and linking
- from the command line, do the following:
-
- 1. Use the full linker, LINK.EXE, during early development stages
- until you have a number of different code and data segments.
-
- 2. Prepare for incremental linking by using the /INC (incremental)
- option, for example:
-
- link /INC file1 file2 ... filen;
-
- 3. Use the incremental linker, ILINK.EXE, after any small changes
- are made, for example:
-
- ilink /i file1 file2 ... filen
-
- To view ILINK options, type ILINK at the DOS prompt and press
- ENTER.
-
- 4. Relink with LINK after any major changes are made. Often, a
- major change causes ILINK to fail and then calls a full LINK.
- Relinking with LINK alleviates this unnecessary step.
-
- 5. Repeat Steps 3 and 4 as necessary.
-
- To use the same development process with the QuickC Version 2.00
- environment, you can toggle on and off the incremental compile and
- incremental link switches. You can find these switches under the
- Options menu, Make option, in the Compiler Flag selection and Linker
- Flag selection, respectively.
-
- Linking with the /INC option may take longer than without the option
- because of additional overhead involved in preparing for incremental
- linking.
-
- The /INC linker option is not compatible with the /EXEPACK option.
-
- If you compile and link at the command line with QCL using the /Gi
- (incremental compile) option, then incremental link is automatically
- invoked. If you do not want an incremental compile you can still
- request incremental link with the /Li compiler option.
-
-
- 396. Difference between Arrays and Pointers in C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G890510-18105 S_QuickC
- Last Modified: 19-SEP-1989 ArticleIdent: Q44463
-
- Question:
-
- My program is divided into several modules. In one module, I declare
- an array with the following declaration:
-
- signed char buffer[100];
-
- In another module, I access the variable with one of the following:
-
- extern signed char *buffer; /* FAILS */
- extern signed char buffer[]; /* WORKS */
-
- Using CodeView reveals that the program is using the wrong address
- for the array in the first case. The second case works correctly.
-
- What is the difference between an array and a pointer.
-
- Response:
-
- This is a C programming mistake. The following declarations are NOT
- the same:
-
- char *pc;
- char ac[20];
-
- The first declaration sets aside memory for a pointer; the second sets
- aside memory for 20 characters.
-
- A picture of pc and ac in memory might appear as follows:
-
- pc +--------+
- | ??? |
- +--------+
-
- ac +-----+-----+-----+-----+ +-----+
- | ? | ? | ? | ? | ... | ? |
- +-----+-----+-----+-----+ +-----+
-
- The same is true for the following:
-
- extern char *pc;
- extern char ac[];
-
- Thus, to access the array in ac in another module, the correct
- declaration is as follows:
-
- extern signed char ac[];
-
- In your case, the correct declaration is the following:
-
- extern char buffer[];
-
- The first declaration says that there's a pointer to char called pc
- (which is two or four bytes) somewhere out there; the second says that
- there's an actual array of characters called ac.
-
- The addressing for pc[3] and ac[3] is done differently. There are some
- similarities; specifically, the expression "ac" is a constant pointer
- to char that points to &ac[0]. The similarity ends there, however.
-
- To evaluate pc[3], we first load the value of the pointer pc from
- memory, then we add 3. Finally, we load the character which is stored
- at this location (pc + 3) into a register. The MASM code might appear
- as follows (assuming small-memory model):
-
- MOV BX, pc ; move *CONTENTS* of pc into BX
- ; BX contains 1234
- MOV AL, [BX + 3] ; move byte at pc + 3 (1237) into AL
- ; ==> AL contains 'd'
-
- A picture might appear as follows, provided that pc had been properly
- set to point to an array at location 1234 and that the array contained
- "abcd" as its first four characters:
-
- address: 1000 1234 1235 1236 1237
- pc +--------+--->>>>>------v-----v-----v-----v-----+
- | 1234 | *pc | a | b | c | d | ...
- +--------+ +-----+-----+-----+-----+
- pc[0] pc[1] pc[2] pc[3]
- *pc *(pc+1) etc.
-
- Note: Using pc without properly initializing it (a simple way to
- initialize it is "pc = malloc(4);" or "pc = ac;") causes you to access
- random memory you didn't intend to access (and causes the strange
- behavior).
-
- Since ac is a constant, it can be built into the final MOV command,
- eliminating the need for two MOVs. The MASM code might appear as
-
- MOV AL, [offset ac + 3] ; mov byte at ac + 3 into AL
- ; offset ac is 1100, so move
- ; byte at 1103 into AL
- ; ==> AL contains 'd'
-
- and the picture appears as follows:
-
- address: 1100 1101 1102 1103 1119
- ac +-----+-----+-----+-----+ +-----+
- | a | b | c | d | ... | \0 |
- +-----+-----+-----+-----+ +-----+
- ac[0] ac[1] ac[2] ac[3] ac[19]
- *ac *(ac+1) etc.
-
- Note: If you first initialize pc to point to ac (by saying "pc =
- ac;"), then the end effect of the two statements is exactly the same.
- (This change can be shown in the picture by changing pc so it contains
- the address of ac, which is 1100.) However, the instructions used to
- produce these effects are different.
-
- Note: If you declared ac to be as follows, the compiler would generate
- code to do pointer-type addressing rather than array-type addressing:
-
- extern char *ac; /* WRONG! */
-
- It would use the first few bytes of the array as an address (rather
- than characters) and access the memory stored at that location. This
- is what you're doing and why you're having problems.
-
-
- 397. Use /ND Instead of #pragma data_seg
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 26-MAY-1989 ArticleIdent: Q44477
-
- Support for the data_seg pragma may be eliminated from future versions
- of the Microsoft C Optimizing Compiler. Microsoft strongly recommends
- that you use the /ND option at compile time instead of embedding the
- data_seg pragma in your source code.
-
- When you use /ND to change the name of the default data segment for a
- given module, your program can no longer assume that the address
- contained in the stack segment register (SS) is the same as the
- address in the data segment (DS). You must also compile with /Au or
- use the _loadds keyword. A _loadds function loads its own data segment
- upon entry.
-
- All modules whose data segments have the same name have these segments
- combined into a single segment at link time, including all data that
- would otherwise be allocated in the _DATA segment, i.e., all
- subsequent initialized static and global data.
-
- See the "Microsoft C 5.1 Optimizing Compiler User's Guide," Section
- 6.7, "Naming Modules and Segments," Pages 157-159, for more detail.
-
- The data_seg pragma specifies the name of the data segment that
- subsequent _loadds functions should use and also causes the named
- segment to contain all data that would otherwise be allocated in the
- _DATA segment.
-
- Note that the use of pragma data_seg by itself does not cause
- subsequent functions to load DS. You must also compile with /Au or use
- the _loadds keyword.
-
-
- 398. Ellipse Not Bounded Correctly
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 26-MAY-1989 ArticleIdent: Q44523
-
- The _ellipse function does not behave as defined. The Microsoft QuickC
- and Optimizing C 5.x run-time library reference manuals state that
- "the bounding rectangle [is] defined by the logical points (x1,y1) and
- (x2,y2)." However, the bound specified by y2 may be two pixels distant
- from the lowest point reached by the ellipse.
-
- This behavior can be demonstrated in any video mode, but not all
- possible bounding points will produce this behavior.
-
- This "off by two" behavior is especially troublesome when floodfilling
- a region bounded by the ellipse and a line on y2. The floodfill will
- bleed out of what should be an enclosed region. The following program
- demonstrates this situation:
-
- #include <graph.h>
-
- void main (void)
- {
- int x1=0, y1=0, x2=639, y2=349;
-
- _setvideomode (_ERESCOLOR);
-
- /* Draw the boundary. */
- _setcolor (15);
- _rectangle (_GBORDER, x1, y1, x2, y2);
- _ellipse (_GBORDER, x1, y1, x2, y2);
-
- /* Define _floodfill attributes. */
- _moveto (x1+1, y2-1);
- _setcolor (12);
-
- /* This should not 'bleed' to the right region. */
- _floodfill (x1+1, y2-1, 15);
- }
-
- Microsoft is researching this problem and will post new information as
- it becomes available.
-
-
- 399. UNLINK Does Not Work If the File Is Not Closed
-
- Product Version(s): 4.00 5.00 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 1-JUN-1989 ArticleIdent: Q44608
-
- Question:
-
- I am using the function UNLINK to delete a file. UNLINK seems to
- delete the file, but I do not get the disk space back. Why?
-
- Response:
-
- The C run-time function UNLINK does not work properly if the file you
- are trying to delete is not closed. If the file is not closed, the
- File Allocation Table is not be updated properly and CHKDSK reports
- lost clusters. These lost clusters are the unclosed files which tried
- to delete.
-
- You can recover the lost disk space by running CHKDSK /F. This
- information also applies to the C run-time function REMOVE.
-
-
- 400. printf() and 512-Byte I/O Buffer
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 15-AUG-1989 ArticleIdent: Q44725
-
- Question:
-
- Why does the function printf() take up 512 bytes from the near heap
- (in small and medium memory model) when compiled with QuickC 2.00 but
- does not seem to take up any memory using C 5.10 or QuickC 1.01?
-
- Response:
-
- In QuickC 2.00, the standard I/O buffer gets allocated only when
- needed. This gives the program an extra 512 bytes of near heap space
- in small and medium memory model or an extra 512 bytes of far heap
- space in compact and large model. Therefore, when the printf()
- function is used for the first time, a 512-byte buffer is reserved
- for I/O, and the subsequent calls to printf() use that buffer.
-
- In C 5.10 and QuickC 1.01, a 512-byte buffer is always reserved at
- start-up. It doesn't matter if the program uses standard I/O or not.
- The buffer is also always allocated in the near heap, no matter what
- memory model is used.
-
- The following program prints the amount of space left in the near
- heap. When complied under C 5.10 or QuickC 1.01, the number is the
- same before and after the execution of printf().
-
- The program also uses _fheapwalk to show that C 5.10 and QuickC 1.01
- always allocate the buffer in the near heap in any memory model, and
- QuickC 2.00 allocates it in the near or far heap according to the
- memory model.
-
- When compiled under QuickC 2.00, the number printed after the printf()
- function is executed is 512 bytes fewer than the number printed before
- the execution of printf().
-
- #include <stdio.h>
- #include <math.h>
- #include <dos.h>
- #include <malloc.h>
-
- void heapdump (void);
- void main (void)
- {
- unsigned n1, n2;
-
- n1 = _memavl();
- heapdump();
- printf("first printf has been executed\n");
- n2 = _memavl();
- printf("space left in the near heap before printf %u\n",n1);
- printf("space left in the near heap after printf %u\n",n2);
- heapdump();
- }
-
- void heapdump (void)
- {
- struct _heapinfo hinfo;
- int heapstatus;
-
- hinfo._pentry = NULL;
- while ((heapstatus = _fheapwalk(&hinfo)) == _HEAPOK)
- {
- printf("%6s block at %p of size %d in the far heap\n",
- (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
- hinfo._pentry, hinfo._size);
- }
- switch (heapstatus)
- {
- case _HEAPEMPTY:
- printf("OK - empty far heap\n");
- break;
- case _HEAPEND:
- printf("OK - end of far heap\n");
- break;
- case _HEAPBADPTR:
- printf("ERROR - bad pointer\n");
- break;
- case _HEAPBADBEGIN:
- printf("ERROR - bad start\n");
- break;
- case _HEAPBADNODE:
- printf("ERROR - bad node\n");
- break;
- }
- }
-
-
-
- 401. Using Third-Party Libraries Produced for C Version 4.00
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 31-MAY-1989 ArticleIdent: Q44793
-
- Third-party libraries made for C Version 4.00 can be used with C
- Versions 5.00 and C 5.10. An attempt was made to make third-party
- libraries as compatible as possible. However, a few functions were
- changed to conform to the ANSI C draft and may cause problems.
- Functions such as rename() and memcpy() had their arguments reversed
- from the C 4.00 to C 5.00 libraries; thus, calls to these functions
- from C 4.00 libraries do not work properly. This also applies when
- using third-party libraries with QuickC 1.x and QuickC 2.00.
-
- To use libraries made for C 4.00 under C 5.00 or above, you must link
- with /NOD and specify the C 5.00 combined library to use, as follows
- (the /NOD tells the linker not to use the default libraries for C 4.00):
-
- LINK /NOD file.c ,,, oldlib slibce.lib
-
- In QuickC, this can be done as follows by setting the environment
- variable LINK to /NOD and specifying the QuickC combined library to
- use in a program list:
-
- set LINK=/NOD
-
- If there are still linker errors, you must request library updates
- from the third-party vendor.
-
-
- 402. printf Appears to Print Incorrect Results for Floats
-
- Product Version(s): 5.10 | 5.10
- Operating System: DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 1-JUN-1989 ArticleIdent: Q44816
-
- Question:
-
- The printf() below does not print out the correct values for the float
- if I print the float with a hexadecimal specifier before the float
- specifier. Is this a problem with the code or printf()?
-
- Response:
-
- The problem here is that we are using a 2-byte format specifier for an
- 8-byte value. To correct this problem, replace "%x" and "%lx" with
- "%lx %lx".
-
- Code example
- ------------
-
- #include <stdio.h>
- main()
- {
- float flt = 1.701411e+038;
- double dbl = 1.701411e+038;
-
- printf("\nFLOAT %x %e", flt,flt);
- printf("\nDOUBLE %lx %le",dbl,dbl);
- }
-
- The above code produces incorrect output. However, the source code is
- incorrect. When printing, the above code is using a 2-byte hex format
- specifier %x or a 4-byte hex format specifier %lx with an 8-byte
- double argument (the float is also passed as a double). This produces
- the incorrect results. To solve this problem, use two %lx format
- specifiers to remove 8-bytes off the stack before printing the second
- double. An example is as follows:
-
- printf("\nFloat %lx %lx %e",flt,flt);
- printf("\nDouble %lx %lx %le",dbl,dbl);
-
- This works correctly for Microsoft C under MS-DOS or OS/2; however,
- this code may not be portable under other systems that support types
- of different sizes.
-
- Eight bytes are passed, independent of the fact that one argument is a
- float and the other a double, because the float is being promoted to a
- double. This is because all floats are passed as doubles unless they
- are specified as floats in the prototype. Because printf() has
- variable number of parameters, the arguments are not prototyped and
- therefore all floats are promoted up to doubles.
-
-
- 403. Software/Hardware Required for Writing Windows Applications
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC P_WinSDK
- Last Modified: 26-MAY-1989 ArticleIdent: Q44834
-
- To write programs for Windows, you need the following software
- packages:
-
- 1. Microsoft Windows/286 or Windows/386 Version 2.00 or later.
-
- 2. Microsoft Windows Software Development Kit (SDK) Version 2.00 or
- later.
-
- Note: The version number for the Windows package must match
- the version number for the SDK, e.g. Windows 2.0x with SDK 2.00
- or Windows 2.1x with SDK 2.10.
-
- 3. Microsoft C Compiler Version 4.00 or later, Microsoft QuickC
- Version 2.00, or another compiler suitable for compiling Windows
- programs.
-
- 4. Microsoft Macro Assembler 4.00 or later (for writing DLLs).
-
- To run Windows and the Windows Software Development Kit, you need the
- following hardware:
-
- 1. An IBM personal computer (or compatible) with a fixed disk and
- 640K of memory running MS-DOS Version 3.00 or later. (A machine
- based on an 80286 or 80386 microprocessor with a fast fixed disk is
- best.)
-
- 2. A graphics display and video board, preferably an Enhanced Graphics
- Adapter (EGA) or Video Graphics Array (VGA). A Color Graphics
- Adapter (CGA), Hercules Graphics Card or compatible, or an IBM 8514
- can also be used.
-
- 3. A mouse (optional).
-
- To debug with CodeView (CVW) you need the following:
-
- 1. 1.5 MB of LIM 4.00 expanded memory (2 MB or more is recommended).
-
- 2. Either dual monitors (the second of which is monochrome, the first
- a CGA, EGA, or VGA) or a dumb terminal connected to COM1.
-
- Note: In a dual-monitor setup, when the primary monitor is a CGA,
- the Windows on the CGA is in monochrome due to resolution and the
- monochrome monitor is in text.
-
- Windows/286 can run under DOS or in the DOS compatibility box under
- OS/2 on an 80286 or 80386. Windows/386 requires an 80386 where it can
- run under DOS but not in the DOS compatibility box. Typing "WIN86"
- (without the quotation marks) at the DOS prompt (or DOS box) initiates
- a 80286 (not a 80386) session.
-
-
- 404. kbhit() Does Not Take Character Out of Buffer
-
- Product Version(s): 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 26-MAY-1989 ArticleIdent: Q44895
-
- If you are repeatedly testing the value of "!kbhit()", you must fetch
- the character out of the keyboard buffer yourself after entering a
- keystroke. If you do not, kbhit() returns TRUE and the test repeatedly
- fails.
-
- The following code demonstrates the situation:
-
- #include <conio.h>
-
- void main (void)
- {
- while (!kbhit ()); /* waits for keystroke */
- while ( kbhit ())
- getch (); /* empties buffer */
-
- while (!kbhit ()); /* waits for keystroke */
- while (!kbhit ()); /* does not wait for keystroke */
- }
-
-
- 405. system() Returns an Exit Code Under OS/2
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 31-MAY-1989 ArticleIdent: Q44897
-
- The system() function under OS/2 returns the exit code of the process
- executed, unlike MS-DOS. Under MS-DOS the system() function always
- returns 0 to indicate successful completion.
-
- Under both operating systems, if the system() function fails then a
- value of -1 is returned.
-
-
- 406. How Does _osmode Get Set?
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G890523-18896
- Last Modified: 21-AUG-1989 ArticleIdent: Q44927
-
- The Microsoft C Run-time Library variable _osmode is set to one (1)
- when running under OS/2 and to zero (0) when running under DOS. A C
- program can look at this variable and easily determine whether it's
- running under DOS or OS/2, without calling DosGetMachineMode.
-
- To declare the variable, use the following line:
-
- #include <stdlib.h>
-
- An examination of the start-up code (included with the compiler) shows
- how the value of this variable is determined. The DOS start-up code
- just initializes the variable to zero. The OS/2 code initializes it by
- making a call to the OS/2 API DosGetMachineMode, which sets it to zero
- for DOS or one for OS/2. Thus, you don't need to make the call.
-
- If you compile for DOS (/Lr or /Lc), the DOS start-up code is included
- because the linker links your program with the appropriate DOS library
- (xLIBCyR, where x is the memory model and y is the math option). By
- the same token, when you compile with /Lp, the linker links the proper
- library for OS/2 (xLIBCyP). If you don't specify one of these options,
- your code is linked with xLIBCy.
-
-
- 407. setbuf() Does Not Control Buffering of DOS or Keyboard Buffer
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 25-JUL-1989 ArticleIdent: Q45563
-
- Question:
-
- Why does getchar() still wait for a carriage return even though I used
- setbuf() to unbuffer stdin?
-
- Response:
-
- The function setbuf() affects a stream file buffer like stdin, but has
- no effect on the keyboard or DOS device buffers. The stream I/O
- function getchar() can only read a character from the keyboard buffer
- when the keyboard buffer is flushed by either being filled, by a
- carriage return, or by an interrupt 0x21, function 0xC call.
-
- To read typical characters directly from the keyboard, you can use
- the console I/O function getch(). To read control codes such as
- ALT+Q (echo subsequent output to printer) or ALT+R (pause output), you
- can use the _bios_keybrd() function. Query on the following:
-
- _bios_keybrd()
-
- The following example demonstrates the difference between using
- getchar() and getch():
-
- #include <stdio.h>
- #include <conio.h>
-
- void main (void)
- {
- setbuf (stdin, NULL); /* cause stdin to be unbuffered */
- if (getchar () != EOF )
- printf ("getchar() still waits for return key\n");
- if (getch () != EOF )
- printf ("getch() does not wait for return key\n");
- }
-
-
- 408. Installing C 5.10 to Compile Both DOS and OS/2 Programs
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G890523-18896
- Last Modified: 18-SEP-1989 ArticleIdent: Q45145
-
- If you'd like to install your C compiler so that you can create both
- DOS and OS/2 applications, you have three options. The option you
- select affects the compiler options you must set when you compile for
- the two operating systems.
-
- The three options are as follows:
-
- 1. Rename none of the libraries.
-
- 2. Rename the protected-mode libraries to the default names.
-
- 3. Rename the real-mode libraries to the default names. This
- renaming can also be done while setting up the product.
-
- To install for both OS/2 and DOS, select both operating systems when
- using SETUP to install the product. If you've already installed the
- product for only one operating system, the easiest method is to
- reinstall again from the beginning.
-
- Once the dual installation is done, you have the following two sets of
- libraries (unless you tell SETUP to rename libraries for you when it
- asks):
-
- 1. Those whose names are of the form xLIBCyR.LIB (where x is S, M, C,
- or L for the memory model and y is E, 7, or A for the math option --
- see the Version 5.10 "Microsoft C Optimizing Compiler for the MS-DOS
- Operating System User's Guide" for more information) for "R"eal mode.
-
- 2. Those whose names are of the form xLIBCyP.LIB for "P"rotected mode.
-
- If you install medium model emulator math only, and don't tell SETUP
- to rename libraries, the libraries will be named "MLIBCEP.LIB" and
- "MLIBCER.LIB". There will be no library named with the default name,
- which is "MLIBCE.LIB".
-
- You can leave the libraries named in this way; however, if you do, you
- must always compile with one of the /Lr (link real mode), /Lc (link
- compatibility mode -- a synonym for real mode), or /Lp (link protected
- mode) compiler options.
-
- None of the /Lp, /Lc, or /Lp options affects the compilation process;
- they only affect what libraries the linker is asked to link in.
- Whether the final executable program is a real-mode executable or a
- protected-mode executable is determined solely by the library with
- which you link.
-
- The /Lp option tells the linker to ignore the default library and to
- use xLIBCyP.LIB instead (x and y depend on the memory model and math
- option selected by the /Ax and /FP switches). The /Lr and /Lc options
- tell the linker to use xLIBCyR.LIB rather than the default. xLIBCy is
- the library generated if none of these options is used. This is shown
- in the following table:
-
- Compiler Flags Library Used
- -------------- ------------
-
- -AS SLIBCE
- -AL -FPi87 LLIBC7
- -AM -FPa -Lp MLIBCAP
- -AH -FPc -Lr LLIBCER
-
- If you do most of your programming for one operating system or the
- other, you can rename the appropriate libraries (xLIBCyR or xLIBCyP)
- to xLIBCy and avoid having to use /Lp or /Lr. You still must use /Lp
- or /Lr when compiling for the other mode. For instance, if you rename
- the xLIBCyP libraries to xLIBCy, then when you compile without a /Lc
- or /Lr option, your executable will be a protected-mode executable.
- To generate a DOS executable, you must use /Lr or /Lc. Instead, if you
- rename the xLIBCyR libraries to xLIBCy, the default mode will be DOS
- -- you must use /Lp to produce an OS/2 program.
-
-
- 409. Initialization and Discarding of DLLs Built with C Run Time
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | softlib CRTDLL.ARC S12104.EXE
- Last Modified: 5-OCT-1989 ArticleIdent: Q45180
-
- Question:
-
- Is there a C run-time DLL de-install function provided with
- LLIBCDLL.LIB that, among other things, removes the DosExitList
- functions? Using DosFreeModule doesn't work properly.
-
- Response:
-
- You must do some DLL initialization and cleanup to prevent our default
- DLL initialization and exit code from including the exit list set up
- by LLIBCDLL.LIB, and we have files and suggested procedures for this
- purpose.
-
- The OnLine Software/Data Library file CRTDLL contains the files
- DLLINIT.OBJ and DLLTERM.OBJ, which contain initialization and
- termination functions for LLIBCDLL. Link these functions in with your
- own DLL's initialization and termination functions. (CRTDLL also
- contains CRTDLL_I.OBJ, but this is to replace CRTDLL.OBJ for use with
- the multiple thread CRTLIB.DLL.)
-
- CRTDLL can be found in the Software/Data Library by searching on the
- keyword CRTDLL, the Q number of this article, or S12104. CRTDLL was
- archived using the PKware file-compression utility.
-
- The prototypes for the functions in DLLINIT.OBJ and DLLTERM.OBJ are,
- respectively, the following:
-
- void far pascal C_INIT(void);
- void far pascal C_TERM(void);
-
- To specify the entry point into your own DLL initialization routine,
- you must have a MASM file specifying the name of your DLL
- initialization function with the MASM "END" InitRoutineName statement,
- as in the following:
-
- ; MASM routine
- ...
- END InitRoutineName
-
- The InitRoutineName can specify a MASM or C routine. For C, the DLL
- initialization routine would appear similar to the following:
-
- void far pascal C_INIT(void);
-
- int _export _loadds InitRoutineName() {
- C_INIT();
-
- // ... your own initialization code
-
- return(1); //Indicates to OS/2 that the DLL init succeeded.
- //If return(0), OS/2 won't load .EXE's using the DLL
- }
-
- Your own initialization code must not use C run-time library function
- calls before C_INIT() is called.
-
- Link the MASM entry code .OBJ, the module containing the above
- InitRoutineName() and other DLL functions, and DLLINIT.OBJ together
- with LLIBCDLL and DOSCALLS.LIB (for OS/2 1.00, or OS2.LIB for OS/2
- 1.10).
-
- The DLL's .DEF file must contain the following statements:
-
- LIBRARY dllname INITINSTANCE
- DATA MULTIPLE
-
- To eliminate your DLL, write an initialization function in your DLL
- (or add to the one above) that registers one or more exit routines
- with DosExitList. The exit routines should free all resources acquired
- by the DLL that are no longer needed. The C_TERM() function must be
- called to clean up for LLIBCDLL.
-
- Link in DLLTERM.OBJ with this module. DLLTERM.OBJ will suppress our
- standard use of DosExitList for cleaning up after LLIBCDLL to allow you
- to create your own exit routine list. (For cleaning up after DLL's use
- of the multithread CRTLIB.DLL, you must create your own exit routines
- with C's atexit() or DosExitList.)
-
- All the DLL function entries in the exit list must be removed before
- the .EXE can detach itself from the DLL. To actually discard the DLL,
- your .EXE must call a final termination routine in the DLL. The final
- DLL termination routine must remove the other functions in the exit
- list and then call "DosExitList(EXLST_EXIT, 0L);" to remove itself
- from the exit list. Then, the DosFreeModule of the DLL should succeed.
-
-
- 410. Documented Search Order for Include Files
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 18-SEP-1989 ArticleIdent: Q45187
-
- I am having trouble determining the precise search order for include
- files. The Version 5.10 "Microsoft C for the MS-DOS Operating System:
- User's Guide" states the following on Page 34:
-
- The compiler always searches the current working directory first
- before searching the locations given in the environment variable.
-
- (Except when using < >).
-
- The Version 5.10 "Microsoft C for the MS-DOS Operating System:
- Language Reference" on Page 203 discusses searching in terms of the
- "parent" file's directory, then also mentions the current working
- directory in a subsequent paragraph.
-
- From my experimenting, it seems that all references to the current
- working directory are incorrect. The compiler actually searches based
- on the parent's directory. The MS-DOS current directory is never
- searched unless it is included on the command line or in the INCLUDE
- variable.
-
- The above assumptions are correct. All references to the "current
- working directory" should be referring to the "parent" directory. This
- is a documentation error. If include files are nested, then this error
- becomes important. With nested include files, the current working
- directory can be very different from the parent directory. The parent
- directory is always the one that is searched.
-
-
- 411. Run-Time Library FP Signal Handler Assumes SS=DS
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | softlib CFPLIBS.ARC S12318.EXE
- Last Modified: 25-JUL-1989 ArticleIdent: Q45195
-
- Note that the Microsoft Run-Time Library Exception handler will call
- another routine that calls the task's SIGFPE signal handler, if one
- exists.
-
- However, this intervening routine assumes that the stack segment is
- that of the program that caused the 8087 exception. It is known that
- certain 8087 instructions can take a (relatively) long time to
- execute. It is also known that other interrupt routines, such as the
- timer or the disk interrupt or one belonging to a TSR, may in fact be
- running when the 8087 interrupt occurs.
-
- As the NMI, it will nest, and the run-time library routine's
- assumption about the stack segment may not be valid.
-
- This problem is very rare; however, it is a valid concern. Instead of
- sacrificing speed, the decision was made to take the small chance that
- SS=DS. Checking for SS=DS would slow the floating-point libraries
- considerably.
-
- There is a file in the OnLine Software/Data Library that contains two
- floating-point libraries. These libraries should protect you from the
- unlikely event of SS!=DS. These libraries are approximately 10%
- slower than the retail floating-point libraries.
-
- This file can be found in the Software/Data Library by searching on
- the keyword CFPLIBS, the Q number of this article, or S12318. CFPLIBS
- was archived using the PKware file-compression utility.
-
- These libraries eliminate the possibility of SS!=DS within a
- floating-point signal handler. However, these libraries are about 10%
- slower than the original floating-point libraries. To include these
- files in your combined libraries, first make backup copies of the
- original floating-point libraries, rename these new libraries to
- EM.LIB and 87.LIB, and then run SETUP with the /L option to rebuild
- libraries. This will rebuild the combined libraries with these new
- floating-point components.
-
- The libraries provided with this archived file are fully tested.
- However, they are not regularly released with Microsoft C 5.10.
- Consequently, they will not be maintained, and any problem reported
- with them will not result in a patch or any other immediate fix.
- Please report all problems experienced with these libraries.
-
- The archived file contains the following files:
-
- README.DOC
- PIEM.LIB
- PI87.LIB
-
-
- 412. _ERESNOCOLOR Is a Monochrome/Graphics Mode
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr
- Last Modified: 22-NOV-1989 ArticleIdent: Q45219
-
- On Page 359 of the "Microsoft C for the MS-DOS Operating System:
- Run-Time Library Reference" for C Versions 5.00 and 5.10 and for
- QuickC, the video mode specified by _ERESNOCOLOR is incorrectly
- listed as being a monochrome/text mode. This is really a
- monochrome/graphics mode. The incorrect line reads as follows:
-
- _ERESNOCOLOR M/T 640x350 1 EGA
-
- This line should read as follows:
-
- _ERESNOCOLOR M/G 640x350 2 EGA
-
-
- 413. Tzset Sample Program Redefinition Errors in Large Model
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC docerr
- Last Modified: 25-JUL-1989 ArticleIdent: Q45228
-
- The TZSET sample program given on Page 619 of the "Microsoft C 5.1
- Run-time Library Reference" may yield the following errors:
-
- error C2086: 'daylight' : redefinition
- error C2086: 'timezone' : redefinition
- error C2086: 'tzname' : redefinition
-
- These errors occur only when compiling for the large or compact-memory
- models.
-
- The errors occur because under the large and compact-memory models,
- the variable references default to far addresses, which contradicts
- the external near declarations contained within the include file
- TIME.H.
-
- You may correct this problem by declaring the three variables in
- your source as follows:
-
- int near daylight;
- long near timezone;
- char * near tzname[];
-
- The include file, TIME.H, declares the variables as follows:
-
- extern int near cdecl daylight;
- extern long near cdecl timezone;
- extern char * near cdecl tzname[2];
-
-
- 414. Unsigned Characters and Arithmetic Operators
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 13-SEP-1989 ArticleIdent: Q45237
-
- Question:
-
- In the sample program below, I compare two unsigned character
- variables. The conditional always evaluates to true, even when x and
- y are complements. When I examine the assembly code produced, it
- appears as though the compiler is generating code to compare two
- unsigned integers, not unsigned characters. Is this a bug?
-
- Sample Program
- --------------
-
- #include <stdio.h>
- void main (void)
- {
- unsigned char x, y;
- x = 0;
- y = 255;
-
- if (x != (~y))
- printf ("y is not a complement of x\n");
- else
- printf ("y is a complement of x\n");
- }
-
- Response:
-
- The code generated in this case is correct. The Microsoft C language
- reference guide clearly states that operands of unsigned character
- type are promoted to unsigned integer type when using arithmetic
- operators. Refer to Point 5, Page 116, in the "Microsoft C for the
- MS-DOS Operating System: Language Reference."
-
- For this sample code to work as you intended, cast the "~y" as
- unsigned character, as follows:
-
- if (x != (unsigned char)(~y))
- printf ("y is not a complement of x\n");
- else
- printf ("y is a complement of x\n");
-
-
- 415. Can't Take Address of Frame Variable in DLL (SS!=DS)
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | SR# G890605-19757
- Last Modified: 25-JUL-1989 ArticleIdent: Q45584
-
- Question:
-
- In my .DLL, whenever I take the address of an automatic variable, the
- compiler issues the following warning:
-
- "address of frame variable taken, DS != SS"
-
- Whenever the DLL is called, it causes a GP fault. What is causing this
- problem and how do I correct it?
-
- When I added "NONSHARED" to the DATA directive in the .DEF file, the
- GP trapping stopped. Why did the trapping stop?
-
- Response:
-
- If you're using small or medium memory model, your pointers are
- 2-byte pointers, which contain only the offset of the variable into
- the data segment.
-
- In compact, large, and huge models, pointers are 4 bytes, containing
- both a segment and an offset.
-
- When a .DLL is executing, it uses your stack (normally in your
- data segment) and the .DLL's default data segment. Thus, you must
- compile with /Au or /Aw, telling the compiler that it should not
- assume (as it normally does) that DS (the default data segment
- selector) and SS (the current stack segment selector) are the same.
-
- All near (2-byte) pointers are assumed to be relative to current DS.
- When you take the address of a frame (automatic) variable, this
- address is relative to SS. When SS == DS, as is the usual case, this
- is not a problem. However, it does cause problems in .DLLs, where SS
- cannot be equal to DS.
-
- There is no way to take a near address of a stack variable when
- DS!=SS. You do have several alternatives, however:
-
- 1. Change to compact, large, or huge model. Since the pointers are far
- pointers, you'll be able to represent the address properly. In
- addition, all the run-time library functions accept such far
- pointers.
-
- 2. Use a far pointer to hold the address. You can do this without
- changing memory models. This method has the advantage that the only
- pointer accesses that are slowed are the individual far pointers
- used to access the stack. The disadvantage is that most small and
- medium model library routines do not support far pointers, so
- you must either avoid those routines or copy the far data into
- the default data segment before calling the routine. Please note
- that this is only necessary with routines that accept pointers;
- routines that accept variables by value aren't affected because the
- value of the expression doesn't change when the pointer size does.
- It is strongly recommended that you use prototypes and new-style
- declarations for ALL your functions to prevent errors.
-
- 3. Rework the code to avoid the need for taking the address of frame
- variables.
-
- The reason the trapping seems to stop when you changed the .DEF file
- probably has more to do with the sizes of the segments involved -- in
- one case, the address generated was larger than the maximum for that
- segment; in the other, it happened not to be. In each case, the
- address was wrong because the compiler used DS rather than SS.
- Therefore, changing the data directive in the .DEF file covered up but
- did not correct the error.
-
- .DLL's which use the C Runtime Library **ALWAYS** use NONSHARED
- default data and instance initialization. Instance initialization is
- specified in the LIBRARY statement of the .DEF file.
-
-
- 416. Why There's a 128K Limit on Some Huge Arrays and halloc()s
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 21-AUG-1989 ArticleIdent: Q45705
-
- Question:
-
- Why am I limited to allocating 128K with halloc() or a huge array
- unless the size of the elements I am using is a power of 2?
-
- Response:
-
- With huge pointers and arrays, the Microsoft C Compiler produces
- 32-bit pointer arithmetic only when accessing whole elements. Only the
- 16-bit offset of a pointer is used when accessing the individual
- members of elements. This technique is used in the interest of speed
- and smaller code size. However, it assumes that elements do not extend
- from the end of one segment into the beginning of the next. When
- crossing a 64K segment boundary, elements must end evenly with the end
- of that segment. The following diagram illustrates the conditions
- necessary for huge pointers and arrays:
-
- Seg1 Seg2
- Segment 1 FFFF 0000 Segment 2
- ----------------------------+----------------------------
- ......| Elem | Elem | Elem + Elem | Elem | Elem |.....
- ......| X | X+1 | X+2 + X+3 | X+4 | X+5 |.....
- ----------------------------+----------------------------
- ^ Elements must not cross
- a segment boundary.
-
- If an element's size is not a power of 2, an array of that element
- will not fit evenly into a 64K segment. This is the root of the 128K
- limitation. To avoid breaking an element across a segment boundary in
- this case, extra space is left at the beginning of the first segment,
- pushing the entire array upwards in memory so that the element before
- the one that would have spanned the segment boundary ends exactly at
- the segment ending. The element that would have spanned the segment
- boundary is pushed to the beginning of the second segment.
-
- If the allocated elements do not fit evenly into a segment, there can
- be only one segment boundary onto which they fall evenly. The function
- halloc() uses the element size it is passed to calculate and return a
- pointer with an offset that results in the allocated elements falling
- evenly on this boundary. The following diagram demonstrates the way
- this is done and what can happen at the end of the second segment:
-
- Segment 1 Segment 2
- 0000 FFFF 0000 FFFF
- +----------------------+-------------------+
- +Pad |Elem |Elem |Elem +Elem |Elem |Elem | +
- +----------------------+-------------------+
- ^ ^ ^
- ^ ^ Next element will not fall
- ^ ^ on segment bounds.
- ^ ^
- ^ Offset returned to allow elements to fall on segment bounds.
- ^
- Padding area used to force element boundary to fall on segment
- boundary
-
- These restrictions should also be considered when allocating memory
- for very large elements. For example, a request for three 33K
- structures will fail. Two of the structures could be allocated, but
- since each would go into a separate segment, neither of the segments
- would contain enough space for the third element.
-
-
- 417. L2002 When Linking Small Model Main with Other Memory Models
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 14-AUG-1989 ArticleIdent: Q45710
-
- An attempt to link a module that has been compiled in the small memory
- model with a module compiled in the medium or large memory model
- produces the following error:
-
- L2002: fixup overflow
-
- The cause, in this particular case, of the "fixup overflow" error
- message is not documented in the C Version 5.10 "CodeView and
- Utilities, Microsoft Editor, Mixed-Language Programming Guide" on Page
- 366.
-
- Normally, you should NOT link programs that contain different memory
- models. All modules should be compiled using the same memory model.
- (It is possible to use the "near" and "far" keywords to produce
- mixed-model programs, but this is tricky and usually doesn't give much
- performance gain.)
-
- If the following module, MOD1.C
-
- #include<stdio.h>
-
- void main(void);
-
- void main()
- {
- printf(" module 1 \n");
- mod2();
- }
-
- is linked with the module, MOD2.C
-
- #include<stdio.h>
-
- void mod2(void);
-
- void mod2()
- {
- printf(" module 2 \n");
- }
-
- in various memory models, the following results occur:
-
- Memory Model Result
- ------------ ------
- MOD1 | MOD2
- ------|-----
- |
- /AS | /AM L2002 : fixup overflow
- |
- /AS | /AL L2002 : fixup overflow
- |
- /AM | /AS Links, hangs on run
- |
- /AM | /AL Executes normally
- |
- /AL | /AS Links, hangs on run
- |
- /AL | /AM Links, prints trash for MOD2 on run
-
-
- 418. Typographical Error in ALMUL.ASM of C Library Source
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | H_MASM docerr
- Last Modified: 13-SEP-1989 ArticleIdent: Q45763
-
- In the "Microsoft C Run-Time Library Source Routines" for C Version
- 5.00 or C 5.10, Line 28 of the file ALMUL.ASM in the \HELPER directory
- contains a typographical error. The incorrect statement reads as
- follows:
-
- assume ds,code
-
- The statement should read as follows:
-
- assume ds,data
-
- Since no data is defined or referenced in the original ALMUL.ASM, the
- typographical error does not cause problems in the C library. However,
- if you purchased the C library source code from the end user sales
- department, defined and referenced data in ALMUL.ASM, and attempted to
- assemble the modified ALMUL.ASM with MASM, you receive the following
- error:
-
- error A2068: Cannot address with segment register
-
- Correcting the error in ALMUL.ASM, as noted above, corrects the
- problem.
-
-
- 419. Using DosExecPgm() After Changing PATH Environment Variable
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 25-JUL-1989 ArticleIdent: Q45904
-
- Question:
-
- I use the C 5.10 run-time putenv() function to change my PATH
- environment variable. I then use the OS/2 DosExecPgm() API call to
- start an executable that lies on that path. DosExecPgm() fails to
- execute the process, giving me a return code indicating that the file
- could not be found. I try the run-time spawnlp() function and it works
- correctly. What is the problem? How can I get DosExecPgm() to work?
-
- Response:
-
- The C run-time startup code copies the environment table into DGROUP.
- The putenv() run-time function modifies this copy of the environment.
- Other C run-time functions, including spawnlp(), will use this copy of
- the environment. So, when you alter your path variable
-
- putenv( "PATH=d:\\whack" );
-
- and look at it
-
- Path = getenv( "PATH" );
-
- you see that Path does indeed point to the new path. However, then
- using an OS/2 API call to check the path variable
-
- DosScanEnv( "PATH", &Path );
-
- reveals that the path is unchanged. This is because the API functions
- deal with the original environment table, not the copy in DGROUP.
- DosExecPgm() is no exception, meaning that the original PATH
- environment variable will be used rather than the altered copy.
-
- In order to perform a DosExecPgm() of a process that is not on the
- original search path but is known to be on another search path, you
- may wish to use the DosSearchPath() function in conjunction with
- DosExecPgm(), in the following manner:
-
- #define INCL_DOS
-
- #include <os2.h>
- #include <stdio.h>
-
- void main( void );
-
- void main()
- {
- RESULTCODES ResCodes;
- char Fail[256];
- USHORT ret;
- char Pgm[256];
-
- DosSearchPath( SEARCH_CUR_DIRECTORY, // Start with cur dir
- "d:\\;c:\\;b:\\whack", // Search this path
- "off.exe", // For off.exe
- Pgm, // Put result path here
- 256 ); // It's 256 bytes long
-
- printf( "Pgm path: %s\n", Pgm );
-
- ret = DosExecPgm( Fail,
- 256,
- 0,
- NULL,
- 0,
- &ResCodes,
- Pgm );
-
- printf( "DosExecPgm says: %u\n", ret );
- printf( "Fail: %s\n", Fail );
- }
-
- This program uses DosSearchPath() to generate a full path to
- "off.exe". Each directory in the path passed to DosSearchPath() will
- be searched. In this case the current directory will be searched
- first, because of the SEARCH_CUR_DIRECTORY flag.
-
-
- 420. Unresolved Externals Using OS/2 Functions and INCL_NOCOMMON
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 25-JUL-1989 ArticleIdent: Q45946
-
- If you are using OS/2 functions and getting "unresolved external"
- messages at link time even though OS2.H is included, check for a
- definition of the manifest constant INCL_NOCOMMON. The definition of
- this constant excludes any function group that is not explicitly
- included by the definition of another manifest constant.
-
- For example, to include the OS/2 system functions (DOS) and exclude
- all others, the following two statements must exist in the source
- code:
-
- #define INCL_NOCOMMON
- #define INCL_DOS
-
- Look closely at the "unresolved external" message. If the compiler has
- prepended an underscore to the function name, then the prototype is
- not being included. All OS/2 functions are defined with a PASCAL
- calling sequence. Therefore, there should never be an underscore
- prepended to the function name.
-
- As a quick test, remove the INCL_NOCOMMON statement from the code and
- recompile. If the program compiles and links without the INCL_NOCOMMON
- statement, then you have only to determine which manifest constant
- correctly includes the function group that includes the function in
- question.
-
- As an alternative, compiling at warning level three generates a "no
- prototype given" warning for the function if the function prototype is
- being excluded by the INCL_NOCOMMON statement. If this is the case,
- determine which manifest constant will include the function prototype,
- and define it along with the INCL_NOCOMMON statement.
-
- A comprehensive listing of these manifest constants can be found in
- the "Microsoft OS/2 Programmer's Reference," Volume #1, Pages 41-44.
-
-
- 421. fopen Will Set errno Values
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 18-SEP-1989 ArticleIdent: Q46024
-
- Question:
-
- The "Microsoft C 5.10 Optimizing Compiler Run-Time Library Reference"
- manual indicates that open and sopen will set errno values. The fopen
- documentation on Pages 274-275 does not explicitly state that fopen
- will set errno. Will fopen set errno?
-
- Response:
-
- Yes, fopen will set errno values. Internally, fopen calls the same
- low-level routines that open and sopen call. These routines cause
- errno to be set.
-
- For more information, please refer to the documentation for open.
-
-
- 422. Modifying P_tmpdir Does Not Change the Operation of tmpnam()
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 25-JUL-1989 ArticleIdent: Q46131
-
- The functions tmpnam() and tempnam() both state that under certain
- conditions they create a name that consists of the path prefix defined
- by the P_tmpdir entry in STDIO.H. This is ambiguous. A more correct
- way of stating this is that they create a name that consists of a path
- prefix to the root of the current drive; this is also what P_tmpdir is
- defined as. Under C Version 5.10 and QuickC Version 2.00, P_tmpdir is
- defined as the root directory on the default drive, which is where the
- created name would reside. However, any modification of P_tmpdir in
- STDIO.H does not change the filename created.
-
- It states on Page 611 of the "Microsoft C for the MS-DOS Operating
- System Run-Time Library Reference" that changing the definition of
- P_tmpdir or L_tmpnam does not change the operation of tmpnam(). Nor
- does it change the operation of tempnam(). These two defines are only
- provided for XENIX/UNIX portability. The two functions tmpnam() and
- tempnam() do not make any use of these two defines.
-
-
- 423. Typedef of Function Pointer with _loadds Fails
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G890616-20706
- Last Modified: 11-SEP-1989 ArticleIdent: Q46270
-
- Question:
-
- I have the following typedef declaration:
-
- typedef void far _loadds pascal MYFUNC(void);
- typedef MYFUNC far *PMYFUNC;
-
- The second typedef gives a compiler warning (at -W3 level):
-
- Warning C4105: 'PMYFUNC' : code modifiers only on function
- or pointer to function
-
- How can I avoid the warning?
-
- Response:
-
- This compiler does not handle this situation properly.
-
- One solution is to use a macro as shown below:
-
- #define FN_FLP far _loadds pascal
-
- void FN_FLP myfunc1();
-
- void (FN_FLP *pmyfunc1)();
-
- This isn't as attractive as a typedef, but it does help.
-
- Another way to work around the problem is to put the definition of the
- function in a different source file than the calls, leaving the
- _loadds keyword in the function definition but taking it out of the
- declarations. Since _loadds does not affect the calling sequence, this
- process should not cause additional problems.
-
- Note: Be sure to check your generated code.
-
- Microsoft is researching this problem and will post new information as
- it becomes available.
-
-
- 424. Compiler Options for Intel 80x86 Processors
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 14-AUG-1989 ArticleIdent: Q46381
-
- The following is extracted from the "Microsoft C Optimizing Compiler
- User's Guide," Page 81, Section 3.3.10, "Using the 80186, 80188, or
- 80286 Processor (/G0, /G1, /G2)":
-
- Options
- -------
-
- /G0 Enables instruction set for 8086/8088 processor (default)
- /G1 Enables instruction set for 80186/80188 processor
- /G2 Enables instruction set for 80286 processor
-
- If you have an 80186, 80188, or 80286 processor, you can use the /G1
- or /G2 option to enable the instruction set for your processor. Use
- /G1 for the 80186 and 80188 processors; use /G2 for the 80286.
- Although it is usually advantageous to enable the appropriate
- instruction set, you are not required to do so. If you have an 80286
- processor, for example, but you want your code to be able to run on an
- 8086, you should not use the 80186/80188 or 80286 instruction sets.
-
- The /G0 option enables the instruction set for the 8086/8088
- processor. You need not specify this option explicitly, since the
- 8086/8088 instruction set is used by default. Programs compiled in
- this way also run on machines with the 80186, 80188, or 80286
- processor.
-
- Since DOS and existing versions of OS/2 are not 80386 operating
- systems, Version 5.10 (as well as previous versions) of the C compiler
- do not offer a /G3 switch for 80386 code generation.
-
-
- 425. Spawned Processes Do Not Always Handle Signals Properly
-
- Product Version(s): 4.x 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 9-AUG-1989 ArticleIdent: Q46383
-
- In the following example, the CTRL+C signal is not handled as expected
- within the spawned process:
-
- #include <stdio.h>
- #include <process.h>
-
- void main( void )
- {
- int err;
-
- err = system( "TYPE TEST.TXT | MORE" );
-
- printf( "Return from system: %d\n", err );
- }
-
- If CTRL+C is pressed while the file is being typed, temporary files
- used by MORE to emulate pipes are left in the root of the current
- drive. The return value from the system does not indicate any
- problems.
-
- This is a limitation of MS-DOS and the way child processes handle
- certain signals, not a problem with the C compiler. Interrupting an
- assembly language program that simply calls DOS interrupt 0x4B to
- spawn "COMMAND /c TYPE TEST.TXT | MORE" gives the same results.
-
-
- 426. Where to Find Information on Writing TSRs
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890601-19569
- Last Modified: 25-JUL-1989 ArticleIdent: Q46734
-
- Question:
-
- What is the definitive Microsoft reference that describes "the rules"
- for creating a TSR?
-
- Response:
-
- Since the DOS environment is so loosely structured, there are no hard
- and fast rules that guarantee that a TSR will work correctly with any
- application. The best source for this information is the "MS-DOS
- Encyclopedia" (published by Microsoft Press). This excellent reference
- contains a 37-page chapter on TSRs, and other related information on
- exception handlers and hardware-interrupt service routines. If you
- take care to write your TSR in the manner described in this reference,
- you will minimize interactions and other problems.
-
-
- 427. Loop Optimization May Cause Improper Type Cast of int
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 25-JUL-1989 ArticleIdent: Q46735
-
- In certain situations, compiling with loop optimization may cause a
- type cast of an int to a long or unsigned long to produce an incorrect
- value if the cast precedes a loop. When an int is type cast to a long,
- the correct conversion sign extends. Thus, a negative integer remains
- negative. On the other hand, when casting an int to an unsigned long,
- the correct conversion is to sign extend to long, THEN convert the
- long to unsigned long. This means a negative integer will be cast to a
- really huge positive number when cast to an unsigned long. This
- expected behavior is documented on page 141 of the "Microsoft C 5.1
- Optimizing Compiler Language Reference." Loop optimization may cause
- errors in both of these type casts. Disabling loop optimization or
- rearranging the code corrects the problem.
-
- The following program, when compiled with the /Oal or /Ox option,
- displays this erroneous type casting. In the third assignment
- statement, -31536 is cast to a long and assigned to lNum. The result
- should still be -31536, but lNum ends up being 34000. The fourth
- assignment statement casts this same number to an unsigned long and
- assigns it to ulNum. The expected result, as described above, is the
- huge positive number 4294935760, but the value assigned to ulNum is
- again 34000.
-
- Program Sample
- --------------
-
- #include <stdio.h>
-
- void main(void)
- {
- int iNum;
- unsigned uNum;
- long lNum;
- unsigned long ulNum;
-
- lNum = 34000;
- printf ("lNum = %ld\n", lNum);
- iNum = (int) lNum;
- printf ("iNum = (int) lNum = %d \n", iNum);
- lNum = (long) iNum;
- printf ("lNum = (long) iNum = %ld \n", lNum);
- ulNum = (unsigned long) iNum;
- printf ("ulNum = (unsigned long) iNum = %lu \n", ulNum);
-
- for (lNum = 0L; lNum < 17 ; lNum += 1)
- ;
- printf ("%s", "done");
- }
-
- The following is the program output:
-
- lNum = 34000 <== Correct
- iNum = (int) lNum = -31536 <== Correct
- lNum = (long) iNum = 34000 <== WRONG! (should be -31536)
- ulNum = (unsigned long) iNum = 34000 <== WRONG! (should be 4294935760)
- done
-
-
- 428. Mixed-Model Programming and long int Helper Library Routines
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890606-19866
- Last Modified: 25-JUL-1989 ArticleIdent: Q46738
-
- Question:
-
- I notice that the Microsoft C Optimizing Compiler Version 5.10
- implicitly generates calls to "helper" routines in to handle long
- integer arithmetic for operations such as division, left-shift,
- right-shift, etc.
-
- I see a problem in situations such as the following:
-
- My program is compiled in small model, so all code and data pointers
- are near. However, I explicitly declare a far pointer to a long
- integer, and then I perform a left-shift on this long integer.
-
- Won't the library routines be expecting near pointers to data and,
- therefore, fail?
-
- Response:
-
- The compiler is aware of this mixed-model programming issue and
- generates appropriate calls to ensure that the helper routines don't
- make the wrong assumption as to near versus far pointers.
-
- To demonstrate this, consider the following test program:
-
- long lNear; /* this resides in DGROUP */
- long far lFar; /* this goes in a FAR_BSS segment */
-
- void main(void);
-
- void main(void)
- {
- long lStack; /* this goes in SS, part of DGROUP */
-
- lNear = 30000;
- lFar = 15000;
- lNear <<=4; /* force call to helper routines */
- lFar <<= 4;
- lStack = lNear + lFar;
- lStack <<= 4;
-
- }
-
- The above comments point to the salient points of this test. There are
- three long variables, one in DGROUP, one in a far segment, and one on
- the stack. The compiler is asked to left-shift the near and far longs
- by 4 bits to force a call to the helper routines. Some of the compiled
- code generated by the above source is shown in the following:
-
- ...
-
- EXTRN __acrtused:ABS
- EXTRN __chkstk:NEAR
- EXTRN __aNNalshl:NEAR
- EXTRN __aNFalshl:NEAR
- _BSS SEGMENT
- COMM NEAR _lNear: BYTE: 4
- COMM FAR _lFar: BYTE: 4
-
- ...
-
- ;|*** lNear <<=4;
- ; Line 12
- *** 000029 b0 04 mov al,4
- *** 00002b 50 push ax
- *** 00002c b8 00 00 mov ax,OFFSET DGROUP:_lNear
- *** 00002f 50 push ax
- *** 000030 e8 00 00 call __aNNalshl
- ;|*** lFar <<= 4;
- ; Line 13
- *** 000033 b0 04 mov al,4
- *** 000035 50 push ax
- *** 000036 b8 00 00 mov ax,OFFSET _lFar
- *** 000039 ba 00 00 mov dx,SEG _lFar
- *** 00003c 52 push dx
- *** 00003d 50 push ax
- *** 00003e e8 00 00 call __aNFalshl
-
- Note that even though this program compiled in small model, it created
- a far segment (FAR_BSS), and it put lFar in it with the declaration
- "COMM FAR _lFar: Byte: 4". Note also the difference between how it
- left-shifted the lNear variable (__aNNalshl) versus the way it shifted
- the lFar variable (__aNFalshl). The routine __aNNalshl is for small
- model (near code pointer plus near data pointer), whereas __aNFalshl
- is compact model (near code pointer plus far data pointer); this makes
- complete sense for the mixed-model program.
-
- To summarize, the compiler knows about these near/far dependencies
- between source code and library routines, and puts in requests for the
- appropriate routines even if you're in a memory model that wouldn't
- normally use them (in this case, you wouldn't normally generate a call
- to __aNFalshl in small model).
-
-
- 429. Possible Cause for Slow Stream I/O
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 25-JUL-1989 ArticleIdent: Q46741
-
- Question:
-
- I have an application program that does intensive file manipulation
- with the stream level I/O routines. Normally it works very fast, but
- lately the file operations have become increasingly slower and now it
- can take several minutes to process a single file. What causes this
- time delay in the stream I/O routines and how can I prevent it?
-
- Response:
-
- The stream level I/O routines inherit their speed and flexibility from
- the buffering system they use. Upon opening a file with the fopen
- function, a file record is created that contains pointers into a
- stream buffer. This buffer is then allocated (malloc-ed) when the
- first I/O operation is performed. If there is not enough room in the
- heap for this buffer allocation, the file operation continues with a
- buffer size of one character.
-
- A stream I/O routine that takes an excessive amount of time is most
- likely the result of a failure to allocate the 512-byte buffer on the
- heap (near or far, depending on the memory model). Without this
- buffer, the I/O routines are extremely slow, requiring disk access for
- all I/O operations.
-
- To get around this problem, you can do one of two things. Reduce the
- amount of allocation on the heap. Or, change memory models to compact
- or large (if you are in small or medium). If you change memory models,
- you may need to use the /Gt switch to push static data out of DGROUP.
-
-
- 430. Some Causes of Differences in Floating-Point Results
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890124-10419
- Last Modified: 25-JUL-1989 ArticleIdent: Q46749
-
- This article discusses some reasons why programs might produce
- different floating-point results when compiled with different compiler
- options.
-
- The program below produces different results when complied using
-
- cl -AM -FPi prog.c
-
- than when using the following:
-
- cl -AM -FPa prog.c
-
- Part of the reason for these differences is that /FPa and /FPi
- generate math routines that work differently. /FPi math emulates the
- 80x87, to the point of actually converting 8-byte doubles to 10-byte
- internal format and doing the math in internal format. /FPa uses an
- 8-byte format for calculations; therefore, it is less accurate. This
- often accounts for differences in results.
-
- Also of special interest is the fact that the second number printed in
- the /FPi case is smaller than DBL_MIN, as defined in FLOAT.H. This
- situation is also correct because DBL_MIN is the smallest possible
- NORMALIZED value. (Normalized means that the high-order bit of the
- mantissa is a one.)
-
- "Denormals" (numbers where there are zeros in some of the high-order
- bits of the mantissa), however, can represent numbers "x" in the
- ranges + DBL_MIN > x > 0 and 0 > x > -DBL_MIN. Although this is an
- unusual situation, it is not an error. Although it is less precise
- than a normalized number, a denormal is still more precise than 0
- (zero) (which is the next best representation). By allowing use of
- denormal numbers, we make our floating-point result slightly more
- accurate. The alternate math library (/FPa) represents denormal
- numbers as 0 (zero).
-
- There is a good explanation of floating point exceptions (including
- the denormal exception, which is always masked) in the FPEXCEPT.DOC
- file that comes with the C compiler. For more detailed background, see
- the Intel "80387 Programmer's Reference Manual."
-
- Another possible cause of differences in floating-point results is the
- inclusion or omission of the /Op option. When /Op is omitted, the
- compiler may skip storing intermediate results as 64-bit objects in
- memory, leaving them instead in the 80-bit registers of the 80x87 (or
- emulator package). This increases the speed and accuracy of the
- calculation. However, this can decrease the consistency of the
- calculations because other intermediate results may have been stored
- in 64-bit objects in memory anyway. Including /Op forces all
- intermediate results to be stored in memory, giving more consistent
- results. This option is often handy in programs involving complicated
- floating-point calculations.
-
- The program and its output follow:
-
- #include <stdio.h> // START OF PROG.C
- #include <float.h>
-
- main()
- {
- double a,d,c,prod1,prod2;
-
- _fpreset();
- a=9.5788979e-283;
- b=8.050847e-1;
- c=9.5588526e-28;
-
- prod1=a*b;
- printf("\n product1 = %1.15le \n",prod1);
- prod2=c*prod1;
- printf("\n product2 = %1.15le \n",prod2);
-
- } // END OF PROG.C
-
- // RESULTS OBTAINED USING CL -AM -FPi PROG.C
-
- product1 = 7.711824142152130e-283
-
- product2 = 7.371619025195353e-310 // This value is less than DBL_MIN
-
- // RESULTS OBTAINED USING CL -AM -FPa PROG.C
-
- product1 = 7.711824142152130e-283
-
- product2 = 0.000000000000000e+000
-
-
- 431. Using C Run-Time Library Functions in .DLLs
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | SR# G890705-21975
- Last Modified: 25-JUL-1989 ArticleIdent: Q46773
-
- Question:
-
- In a .DLL, what C standard library functions are usable?
-
- Also, one reference mentions special re-entrant libraries for use in
- .DLLs. Is that correct, and if so, how do you get at them? Is there
- some place where this information is documented?
-
- Response:
-
- There's been a lot of confusion about the proper way to write .DLLs
- because what was legal and what's not legal has changed at least once
- during the lifetime of the OS/2 SDK.
-
- In the past, there were restrictions on which library functions you
- could use and how you could use them. These restrictions have been
- removed because we've created several specially-modified libraries
- that can be used freely in .DLLs. All library functions can be called.
- Any serialization needed is handled by the library.
-
- The proper way to create .DLLs is outlined in the file MTDYNA.DOC,
- which is included with the C 5.10 compiler. There are also examples
- included with the compiler that you can compile and modify. If you are
- developing for OS/2 1.10, instead of OS/2 1.00, with the OS/2 1.10
- Software Development Kit or Tool Kit, use the OS/2 1.10 library
- OS2.LIB in place of the OS/2 1.00 library DOSCALLS.LIB. Also make sure
- to include the OS/2 1.10 include files before, or instead of, the C
- 5.10 regular and multi-thread include files with the same names, such
- as OS2.H and BSE.H. These C 5.10 OS/2 API-related include files are
- for OS/2 1.00.
-
- Note: There are two very important details about writing your .DEF
- file that MTDYNA.DOC doesn't mention:
-
- 1. You MUST use a DATA MULTIPLE NONSHARED statement for any .DLL that
- uses the C run-time library because each process that uses the .DLL
- needs its .DLL to have a separate data area. Otherwise, multiple
- instances of the .DLL will corrupt each other's C run-time library
- static data.
-
- 2. You also MUST use LIBRARY INITINSTANCE in any .DLL that calls the
- C run-time library because each instance of the .DLL must have its
- run-time library data area initialized separately.
-
- Aside from these two details and the new OS/2 1.10 library and header
- files, MTDYNA.DOC is an excellent guide for writing .DLLs.
-
-
- 432. _setvideomode Resets the Palette
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC _remapallpalette _remappalette
- Last Modified: 25-JUL-1989 ArticleIdent: Q46792
-
- The Microsoft C function _setvideomode resets the palette to the
- default palette colors each time it is called. Therefore, remapping
- the color palette in C lasts only as long as the video mode remains
- active.
-
-
- 433. Q & A on MS Recommendation of Glockenspiel C++ and CommonView
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890705-21998 plus plus
- Last Modified: 26-JUL-1989 ArticleIdent: Q46836
-
- The following questions and answers concern the use of Glockenspiel
- C++:
-
- Q. Does Microsoft recommend the Glockenspiel C++ and CommonView?
-
- A. Microsoft has included their advertising literature in our C
- Version 5.10 package and has mentioned them in the new languages
- newsletter, which was sent to all registered users. Glockenspiel's C++
- is a preprocessor, which generates C 5.10 code from your C++ source
- program. (You then use Microsoft C 5.10 to compile this code.) This
- C++ product is currently the only way to use C++ while retaining the
- sophisticated code generation and tool set of Microsoft C. It is ideal
- for Microsoft customers who want to use C++ today.
-
- CommonView is a C++ object library, which makes programming for
- graphical user interfaces, including Windows, easier. This is also the
- only product of its type on the market today that is compatible with
- Microsoft C.
-
- The products included here are manufactured by vendors independent of
- Microsoft; we make no warranty, implied or otherwise, regarding these
- products' performance or reliability.
-
- Q. What does Microsoft think about C++? Does Microsoft recommend
- programming in C++?
-
- A. Microsoft has publicly stated that object-oriented programming,
- including C++, is the way of the future and that it will result in
- great productivity gains for programmers. We have already introduced
- object-oriented extensions in our new QuickPascal product and have
- announced that we are working on an implementation of C++ (release
- date is unknown). We think that this is very important technology and
- that it will make possible the sophisticated systems of tomorrow.
-
- Since C++ is going to be so important in the near future, it is
- certainly wise to start getting experience in it now.
-
- Q. Does Microsoft use C++ in-house?
-
- A. Microsoft uses a variety of languages in-house including Microsoft C
- and MASM. Beyond that, it is not possible to comment on which products
- use what languages.
-
-
- 434. Type of Expression "&arrayname" Changes under ANSI C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G890706-22068
- Last Modified: 26-JUL-1989 ArticleIdent: Q46947
-
- Question:
-
- When I compile the following program
-
- 1: void main(void)
- 2: {
- 3: char String[10];
- 4: char *s;
- 5:
- 6: s = &String;
- 7: }
-
- using Version 5.10 and the command line
-
- cl -W3 karma.c
-
- the compiler generates the following message:
-
- karma.c(6) : warning C4046: '&' on function/array, ignored
-
- This is consistent with historical C behavior. However, I understand
- that ANSI C considers array names to be lvalues. The July 1989 MSJ
- article "Pointers 101: Understanding and Using Pointers in the C
- Language" validates this assumption. Does this mean that the "&" in
- "&String" is no longer benign? Under ANSI C, does this give me (in
- effect) a pointer to the address of "String"? What is the type and
- value of the expression "&String"?
-
- Response:
-
- The 5.10 compiler ignores the "&", so the type of "&String" is the
- same as "String", which is "pointer to char." This represents common
- pre-ANSI behavior.
-
- ANSI requires that the type of "&String" now be "pointer to array of
- 10 char." The next version of Microsoft C will conform to this
- requirement.
-
- However, aside from type warnings that may occur, this change IS
- benign because the address generated is identical in either case --
- the address of the zeroth element of the array. In other words, it
- will not somehow generate the address of the address -- especially
- since the address is a constant.
-
-
- 435. MSJ 9/88: "Using MSC for TSRs" Omission/TSRs in C Information
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890710-22224
- Last Modified: 26-JUL-1989 ArticleIdent: Q46948
-
- The September 1988 article in Microsoft Systems Journal (MSJ) titled
- "Using Microsoft C Version 5.1 to Write Terminate-and-Stay-Resident
- Programs" omits and misstates some important information about writing
- TSRs. In addition, the example calls BIOS from within a TSR, which is
- not guaranteed to be safe. Although this article is an excellent
- introduction to writing TSRs, especially in C, it does not contain all
- of the needed information. The article on TSRs in the "MS-DOS
- Encyclopedia" is a much more definitive reference.
-
- There are two problems in the article: first, the program calls BIOS
- functions from within the TSR. Since BIOS is not re-entrant, you can't
- always call BIOS from within a TSR. Second, it is not good advice to
- say that it's OK to compile with -AS rather than -Asnw. Unless you're
- going to switch to your own stack in the TSR, you should always use
- -Asnw.
-
- The article is correct when it says that, in general, you may NOT call
- DOS functions from within a TSR without taking special precautions.
- DOS is not re-entrant.
-
- Although the MSJ article does prepare you for the concepts you'll need
- to write TSRs, the best reference is the "MS-DOS Encyclopedia," which
- has a 40-page chapter on the topic. Among the topics are descriptions
- of how to safely call BIOS and DOS from within a TSR. The "MS-DOS
- Encyclopedia" is available in hardcover and paperback from Microsoft
- Press at (800) 888-3303 and is an exceptionally useful reference book.
-
- Programming TSRs in C is a very complicated task. Microsoft is unable
- to offer assistance beyond the "MS-DOS Encyclopedia" to help you with
- TSR programming. There are a number of small problems: many library
- functions call DOS, do stack checks, or make memory allocations (or
- all three); so they can't be called. However, you can often work
- around this problem by buying the library source from Microsoft [call
- (800) 426-9400] and modifying offending routines.
-
- A bigger problem is that there is no routine supplied to change the
- stack from the user's stack to your own. It's not wise to rely on the
- user's stack being big enough for your needs. To change to your own
- stack, you'll need an assembly-language subroutine, which may be a
- part of some function packages for writing TSRs in C.
-
- It's a bit easier to program TSRs in assembly language. With assembly
- language, you know exactly what's going on all the time. This is a big
- help in debugging. For a TSR that's going to be reliable, you'll need
- to know exactly what's going on.
-
- There are third-party packages that make programming TSRs in C
- easier and safer. You may want to contact one of the PC programmers'
- software houses about this.
-
-
- 436. VRES Video Modes Have 30 Lines Using Graphics Text Functions
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 15-JAN-1990 ArticleIdent: Q47021
-
- When using the Output Text routines in the Microsoft run-time library
- (Version 5.10 "Microsoft C for the MS-DOS Operating System: Run-Time
- Library Reference," Pages 54-55), the two graphic modes, _VRES2COLOR
- and _VRES16COLOR, have 30 text lines by default, due to their
- increased vertical resolution. All other graphics modes have 25 text
- lines when using these routines.
-
- The following graphics functions are the routines concerned with text
- placement and output:
-
- _displaycursor()
- _gettextcolor()
- _gettextposition()
- _outtext()
- _settextposition()
- _settextcolor()
- _settextwindow()
- _wrapon()
-
- The line numbers stated above are based on the default 8 x 8 font size
- of the IBM ROM BIOS. Note that when using fonts, the number of text
- lines in any video mode depends on the height of the font. For
- information concerning changing from the default font size, see the
- interrupt 10, function 11 entries in "IBM ROM BIOS," a Microsoft Press
- book by Ray Duncan.
-
-
- 437. Using _pgmptr to Get the Full Path of the Executing Program
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 8-AUG-1989 ArticleIdent: Q47037
-
- Question:
-
- On Page Update-23 of the "Version 5.10 Update" to the Microsoft C 5.10
- Optimizing Compiler, there is a description of the variable _pgmptr.
- The documentation states that _pgmptr points to a string containing
- the full pathname of the invoked program, but does not describe how to
- use it. I can't find _pgmptr in any of the include files. Where is
- _pgmptr declared and how do I use it?
-
- Response:
-
- The variable _pgmptr is not defined in an include file. It is declared
- in CRT0DAT.ASM, which is part of the C start-up code. This code is
- linked in to any module that contains a main() function. To use
- _pgmptr, you must first declare it as an external far character
- pointer, as follows:
-
- extern char far *_pgmptr;
-
- Since _pgmptr is automatically initialized at start-up to point to the
- full pathname of the executing program, this declaration is all that
- is required to make the full pathname available to your program.
-
- The following program demonstrates the usage of _pgmptr:
-
- #include <stdio.h>
-
- extern char far *_pgmptr;
-
- void main(void)
- {
- printf ("The full path of the executing program is : %Fs\n", _pgmptr);
- }
-
- In OS/2 real mode or DOS 3.x, argv[0] also contains a pointer to the
- full pathname of the executing program. In OS/2 protected mode,
- argv[0] contains only the information typed at the command line to
- invoke the program. Therefore, in OS/2 protected mode, using _pgmptr
- is the only way to easily access the executing program's full pathname
- string.
-
-
- 438. Best to Avoid C Run-Time Library Routines in TSRs
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890601-19569
- Last Modified: 30-AUG-1989 ArticleIdent: Q47105
-
- Question:
-
- I have two questions about using the C run-time library in a TSR
- (terminate-and-stay-resident program):
-
- 1. Will I encounter any problems with calling the following routines
- from a TSR? What about other library routines?
-
- _strncmp __aFFalshr __chkstk _sprintf _free
- __acrtused _memcpy _realloc _strlen _malloc
- _strcmp __aFFaulshr
-
- 2. What DOS system calls (INT 21) do the C library references shown
- above generate? I want to avoid calling DOS because it's not
- re-entrant.
-
- Response:
-
- Microsoft does not recommend using standard library routines in TSRs
- at all, even though they may appear to be safe. The main problem is
- that although they may be safe in this version of the compiler, they
- may change in future versions. Microsoft does not support using the
- run-time code in a TSR.
-
- In particular, you can have severe problems with chkstk, sprintf,
- malloc, realloc, and free. It is likely that the other routines won't
- present too much of a problem, but without digging through the source
- and knowing EXACTLY what you're doing, there is no way to be sure.
-
- There is, however, an excellent alternative. Microsoft offers the
- run-time library source for sale. Call our sales number at (800)
- 426-9400 for pricing and to order. With this source, you have almost
- total control over what your TSR looks like and how it acts. You can
- inspect each routine you use to ensure that it won't cause any
- interactions you don't want, and you can modify those routines that
- do. You're also better insulated against later modifications to the
- run-time library; since you control the code, you can modify it when
- you need to. This is by far your best alternative. You'll KNOW what's
- going on and you'll be able to ensure that you can maintain your
- applications. The only routines not included in this source are the
- floating-point and graphics routines.
-
- You may be able to find a source for routines written to support TSR
- programming even though Microsoft does not offer such software. Look
- for ads in the programmer-oriented PC magazines and/or call some of
- the programming-oriented software dealers.
-
- The run-time source allows you to determine which functions call DOS
- via INT 21h and which don't. Having the source also allows you to come
- up with alternative strategies for those functions that make calls.
-
- The "MS-DOS Encyclopedia" (published by Microsoft Press) is an
- excellent source of information about writing TSRs.
-
-
- 439. Warning C4051: Data Conversion from Constant to float
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 25-JUL-1989 ArticleIdent: Q47158
-
- Question:
-
- Why does the following program cause the C compiler to issue warning
- C4051 data conversion at warning level 2 or 3?
-
- void main(void)
- {
- float num1 = 3.4;
- }
-
- Response:
-
- The data conversion results from a type conversion between a float and
- a double. Num is declared as a float while 3.4 is a constant. Floating
- point constants have a default type of double. You may eliminate this
- warning error in one of two ways:
-
- 1. Declare the constant as a float as follows:
-
- float num1 = 3.4f;
-
- where the "f", or an "F", following "3.4" indicates that the constant
- is a 4-byte float instead of an 8-byte double.
-
- 2. Type cast the constant to a float as follows:
-
- float num = (float) 3.4;
-
-
- 440. .DEF File Optional Internal Names Not Supported by Implib
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | OPSYS PMWIN BUSLANG
- Last Modified: 17-AUG-1989 ArticleIdent: Q47225
-
- The implib utility does not put the optional internal name of a
- dynamically linked function into the import library it creates. Implib
- puts only the entry name of the function (the function name that
- external modules call) into the import library.
-
- The use of optional internal names is supported only by linking with
- the module definition file (.DEF) that specifies the internal function
- names (the actual function names in the source file) within a Dynamic
- Link Library (DLL) for OS/2 or DOS Windows.
-
- In a .DEF file, you can optionally specify aliases for the entry
- points into your DLL as in the following .DEF file statement:
-
- EXPORTS
- ENTRYNAME=INTERNALNAME
-
- ENTRYNAME is the name of a DLL routine called by other modules, and
- the optional INTERNALNAME is the actual name of the function or
- procedure in the DLL. By default, the INTERNALNAME is the same as the
- ENTRYNAME, but you may want to provide more meaningful entry names to
- the users of your DLL in addition to the actual internal function
- names.
-
- The names of dynamically linked functions in a DLL must be specified
- in either a .DEF file or in an import library, which has a .LIB
- extension, so that the linker can resolve all references (calls) to
- the DLL functions. Attempting to link an application that calls DLL
- functions without an import library or .DEF file results in LINK :
- error L2029: Unresolved externals: for the DLL function names.
-
- Import libraries, consisting of little more than the names of the
- modules in the DLL and the externally callable functions within the
- DLL, are created by the implib utility from an existing .DEF file with
- a command such as the following, which creates the import library
- "myimport.lib" from the existing module definition file "myfile.def":
-
- implib myimport.lib myfile.def
-
- Commonly used import libraries for OS/2 are DOSCALLS.LIB for the OS/2
- 1.00 API (Application Program Interface) DLL routines, OS2.LIB for
- OS/2 1.10, or CRTLIB.LIB for the multi-thread C 5.10 run-time
- CRTLIB.DLL. The Windows Software Development Kit for creating DOS
- Windows applications comes with memory model-specific import libraries
- such as SLIBW.LIB.
-
-
- 441. _makepath() and _splitpath Examples Are Incomplete
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr S_QuickC
- Last Modified: 17-AUG-1989 ArticleIdent: Q47226
-
- In the C 5.x "Microsoft C for the MS-DOS Operating System: Run-Time
- Library Reference" documentation for _makepath (Page 407) and
- _splitpath (Page 559), the examples do not compile without generating
- an indirection error. This is due to the variables being declared as
- pointers. Also, the file should include <stdlib.h>, not <dos.h>. Below
- is an example of how the file should read to compile on warning level
- 3 without errors.
-
- In the QuickC Versions 1.00 and 1.01 "Microsoft QuickC Run-Time
- Library Reference," the documentation for _makepath (Page 407) and
- _splitpath (Page 559) also contain an error. The example program
- declares the ext variable as a 4-byte character array. This should be
- changed to a 5-byte array as shown below. This second problem appears
- when the file extension has a three-character extension such as
- ".doc".
-
- The following code should be used in place of the examples for
- _makepath and _splitpath in the QuickC 1.x run-time documentation as
- well.
-
- #include <dos.h>
- #include <stdlib.h>
- #include <stdio.h>
-
- void main( void )
- {
- char path_buffer [40];
- char drive [3];
- char dir [30];
- char fname [9];
- char ext [5];
-
- _makepath (path_buffer, "d:", "\\src\\test\\", "new","dat");
- printf("path created with _makepath: %s\n\n", path_buffer);
-
- _splitpath (path_buffer, drive, dir, fname, ext);
- printf("path extracted with _splitpath\n");
- printf("drive: %s\n", drive);
- printf("dir: %s\n", dir);
- printf("fname: %s\n", fname);
- printf("ext: %s\n", ext);
- }
-
-
- 442. BSEARCH Does Not Find the First Occurrence of Key in the Array
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr S_QuickC
- Last Modified: 31-AUG-1989 ArticleIdent: Q47234
-
- The run-time library function bsearch() is documented on Page 147 in
- the "Microsoft C for the MS-DOS Operating System: Run-Time Library
- Reference" as returning a pointer to the first occurrence of key in
- the array pointed to by base. This may not be true when multiple
- elements of the array match the key. In the case where multiple
- elements match the key, bsearch returns a pointer to the first element
- that it finds, not necessarily the first element of the array that
- matches the key. This is the proper action for bsearch to take. The
- documentation should read as follows:
-
- Return Value:
-
- The bsearch function returns a pointer to the occurrence of key in
- the array pointed to by base. If there is more than one occurrence
- of key, the pointer returned by bsearch may point to any of them.
- If key is not found, the function returns NULL.
-
- The behavior occurs because of the nature of the binary search
- algorithm. If you need to find the first matching element, use the
- lfind() (linear find) function instead of bsearch(). Note: Linear
- finds are much slower than binary searches.
-
- Below is a sample program that demonstrates this behavior:
-
- #include <search.h>
- #include <string.h>
- #include <stdio.h>
-
- int qcompare(); /* declare a function for qsort's compare */
- int bcompare(); /* declare a function for bsearch's compare */
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- char **result;
- char *key = "Brad";
- int i;
-
- /* Sort using Quicksort algorithm: */
-
- qsort((char *) argv, argc, sizeof(char *), qcompare);
- for (i = 0; i<argc; ++i) /* Output sorted list */
- printf("%s\n", argv[i]);
-
- /* Find item that begins with "Brad" using a binary search algorithm: */
-
- result = (char **) bsearch((char *) &key, (char *) argv, argc,
- sizeof(char *), bcompare);
- if (result)
- printf("%s found\n", *result);
- else
- printf("PATH not found !\n");
- }
-
- int qcompare (arg1, arg2)
- char **arg1, **arg2;
- { /* Compare all of both strings: */
- return (strcmp(*arg1, *arg2));
- }
-
- int bcompare (arg1, arg2)
- char **arg1, **arg2;
- { /* Compare to length of key: */
- return (strncmp(*arg1, *arg2, strlen(*arg1)));
- }
-
- The program sorts the command line args and then compares them with
- the key "Brad". If you enter the command line arguments, Brad1 Brad2
- Doug, you find that the bsearch routine returns Brad2. Note: The
- number is not checked because the bcompare function checks only the
- first four characters.
-
- Since BSEARCH cuts the array section being searched in half with each
- check, it finds Brad2 before Brad1. Instead of continuing to search
- for the first occurrence of Brad (as is documented), it immediately
- returns with a pointer to Brad2 (which is the proper action).
-
-
- 443. scanf Unable to Match Extended Characters in Format String
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 9-AUG-1989 ArticleIdent: Q47369
-
- Note: In this article, the "??" symbol is used to represent an
- extended ASCII character. Because extended ASCII characters appear
- differently on many systems, it is unreliable to use a real character.
- Therefore, whenever you see the "??" symbol, it is meant to represent
- a character with an ASCII code of 128 to 255.
-
- When using the scanf functions (scanf, cscanf, fscanf, sscanf), you
- may place literal characters in the format string and scanf will read
- an input string as long as the input string matches these characters
- in position and value. Once the input string conflicts with the
- format, scanf terminates. The allowable characters are the standard
- ASCII values only and attempts to use extended ASCII characters in the
- format result in failure. The scanf function terminates as soon as it
- reads an extended character, even if it is the same as the expected
- character in the format. For example, if the format string contains
- "??%d", and "??45" is input, scanf quits reading at "??" even though
- it matches, since it does not recognize the extended ASCII value.
-
- This problem does not occur in QuickC Versions 2.00 and 2.01.
-
- The following program demonstrates this situation. In the first case,
- scanf expects "sqrt" to be typed in followed by a number. If this is
- done correctly, then scanf reads the number and the square root is
- displayed. In the second case, scanf should be expecting the "??"
- symbol followed by a number, but if this is typed in, scanf still
- fails to read the number since it was unable to correctly match the
- "??" to the format string.
-
- /* Before running this program, replace all occurrences of "??" with
- extended ASCII character 251. (Hold down the ALT key and type 251
- on the numeric keypad, then release the ALT key.) */
-
- #include <stdio.h>
- #include <math.h>
-
- void main(void)
- {
- int values_read;
- double num;
-
- /* THIS PART WORKS - scanf recognizes "sqrt" in format string */
-
- printf( "Enter sqrtNUMBER by typing \"sqrt\" followed by any "
- "NUMBER >= 0\n(e.g sqrt87.6) : ");
- values_read = scanf( "sqrt%lf", &num);
- printf( "values_read = %d\n", values_read);
- printf( "sqrt%lf = %lf\n\n", num, sqrt(num));
- fflush(stdin);
-
- /* THIS PART DOES NOT WORK - scanf fails to recognize "??" in
- the format string */
-
- printf( "Enter ??NUMBER by holding down the <ALT> key while "
- "typing\n\"251\" on the numeric keypad followed by "
- "any NUMBER >= 0\n(e.g. ??87.6) : ");
- values_read = scanf( "??%lf", &num); /* returns 0 */
- printf( "values_read = %d\n", values_read);
- printf( "??%lf = %lf\n\n", num, sqrt(num));
- }
-
-
- 444. FP_SEG(), FP_OFF() Need Pointer Rather Than Address
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 31-AUG-1989 ArticleIdent: Q47497
-
- Because FP_SEG() and FP_OFF() macros de-reference the pointer values
- passed to them, the address of a variable cannot be passed as a
- parameter.
-
- The FP_SEG() and FP_OFF() macros are defined in DOS.H as follows:
-
- #define FP_SEG(fp) (*((unsigned *)&(fp) + 1))
- #define FP_OFF(fp) (*((unsigned *)&(fp)))
-
- The first step of the macro is to take the address of the pointer that
- is passed to it. Because of this, the code
-
- unsigned val;
- unsigned i;
- i = FP_OFF(&val);
-
- produces the following error in C 5.00 and 5.10, as well as QuickC
- 1.01:
-
- C2102: '&' requires lvalue
-
- QuickC 2.00 produces the following warning, which does not hinder
- compilation:
-
- C4046: '&' on function/array, ignored
-
- These messages occur because the macro cannot take the address of an
- address. However, the code
-
- unsigned val, *valptr;
- unsigned i;
- valptr = &val;
- i = FP_OFF(valptr);
-
- returns the offset of the variable val, as the address of valptr can
- be taken.
-
-
- 445. Determining the Number of Valid Drives in DOS
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickASM H_MASM O_MSDOS
- Last Modified: 9-AUG-1989 ArticleIdent: Q47484
-
- Question:
-
- I have an application that needs to determine the number of logical
- drives installed on a given computer. I have tried using the DOS
- function "SelectDisk" (0x0E), but it seems to return the number 5 on
- all machines, no matter how many drives are installed. Is there a way
- to get this information from DOS?
-
- Response:
-
- There are no DOS calls for determining the number of logical drives
- installed on a computer. The DOS call SelectDisk returns only the
- value stored in the DOS variable LASTDRIVE. This variable normally
- contains 5 (maximum drive letter is "E") unless LASTDRIVE is
- specifically set in the CONFIG.SYS file.
-
- The LASTDRIVE value is useful, however, when determining which drives
- are valid and which are not. Since LASTDRIVE reflects the highest
- available drive letter, we can use DOS calls to determine which of the
- available drives are valid. The DOS calls SelectDisk (0x0E) and
- GetDisk (0x19) can be used to provide this information.
-
- Note: Any network drives to which you're attached are also considered
- valid. If you need to distinguish between network and non-network
- drives, modify the program below to use INT 21h function 44h (IOCTL),
- subfunction 09h ("Check if block device is remote"). For more
- information, see a good DOS reference such as "Advanced MS-DOS
- Programming" (by Duncan, published by Microsoft Press), or the "MS-DOS
- Encyclopedia" (also published by Microsoft Press).
-
- If you try, one at a time, to change the current drive to each of the
- available drive letters, you will see which ones are valid. Since
- SelectDisk does not return an error code in the event that it fails to
- select a new disk, call GetDisk afterwards to determine if it was
- successful.
-
- The following C source code illustrates this method:
-
- /*
-
- Will not run under OS/2. For DOS only.
-
- The following program displays all of the logical drives installed on
- a DOS system. This program uses DOS function calls to obtain the
- current drive and change it to a new drive.
-
- */
-
- #include <stdio.h>
- #include <dos.h>
-
- /* simple types */
-
- #define BYTE unsigned char
- #define BOOLEAN int
-
- /* function prototypes */
-
- BYTE DosGetDisk(void);
- int DosSelectDisk(BYTE);
- BOOLEAN ValidDrive(BYTE);
-
- void main(void)
- {
- BYTE CurDrive;
- int NumDrives;
- int x;
-
- CurDrive = DosGetDisk(); // currently active drive
- NumDrives = DosSelectDisk(CurDrive); // returns number set in
- // LASTDRIVE
-
- for (x = 0; x < NumDrives; x++) // go through all possible drives
- if (ValidDrive((BYTE)x)) // print message if drive x valid
- printf("Drive %c is valid\n",(char)x+'A');
-
- DosSelectDisk(CurDrive); // set default drive back
-
- } /* end of main */
-
- BOOLEAN ValidDrive(BYTE drive) // returns true if drive valid,
- { // false otherwise
- DosSelectDisk(drive); // attempt to make drive current
-
- return (DosGetDisk() == drive); // did it succeed?
- }
-
- BYTE DosGetDisk(void) // returns drive number of current drive
- {
- union REGS reg;
-
- reg.h.ah = 0x19; // call DOS to find
- int86(0x21,®,®);
-
- return (reg.h.al);
- }
-
- int DosSelectDisk(BYTE drive) // sets current drive
- {
- union REGS reg;
-
- reg.h.ah = 0x0e; // set by calling DOS
- reg.h.dl = drive;
- int86(0x21,®,®);
-
- return ((int) reg.h.al);
- }
-
-
- 446. Variable Width, Precision Available with printf
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC 1.00 1.10 2.00 2.01 S_QuickASM
- Last Modified: 9-AUG-1989 ArticleIdent: Q47663
-
- The Microsoft run-time library function printf() allows the width of
- the format specifier to be supplied at run time. This is done with the
- use of the * with the format specifier. This is mentioned on Pages 460
- and 461 of the "Microsoft C 5.1 Optimizing Compiler Run-Time Library
- Reference." The following code sample demonstrates this capability.
-
- Code Sample
- -----------
-
- /* This program defines a procedure to print out a floating point
- number with variable width and precision.
- */
- #include <stdio.h>
-
- void print(int, int, float);
-
- void main(void) {
- print (10, 2, 1234.5678f);
- print (9, 4, 1234.5678f);
- print (5, 2, 1234.5678f);
- }
-
- void print(int w, int p, float value) {
- printf ("Printf format :%*.*f\n", w, p, value);
- printf ("Width = 0123456789012\n");
- }
-
-
- 447. errno Values Not Used under MS-DOS Indicate Other Problem
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 9-AUG-1989 ArticleIdent: Q47692
-
- When an error occurs in some library routines, the errno variable is
- set to a value that can be used to indicate the nature of the error.
- These error codes are defined in the file errno.h. The codes
- originally were set up for use with UNIX to conform to errors
- occurring under that operating system. Because of this, and the
- differences between MS-DOS and UNIX, many of the codes have no
- relevance to the MS-DOS environment.
-
- In order to maintain compatibility with UNIX and XENIX, all the codes,
- whether meaningful in MS-DOS or not, are defined in errno.h. Appendix
- A of the "Microsoft C 5.1 Optimizing Compiler Run-Time Library
- Reference" lists only those codes that have meaning under MS-DOS along
- with their description and causes. These specific codes have
- corresponding error messages that can be printed out with the perror
- function.
-
- If you are working under MS-DOS and you obtain an errno value that is
- not one of the listed codes, then you can assume that the code was
- generated incorrectly and it is not indicative of the true problem.
- The documentation for the specific function you are using says which
- errno values, if any, may be set by an error in that function.
-
- The following is a listing of all the errno values defined in errno.h
- along with brief descriptions of their meanings. Only the values that
- are marked with "*" may be considered valid under DOS. For more
- information on these, see Appendix A of the "Microsoft C 5.1
- Optimizing Compiler Run-Time Library Reference." For more information
- on the others that are not marked with an asterisk (*), see a UNIX or
- XENIX system manual.
-
- * Used under MS-DOS
-
- Value Define Description
- ----- ------ -----------
-
- EPERM 1 Not owner
- ENOENT 2 *No such file or directory
- ESRCH 3 No such process
- EINTR 4 Interrupted system call
- EIO 5 I/O error
- ENXIO 6 No such device or address
- E2BIG 7 *Arg list too long
- ENOEXEC 8 *Exec format error
- EBADF 9 *Bad file number
- ECHILD 10 No child processes
- EAGAIN 11 No more processes
- ENOMEM 12 *Not enough space
- EACCES 13 *Permission denied
- EFAULT 14 Bad address
- ENOTBLK 15 Block device required
- EBUSY 16 Mount device busy
- EEXIST 17 *File exists
- EXDEV 18 *Cross-device link
- ENODEV 19 No such device
- ENOTDIR 20 Not a directory
- EISDIR 21 Is a directory
- EINVAL 22 *Invalid argument
- ENFILE 23 File table overflow
- EMFILE 24 *Too many open files
- ENOTTY 25 Not a teletype
- ETXTBSY 26 Text file busy
- EFBIG 27 File too large
- ENOSPC 28 *No space left on device
- ESPIPE 29 Illegal seek
- EROFS 30 Read-only file system
- EMLINK 31 Too many links
- EPIPE 32 Broken pipe
- EDOM 33 *Math argument
- ERANGE 34 *Result too large
- EUCLEAN 35 File system needs cleaning
- EDEADLOCK 36 *Would deadlock
-
-
- 448. Initializing Unions Initializes the First Member of the Union
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 16-AUG-1989 ArticleIdent: Q47693
-
- When you initialize a union, the initialization value is applied to
- the first member of the union even if the type of the value matches a
- subsequent member. As stated in the ANSI Standard, Section 3.5.7:
-
- A brace-enclosed initializer for a union object initializes the
- member that appears first in the declaration list of the union
- type.
-
- Since you cannot initialize the value of any member of a union other
- than the first one, you must assign their values in a separate
- statement. Initializing a union with a value intended for a subsequent
- member causes that value to be converted to the type of the first
- member.
-
- The following example demonstrates the issue:
-
- #include <stdio.h>
- union { int a; /* only external unions may be initialized */
- float b;
- } test = {3.6}; /* this is intended to initialize 'b' */
- /* however, the value will be converted */
- /* (first to a long and then to an int) */
- /* in order to initialize 'a' */
-
- void main (void)
- {
- float dummy = 0.0; /* this causes the floating point */
- /* math package to be initialized */
-
- printf ("test.a = %d, test.b = %f\n", test.a, test.b);
- }
-
- The output from the example, though not what is intended, will be as
- follows:
-
- test.a = 3, test.b = 0.00000
-
- To associate a value with "b", you can reverse the order of the
- members, as in the following:
-
- union {
- float b;
- int a;
- } test = {3.6};
-
- Or, you can retain the order of the elements and assign the value in a
- separate statement, as in the following:
-
- test.b = 3.6;
-
- Either of these methods creates the following output:
-
- test.a = 26214, test.b = 3.600000
-
-
- 449. Network License Agreement for All Microsoft Language Products
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickASM S_PasCal S_QuickPas
- Last Modified: 4-JAN-1990 ArticleIdent: Q47724
-
- Network license agreements do not exist for any of the Microsoft
- language products. These agreements are currently available only for
- our application products.
-
- According to the licensing agreement printed on the envelope that
- contains the disks, our languages are licensed as single-user,
- single-workstation products and cannot be used by more than one user
- simultaneously. Running off of a network server or installing copies
- on more than one workstation is specifically prohibited by this
- agreement. However, the agreement does allow users to share the
- software if they run it off the same workstation at different times.
-
- In a networked environment, each node on the network that will be used
- for development must have a copy of the product installed on a local
- drive. Work files can be shared over the network, but neither
- compilers nor the associated utilities of a package can be shared over
- the network.
-
-
- 450. Filelength() Includes EOF Character in Return Value
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC 2.00
- Last Modified: 14-AUG-1989 ArticleIdent: Q47737
-
- The return value of the filelength function is the full length of the
- file in bytes, including any EOF characters. The return value returns
- the same file size value as the DIR command from the DOS or OS/2
- prompt.
-
-
- 451. Closing stdprn and stdaux May Not Increase Available Handles
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | SR# G890728-23559
- Last Modified: 16-AUG-1989 ArticleIdent: Q47741
-
- Question:
-
- We are trying to close the handles for stdaux and stdprn so that we
- can open additional files before hitting the limit of the FILES=
- parameter in CONFIG.SYS (which we set to 11). In that mode, regardless
- of whether or not we close handles 3 and 4 (stdaux and stdprn), we are
- able to open only 8 files (FILES= - 3). The "MS-DOS Encyclopedia"
- states that stdin, out, and err are mapped to one device, but use
- three handles.
-
- We noticed that if FILES= in CONFIG.SYS is set to 20 or above, the
- program DOES get additional files opened when handles 3 and 4 are
- closed. Apparently we're getting some sort of interaction between the
- process file-handle table/limit (of 20) and the system table/setting
- from CONFIG.SYS.
-
- How can we gain access to those two file handles, keeping our FILES=
- setting in CONFIG.SYS at 11? We want to be able to open 10 files in
- our program, with FILES= set to 11.
-
- Response:
-
- Due to a limitation of DOS, you can't do this. The workaround is to
- simply set FILES=13, for the reasons described below.
-
- In order to open a file using the C run time, ALL of the following
- conditions must be true:
-
- 1. There must be a space in the C run-time library's internal file
- tables. This is normally limited to 20 files, but this limit can be
- increased by modifying the start-up code if you're using DOS 3.30
- or later.
-
- 2. There must be DOS file handles available to your particular
- process. Again, the normal limit is 20, but this can be increased
- with a call to function 67h of INT 21h (only under DOS 3.30 or
- later). This can also be modified in the start-up code.
-
- 3. Finally, there must be files available from DOS's system-wide pool,
- as set by FILES= in CONFIG.SYS. (This defaults to 8, but can be set
- as high as 20 under DOS Version 3.30 and earlier or 255 under
- Versions 3.30 and later.)
-
- The results of comparing a C program that uses the C run-time library
- and a MASM program that calls DOS directly are shown below. Each was
- run with stdprn and stdaux, closed and open.
-
- C Program MASM Program
- --------- ------------
-
- FILES= W/o Closing W/ Closing W/o Closing W/ Closing
- ------ ----------- ---------- ----------- ----------
-
- 17 (Note 1) 14 14 14 14
- 18 (Note 1) 15 15 15 15
- 19 15 16 16 16
- 20 15 17 17 17
- 21 (Note 2) 15 17 17 17
-
- Please note the following:
-
- 1. The formula for the number of files you can open for FILES=n, where
- n is less than 19, is n - 3.
-
- 2. No matter how high you set FILES=, you'll be limited to these
- numbers in C unless you modify the start-up code as described in
- README.DOC. In MASM, you'll be limited to these numbers unless you
- raise the per-process limit on file handles by calling INT 21h,
- function 67h.
-
- 3. Running the program from a batch file doesn't change these numbers;
- however, reduce each number by 1 for each input or output
- redirection you do.
-
- 4. The MASM program doesn't get any additional handles freed up when
- it closes handles 3 and 4 because, contrary to what the "MS-DOS
- Encyclopedia" implies, DOS won't allow you to reuse those two
- handles.
-
- Without closing handles, C programs give you a constant 15 or n - 3,
- whichever is smaller. The upper limit is 15 because, unless you modify
- the start-up code, the limit is 20 minus the five default files.
-
- When you close handles 3 and 4, they are closed for C but not for DOS.
- Therefore, you can open exactly as many handles as DOS normally
- allows.
-
-
- 452. _amblksiz Affects Memory Allocation in Near and Far Heaps
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 16-AUG-1989 ArticleIdent: Q47766
-
- The documentation on Page 33 of the "Microsoft C for the MS-DOS
- Operating System: Run-Time Library Reference" states that adjusting
- the value of the global variable _amblksiz has no effect on halloc or
- _nmalloc() in any memory model.
-
- This statement in the manual is incorrect. In fact, _amblksiz is used
- to determine how much to expand both the near heap and the far heap
- segments, and is used by calls to _nmalloc(). The only difference
- between calls to _nmalloc() and _fmalloc is that _nmalloc() doesn't
- actually request memory from DOS, it takes it from the pre-allocated
- heap (in DOS).
-
- However, since the the memory allocated by a call to halloc() is
- maintained independently of the near and far heaps, the value of
- _amblksiz does not affect calls to halloc().
-
- The default value of _amblksiz is 8K (8192) bytes. The variable is
- declared in malloc.h. For more information about the use of _amblksiz,
- refer to the "Microsoft C for the MS-DOS Operating System: Run-Time
- Library Reference," Section 3.2.
-
-
- 453. Linking without /NOI Causes SYS2070 in Program Calling CRTLIB
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | SR# G890807-24188
- Last Modified: 16-JAN-1990 ArticleIdent: Q47779
-
- Programs that are linked with the C run-time library DLL (CRTDLL),
- without the /NOI switch, fail with the following message:
-
- SYS2070: The system could not demand load the application's
- segment. CRTLIB __STDOUT is in error.
-
- To avoid the problem, use the /NOI switch when linking. The proper use
- of /NOI is described in Section 5.2 of the MTDYNA.DOC file supplied
- with Microsoft C Version 5.10.
-
-
- 454. Blinking Text May Be Eliminated with BIOS Call
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickASM EGA
- Last Modified: 16-JAN-1990 ArticleIdent: Q47780
-
- Blinking text can be accessed by setting the foreground text color to
- a value of 16 or greater. However, this can be affected by a BIOS call.
- BIOS call 10, subfunction 3 toggles the interpretation of the
- intensity bit of the foreground color. By making a call to this BIOS
- function you can access additional background colors. Without blinking
- foreground text, you can access 16 background colors. With blinking
- text you are limited to 8 background colors. The program shown below
- demonstrates this.
-
- The example prints 16 lines of text with varying background colors.
- The intensity interpretation is then toggled, limiting the output to
- only 8 background colors.
-
- This problem also occurs in Microsoft QuickC Versions 1.00, 1.01,
- 2.00, and 2.01.
-
- Sample Program:
- --------------
-
- #include <stdio.h>
- #include <graph.h>
- #include <dos.h>
- #include <conio.h>
-
- #define TRUE 1
- #define FALSE 0
-
- void toggle_intensity(int);
-
- void main(void) {
- long i;
- char buf[80];
- _clearscreen(_GCLEARSCREEN);
- toggle_intensity(0);
- for (i=16; i < 32; i++) {
- _setbkcolor (i);
- _settextcolor (i+1);
- _settextposition (i-15, 10);
- sprintf(buf, " Background = %2ld Foreground = %2d \n",i,i+1);
- _outtext (buf);
- }
- getch();
-
- _setbkcolor (_BLACK);
- _clearscreen(_GCLEARSCREEN);
- toggle_intensity(1);
- for (i=16; i < 32; i++) {
- _setbkcolor (i);
- _settextcolor (i+1);
- _settextposition (i-15, 10);
- sprintf (buf, " Background = %2ld Foreground = %2d \n", i, i+1);
- _outtext (buf);
- }
- getch();
- }
-
- /* If onoff is True, intesity bit will indicate blinking text */
- void toggle_intensity(int onoff) {
- #define VIDEO_IO 0x10
- #define BIOS_CALL 0x10
- #define INTENSITY_TGL 0x03
- union REGS regs;
-
- regs.h.ah = VIDEO_IO;
- regs.h.al = INTENSITY_TGL;
- if (!onoff)
- regs.h.bl = 0x0;
- else
- regs.h.bl = 0x1;
- int86 (BIOS_CALL, ®s, ®s);
- }
-
-
- 455. Effective Limit of 52 Threads Per Process with DosCreateThread
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | docerr OpSys PMWin
- Last Modified: 16-JAN-1990 ArticleIdent: Q47933
-
- A single process running under OS/2 Version 1.10 or 1.00 is limited to
- creating 52 threads with DosCreateThread.
-
- Attempting to create additional threads results in a return value
- from DosCreateThread of 155, which is defined as ERROR_TOO_MANY_TCBS
- (Thread Control BlockS) in BSEERR.H.
-
- The "Microsoft OS/2 Programmer's Reference," Volume 3, Page 34,
- incorrectly states "DosCreateThread can create up to 255 threads per
- process." The Reference also fails to note that DosCreateThread could
- return ERROR_TOO_MANY_TCBS.
-
- The only way to work around the current OS/2 1.x limitation with
- DosCreateThread is by starting additional processes, with each process
- being limited to 52 threads. OS/2 1.10 and 1.00 can support up to 255
- threads total for all processes in the entire system.
-
- An increase in the limit will be considered for inclusion in a future
- release.
-
- Note that threads that will be calling C run-time library functions
- should be created with _beginthread, which performs essential library
- initializations that DosCreateThread does not perform. The library
- function _beginthread is limited to creating 31 threads in C 5.10, for
- a total of 32 threads. The next version of C will support the creation
- of substantially more threads with its _beginthread.
-
-
- 456. Patching malloc() to Reuse Memory within an Allocated Block
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 16-JAN-1990 ArticleIdent: Q47958
-
- The malloc() family of functions properly reuse the blocks of memory
- that they allocate from DOS. The size of a block that malloc()
- allocates is 8K bytes by default, but can be modified by assigning a
- different block size in bytes to the C run-time library variable
- "_amblksiz", as noted on Page 33 of the "Microsoft C 5.1 Optimizing
- Compiler Run-Time Library Reference."
-
- However, for small suballocations of "chunks" (author's terminology)
- within an 8K block, previously freed chunks will not be immediately
- reused and fragmentation within blocks can occur; this can cause DOS
- programs that make many small (e.g. 10-byte) allocations to
- prematurely run out of memory. This problem occurs because the "rover"
- pointer that points to the next chunk of memory to be allocated points
- to the memory after the last chunk allocated without being set to
- point to the beginning of chunks that were freed.
-
- Reducing the size of allocated blocks by declaring _amblksiz as above
- and assigning values under 8096 to it may help reduce fragmentation
- within blocks in some cases simply because there is less memory to
- lose to fragmentation per block and your allocations and frees are
- more likely to be on reusable block boundaries.
-
- A better alternative would be to allocate large blocks yourself, then
- perform your own memory management within them to prevent
- fragmentation within blocks.
-
- For those who purchase the C run-time library source code for C 5.10
- available through our Sales department at (800) 426-9400, you can
- force the rover pointer to point at the bottom of the block prior to a
- memory request as noted below, so that any adequately large freed
- chunks will be reused. This technique will result in executable speed
- degradation, but will more fully allocate the last bytes of memory.
-
- To change the behavior of the rover pointer to reallocate freed chunks
- of memory within a block, make the following change to line 83 of
- AMALLOC.ASM, the workhorse module called by malloc() functions:
-
- 1. Delete or comment out line 83 with a semicolon (;), as follows:
-
- ; mov si,[bx].roveroff; si = starting rover offset
-
- 2. Replace the line above with the following two lines:
-
- mov si,[bx].bottom
- mov [bx].roveroff,si ;*** put rover at bottom each time
-
- 3. Reassemble AMALLOC.ASM with MASM, as follows
-
- masm /Mx /Dmem_L amalloc;
-
- where the /Mx option preserves symbol name case sensitivity, and
- /Dmem_L defines the constant to indicate large memory model for
- pointers defined by macros in AMALLOC.ASM and other .ASM files used
- for the C library. The constant "mem_L" is for large model, "mem_S"
- for small, "mem_C" for compact, and "mem_M" is for medium model.
-
- 4. Either link with the new AMALLOC.OBJ (and /NOE), or use lib to
- replace the module in the appropriate memory model library, as
- follows:
-
- lib llibcer.lib -+amalloc;
-
-
- 457. Description of a .MAP File's "Program Entry Point"
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 16-JAN-1990 ArticleIdent: Q47959
-
- The "Program entry point" is the last item in a .MAP file. It refers
- to the segment:offset address of the first instruction of the program
- to be executed, relative to the lowest memory address in the .EXE load
- image (the program loaded into RAM). A more detailed description and
- the use of entry point(s) are noted below.
-
- The load address can be obtained by adding 10h to the segment address
- of the PSP. (In C, this is available in the variable _psp.)
-
- An entry point is where code in a module actually begins execution
- via the loading of the CS:IP (CodeSegment:InstructionPointer --
- segment:offset) registers with the entry point address. The entry
- point could be the actual beginning of a program executed by the
- operating system, or it could be an exported function from an
- OS/2 or DOS Windows dynamic link library (DLL).
-
- The "Program entry point" specified at the end of a .MAP file is where
- the operating system will begin executing the program, RELATIVE to the
- lowest memory address where the program's code will be loaded. In DOS
- or real-mode OS/2, the lowest memory address will be the lowest
- physical address in RAM. In protected-mode OS/2, the lowest relative
- address will be segment selector 1, offset 0.
-
- The lowest address your code occupies in RAM is usually the first
- routine (function, procedure, or main program body) defined at the
- beginning of your main source file, and it is assigned a RELATIVE
- address of 0000:0000 [or, typically, 0:10 for main()] in DOS or
- real-mode OS/2, or an address of 0001:0000 in protected-mode OS/2.
-
- For our current high-level languages (except Microsoft QuickPascal
- 1.00), the entry point is at the beginning of the routine "__astart".
- Our high-level languages require initialization code before executing
- C's main() function or the main program code for other languages such
- as Microsoft Pascal 3.3x or 4.00, and currently __astart is where the
- initializations begin.
-
- The "Program entry point" is a segment:offset address above the
- program's relative address of 0:0. For a C program, the entry point
- will be __astart. If the entry point is something like 2:0abc hex, the
- absolute DOS physical address or the virtual OS/2 address where
- __astart will be located can be calculated as follows:
-
- lowest address of your program's load image 1234:0400
- + relative entry point + 2:0abc
- --------------------------------------------- ---------
- = DOS absolute or OS/2 virtual address of 1236:0e34
- the entry point (__astart)
-
-
- 458. Extracting a Function ptr from a Variable arg List Function
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_quickC S_QuickASM
- Last Modified: 16-JAN-1990 ArticleIdent: Q47961
-
- To remove an item from a variable argument list, you use the va_arg()
- macro. However, when the element to be removed is complex, you may
- have to typedef the item type. This is necessary because the va_arg()
- macro requires you to provide the type of the item to be removed from
- the list. For a pointer to a function, if you were to put the item
- type (the declaration of the function ptr) as follows
-
- FuncPtr = va_arg (arg_list, (int(*)(void)) );
-
- the compiler would yield the following error:
-
- C2059: Syntax Error : ')'
-
- You could attempt to get around this by grabbing the function pointer
- as a data pointer, and then typecasting it to a function pointer, as
- in the following line:
-
- FuncPtr = (int (*)(void)) va_arg (arg_list, char *);
-
- This would work; however, you will get the following warning:
-
- C4074: Non-standard extension used, cast of data pointer
- to function pointer
-
- The best solution to this dilemma is to typedef the function pointer.
- With a typedef, you avoid both the error and the warning.
-
- This problem occurs in C Version 5.10 and in QuickC Version 2.00 and
- 2.01.
-
- The following example passes a function pointer to a variable argument
- list function, changes that pointer, and returns it to the calling
- procedure. To implement this, however, you need to pass the function
- pointer by reference. For this reason, a pointer is typedef'd to a
- function pointer. Once in the variable argument list function, the
- pointer is dereferenced to the function pointer to get at the actual
- function pointer.
-
- #include <stdio.h>
- #include <stdarg.h>
-
- typedef void (*FuncPtr)(void);
- typedef FuncPtr *PFuncPtr;
-
- void hello(void);
- void varfunc(int, ...);
-
- FuncPtr func1, func2;
- int i;
-
- void main(void) {
- func1 = hello;
- printf ("Function pointer: func1 now points to Hello()\n");
- printf ("About to use func1 to make a call to Hello()\n\n");
- func1();
- printf ("Now lets pass these function pointers to our variable");
- printf (" argument list\n");
- varfunc(2, &func1, &func2); /* To alter ptr, pass by reference */
- printf ("\nAfter the call to the variable argument procedure,\n");
- printf ("function pointer: func2 now points to Hello()\n");
- printf ("About to use func2 to make a call to Hello()\n\n");
- func2();
- }
-
- void hello(void) {
- printf ("Hello, I'm in the procedure HELLO()\n");
- }
-
- void varfunc(int i, ...) {
- va_list arg_ptr;
- PFuncPtr tmpfptr; /* Temporary ptr to function ptr */
-
- printf ("\nIn function VARFUNC\n");
- va_start (arg_ptr, i);
- printf ("%d arguments were passed\n", i);
- tmpfptr = va_arg (arg_ptr, PFuncPtr); /* Grab pointer to fnptr */
- *tmpfptr = hello; /* Assign fnptr addr of fn */
- tmpfptr = va_arg (arg_ptr, PFuncPtr); /* Grab pointer to fnptr */
- *tmpfptr = hello; /* Assign fnptr addr of fn */
- }
-
-
- 459. Calling Order Undefined -- Function Calls in Single Expression
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 15-JAN-1990 ArticleIdent: Q47985
-
- When C evaluates more than one function call in a single expression,
- the calls usually are made in reversed or arbitrary order, rather than
- in the stated order. Since there is no defined precedence in C for the
- order in which multiple function calls are made within a single
- expression, the result is compiler-dependent. In Microsoft's products,
- these functions are usually evaluated from right to left.
-
- This occurs in C Versions 5.00 and 5.10 and in QuickC Versions 1.01,
- 2.00, and 2.01.
-
- The following code demonstrates this:
-
- void main( void )
- {
- printf( "First: %d Second: %d", getch(), getch() );
- }
-
- When this code is compiled and run, it returns first the second
- keyboard code that is scanned. For example, if the F5 key is pressed,
- returning first a null character followed by its extended code, the
- program returns "First: 63 Second: 0." The null character that is
- generated by the keyboard first, is written second.
-
-
- 460. _bios_serialcom Sends and Receives Single Character Data
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr S_QuickC S_QuickASM
- Last Modified: 7-DEC-1989 ArticleIdent: Q47987
-
- Question:
-
- In the "Microsoft C for the MS-DOS Operating System: Run-Time Library
- Reference" manual, _bios_serialcom() is documented as taking an
- unsigned integer as the data byte. Since this is 16 bits (large enough
- for two characters), can I pass two characters (or receive two
- characters) with each call to _bios_serialcom()?
-
- Response:
-
- No, _bios_serialcom() sends (and receives) character data. Two
- characters cannot be sent (or received) with one call because the
- function call is a simple interface to the BIOS interrupt 0x14. This
- interrupt expects the data to be sent (or received) to be in the AL
- register (an 8-bit register). Therefore, the data is limited to 8
- bits, even though the function requires an unsigned integer as the
- data parameter.
-
- The parameter is an unsigned integer because the _bios_serialcom()
- function also uses the data parameter in initialization and status
- checks. In the send (and read) functions of the interrupt, however,
- only a single byte in the low-order 8 bits of the unsigned integer
- passed as the data parameter are sent. For more information, see
- interrupt 0x14 in "IBM ROM BIOS" by Ray Duncan. This book clarifies the
- interrupt calls that are being made, and what is actually passed to
- the machine.
-
- This lack of clarification for _bios_serialcom() occurs in the
- documentation for C Versions 5.00 and 5.10; in Microsoft QuickC
- Versions 1.00, 1.01, 2.00, and 2.01; and the QuickC with
- QuickAssembler on-line help Version 2.10.
-
-
- 461. Possible Causes of "'__iob' : Unresolved External"
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | SR# G890807-24188 _iob iob
- Last Modified: 16-JAN-1990 ArticleIdent: Q47990
-
- When linking with CRTLIB.LIB, the problems listed below can cause the
- following message when linking a main program to the C run-time DLL
- created as described in the MTDYNA.DOC file supplied with the C
- Compiler Version 5.10:
-
- .... error : L2029 : '__iob' : unresolved external
-
- The problems that can cause this message include the following:
-
- 1. Compiling with the wrong include files. Typically, this involves
- compiling without the /I option, as described in MTDYNA.DOC.
-
- 2. Compiling without defining the symbol DLL. DLL must be defined in
- any program that calls the C run-time library DLL.
-
- These options, as well as other important information, are covered in
- Section 5.2 of MTDYNA.DOC.
-
-
- 462. Using a Wildcard Argument with the remove() Function
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 16-JAN-1990 ArticleIdent: Q48090
-
- Question:
-
- I'm using the remove() function to delete my files, but when I pass
- the wildcard as an argument, the function does not delete any files.
- Is there any why I can use the remove() function to delete all the
- files in the directory when I specify it to?
-
- Response:
-
- Yes; use the _dos_findfirst and _dos_findnext functions to search for
- each file and then use the remove() function to delete each file. The
- following example demonstrates how to write a code equivalent to
- remove("*.*"):
-
- Code Example
- ------------
-
- #include <stdio.h>
- #include <dos.h>
- #include <io.h>
-
- main ()
- {
- struct find_t c_file;
- char fn[12];
-
- printf ("Enter file to delete: ");
- scanf ("%s", fn);
-
- /* This code section will delete all the files in the directory. */
- if (strcmp(fn, "*.*") == 0) {
- _dos_findfirst ("*.*", _A_NORMAL, &c_file);
- do {
- remove (c_file.name);
- } while (_dos_findnext (&c_file) == 0);
- }
- else
-
- /* This section will delete only one file. */
- if (remove (fn) == -1)
- printf ("File not found\n");
- else
- printf ("File successfully deleted\n");
- }
-
-
- 463. Mixed-Language Examples for Calling Pascal Are Incorrect
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr H_MASM S_PasCal
- Last Modified: 16-JAN-1990 ArticleIdent: Q48251
-
- In the "Microsoft Mixed-Language Programming Guide" provided with C
- Versions 5.00 and 5.10, MASM Versions 5.00 and 5.10, and Pascal
- Version 4.00, there is a sample Pascal module that is incorrect. This
- module is called Pfun and it appears in three different sections of
- the manual. Pfun can be found in the following locations:
-
- 1. Page 30, Section 2.5.2 "Calling Pascal from Basic -- Function Call"
-
- 2. Page 44, Section 3.5.2 "Calling Pascal from C -- Function Call"
-
- 3. Page 57, Section 4.5.2 "Calling Pascal from FORTRAN -- Function Call"
-
- If the Pascal source code shown on these pages is compiled, the
- following errors occur:
-
- 21 7 begin
- = 22 8 Fact := Fact * n;
- 8 --------------^Warning 171 Insert (
- 8 ----------------^268 Cannot Begin Expression Skipped
- 8 -------------------^Warning 155 ; Assumed ,
- 8 -------------------^257 Parameter List Size Wrong Begin Ski
-
- To get the code to compile correctly, all of the incorrect references
- to Fact must be removed and replaced by a temporary variable. The
- following source code contains the necessary changes to the Pfun
- module so that it will compile and run without any errors:
-
- module Pfun;
- function Fact (n : integer) : integer;
-
- {Integer parameters received by value, the Pascal default. }
-
- var temp : integer;
-
- begin
- temp := 1;
- while n > 0 do
- begin
- temp := temp * n;
- n := n - 1;
- end;
- Fact := temp;
- end;
- end.
-
- Note: There is an incorrect reference to the errors in the Fact
- function in the Pascal Version 4.00 README.DOC file. This correction
- does not work.
-
-
- 464. Mixed-Language Examples for Calling Fortran Are Incorrect
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr H_MASM S_PasCal
- Last Modified: 16-JAN-1990 ArticleIdent: Q48424
-
- In the "Microsoft Mixed-Language Programmer's Guide" provided with C
- Versions 5.00 and 5.10, MASM Versions 5.00 and 5.10, and Pascal
- Version 4.00, the C and Pascal sample programs for calling a FORTRAN
- subroutine are incorrect. The documentation error appears in two
- different sections of the manual. The documentation error may be found
- in the following locations:
-
- 1. Page 40, Section 3.4.1, "Calling FORTRAN from C -- Subroutine Call"
-
- 2. Page 67, Section 5.5.1, "Calling FORTRAN from Pascal -- Subroutine
- Call"
-
- The source code in the manual compiles, but when linked with the
- FORTRAN subroutine, the following error occurs:
-
- LINK : error L2029: Unresolved externals:
-
- MAXPAR in file(s):
- FACT.OBJ(fact.c)
-
- There was 1 error detected
-
- This error occurs because the FORTRAN subroutine has a different name
- than is used by the calling programs (maxparam instead of maxpar). To
- get the two modules to link correctly, the following changes must be
- made:
-
- In C (Page 40), change
-
- extern void fortran maxpar (int near *, int near *);
- .
- .
- maxpar (&a, &b);
-
- to the following:
-
- extern void fortran maxparam (int near *, int near *);
- .
- .
- maxparam (&a, &b);
-
- In Pascal (Page 67), change
-
- procedure Maxpar (var i,j : integer) ; extern;
- .
- .
- Maxpar (a,b);
-
- to the following:
-
- procedure Maxparam (var i,j : integer) ; extern;
- .
- .
- Maxparam (a,b);
-
-
- 465. Macros ceil and floor Incorrectly Listed As Functions
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 16-JAN-1990 ArticleIdent: Q48431
-
- Page 94, Section 3.3.13 of the "Microsoft C 5.1 Optimizing Compiler
- User's Guide" incorrectly lists ceil and floor as functions that have
- intrinsic forms.
-
- As correctly noted in the "Microsoft C 5.1 Optimizing Compiler
- Run-Time Library Reference" on Pages 152 and 270, ceil and floor are
- macros defined in the include file MATH.H.
-
-
- 466. The Interrupt Attribute Pushes Registers on the Stack
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 16-JAN-1990 ArticleIdent: Q48444
-
- The interrupt attribute can be applied to a function to tell the
- compiler that the function is an interrupt handler.
-
- When an interrupt function is called, all registers (except SS) are
- saved on the stack. Examining the assembler code the compiler
- generates for an interrupt handler could cause confusion. When
- compiling without the /G1 or /G2 switch (these switches inform the
- compiler to generate 186 or 286 code accordingly) the assembler code
- appears as it should, however, when using one of the two
- aforementioned switches, the assembler output may be deceiving in that
- the registers appear as though they are not being saved on the stack
- as advertised.
-
- This potential misinterpretation results from the use of the PUSHA
- instruction, which does not exist in the 8086 instruction set, but
- does apply to the 80186 and more recent sets. The PUSHA instruction
- pushes the general purpose registers onto the stack in the following
- order: AX, CX, DX, BX, SP, BP, SI, DI. For further information
- regarding the PUSHA instruction, you should consult an reference
- manual for Intel's 80x86-based assembly.
-
- The text that follows displays two partial assembler listings of an
- interrupt handler called foo. The second case demonstrates the usage
- of the 186, 286, 386 specific instruction PUSHA (for load all).
-
- /* Without G1 or G2 */
-
- _foo PROC FAR
- push ax
- push cx
- push dx
- push bx
- push sp
- push bp
- push si
- push di
- push ds
- push es
-
- /* With G1 or G2 */
-
- _foo PROC FAR
- pusha ; This pushes all general purpose registers
- push ds ; for the 80186 processors and above.
- push es
-
-
- 467. How to Find the Total Stack Size from within a Program
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | SR# G890831-26299
- Last Modified: 16-JAN-1990 ArticleIdent: Q48686
-
- Question:
-
- How can I find the total size of the stack from within my program?
-
- Response:
-
- The program below calculates the total size of the stack. Note that
- this works slightly differently for protected-mode and bound programs
- than for real-mode programs. (Normally, the two-byte difference
- shouldn't be important.)
-
- The symbol "_end" is declared just below the lowest location in the
- stack. At any given time, the amount of space left on the stack is SP
- - offset _end. (The C program doesn't use the underscore because C
- automatically prepends an underscore to all identifiers.)
-
- The start-up code stores the maximum (initial) value of SP in the
- variable __atopsp. (The program below uses only one underscore rather
- than two for the reason described in the previous paragraph.)
-
- Default stack checking on function entry fails when the amount left is
- less than 256 bytes for DOS, or less than 512 bytes for OS/2. When
- stack checking fails, you receive the following run-time error:
-
- run-time error R6000
- - stack overflow
-
- The program to calculate the total stack size follows:
-
- #include <stdio.h>
-
- extern unsigned int end;
-
- extern unsigned int _atopsp;
-
- void main(void)
- {
- unsigned stksize;
-
- stksize = _atopsp - (unsigned)&end + 2;
- /* don't add 2 for protected-mode or bound programs */
-
- printf("Total stack size is %u bytes (%x hex bytes)\n",
- stksize, stksize);
- }
-
-
- 468. int86x() and int86() Trap for Interrupts 25h, 26h
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 16-JAN-1990 ArticleIdent: Q48744
-
- Interrupts 25h (absolute disk read) and 26h (absolute disk write)
- require special handling when being used because they leave the CPU
- flags on the stack upon termination.
-
- Functions int86x() and int86() work reliably with these interrupts.
- The int86() functions trap for these two interrupts, and take care of
- the stack appropriately. Use one of the int86() functions to make
- these calls as you would any other DOS interrupt call. You need take no
- extra precautions with these interrupts.
-
- The following example demonstrates the straight-forwardness of the
- function call:
-
- #include <stdio.h>
- #include <dos.h>
- #include <malloc.h>
-
- /***** WARNING!!!!! ******/
- /* If you change the following line so that DRIVE_A is assigned a 2 or
- above, you could destroy data on your hard drive. This test program
- segment was written to read and write from the floppy disk A: */
- #define DRIVE_A 0 /* 0=A, 1=B, 2=C, etc. */
- #define ONE_SECTOR 1
- #define ABS_WRITE 38 /* Decimal value of int call */
- #define ABS_READ 37 /* Decimal value of int call */
- unsigned int far *out; /* Pointer to Data to be output */
- unsigned int far *input; /* Pointer to Data Transfer Area */
- unsigned int output; /* Data to be output */
- union REGS inregs, outregs;
- struct SREGS segregs;
-
- void main(void) {
- out = &output;
- input = (unsigned int far *) malloc (1024 * sizeof(unsigned int));
- *out = 11;
- inregs.h.al = DRIVE_A; /* Write to Drive A */
- inregs.x.cx = ONE_SECTOR; /* Write one sector only */
- inregs.x.dx = 3; /* Logical sector 3 */
- segregs.ds = FP_SEG(out); /* Get Seg address of output */
- inregs.x.bx = FP_OFF(out); /* Get Offset of output */
- outregs.x.ax = 0; /* No error */
- int86x (ABS_WRITE, &inregs, &outregs, &segregs);
-
- inregs.h.al = DRIVE_A; /* Read to Drive A */
- inregs.x.cx = ONE_SECTOR; /* Read one sector only */
- inregs.x.dx = 3; /* Logical sector 3 */
- segregs.ds = FP_SEG(input); /* Get Seg address of buffer */
- inregs.x.bx = FP_OFF(input); /* Get Offset of buffer */
- outregs.x.ax = 0; /* No error */
- int86x (ABS_READ, &inregs, &outregs, &segregs);
- printf ("%u was read from drive A: \n", *input);
- }
-
-
- 469. Potential Problems with Identifiers Over 31 Characters
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuicKASM
- Last Modified: 16-JAN-1990 ArticleIdent: Q48790
-
- The #define statement in Microsoft C accepts identifiers up to 31
- characters. The compiler truncates identifiers over 31 characters, and
- on warning level 1 or greater, produces the following warning message:
-
- warning C4011: identifier truncated to '<truncated identifier>'
-
- This can cause potential problems if two or more identifiers are
- identical up to the 31st character. If this is the case, the following
- warning message appears for each additional #define that is identical
- when truncated (on warning levels 1 or greater):
-
- warning C4005: '<truncated identifier>' : redefinition
-
- All of these identifiers are assigned the value of the last identifier
- that was identical when truncated.
-
- This information also applies to QuickC Versions 1.01, 2.00, 2.01 and
- QuickAssembler Version 2.01.
-
-
- 470. Include Filenames More Than Eight Characters Are Truncated
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 16-JAN-1990 ArticleIdent: Q48792
-
- When given a filename that is more than eight characters, the file
- system under MS-DOS truncates the filename to eight characters.
- Because of this, the following include statement
-
- #include <gefildefish.h>
-
- looks for the following header file to resolve the reference:
-
- gefildef.h
-
- As long as the file gefildef.h is found on the disk, no error or
- warning message is displayed.
-
- Under OS/2 Version 1.10, however, the file system does not truncate
- names, but filenames with more than eight characters are not used.
- Therefore, the following fatal error message appears when specifying
- an include file with more than characters:
-
- C1015: cannot open include file '<filename>'
-
- This problem also occurs in QuickC Versions 1.01, 2.00, 2.01 and
- QuickAssembler Version 2.01.
-
-
- 471. exec() and spawn() with P_OVERLAY Ignore Maximum Allocation
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 16-JAN-1990 ArticleIdent: Q48793
-
- Exec() and spawn() with P_OVERLAY ignore the maximum memory allocation
- information in the .EXE file header. If you exec or spawn with
- P_OVERLAY, a program whose maximum allocation is set equal to the
- minimum allocation (through EXEMOD or the LINK option /CP:1), the
- program is allocated the full 64K DGROUP.
-
- The effective maximum allocation for any exec'ed (or spawn'ed with
- P_OVERLAY) program is 0xffff (whatever DOS has available), regardless
- of the maximum allocation number in the program's .EXE header. When
- run from the DOS prompt, the maximum allocation information of the
- same program is honored.
-
- This behavior occurs because the exec() and spawn() with P_OVERLAY
- functions do not invoke COMMAND.COM, which looks at the minalloc and
- maxalloc fields in the exe header. This is expected behavior for
- exec() and spawn() with P_OVERLAY in C Versions 4.00, 5.00, and 5.10,
- and QuickC 1.00, 1.01, 2.00, and 2.01 (QuickAssembler), as documented
- in the C 5.10 README.DOC on Line 1275, in the run-time library notes
- section for the exec() functions.
-
- Alternatives
- ------------
-
- Instead of calling a program with exec() or spawn() with P_OVERLAY,
- call COMMAND.COM with the desired child program as an argument using
- exec() or spawn() with P_OVERLAY, as follows:
-
- spawnl(P_OVERLAY,"c:\\command.com","command.com","/c child.exe",NULL);
-
- COMMAND.COM then loads your application as if it was from the DOS
- prompt. Note, however, that the COMMAND.COM shell itself requires
- approximately 4K. Also, consecutive exec() or spawn() with P_OVERLAY
- calls using this method run additional shells of COMMAND.COM,
- accumulating one 4K shell per generation, as illustrated below:
-
- +------+ +------+ +------+ +------+
- | P1 |--> |__P2__|--> |__P3__|--> |__P4__|
- +------+ | .COM | |_.COM_| |_.COM_|
- +------+ | .COM | |_.COM_|
- +------+ | .COM |
- +------+
-
- Another option is to call your program with the system() function, but
- this does not overlay the child process.
-
- Additional reference words: execl execle execlp execlpe execcv execve
- execvp execvpe spawnl spawnle spawnlp spawnlpe spawnv spawnve spawnvp
- spawnvpe
-
-
- 472. Newline Character (\n) Is Equivalent to ASCII Linefeed (0x0A)
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickAsm
- Last Modified: 16-JAN-1990 ArticleIdent: Q48885
-
- The newline character in Microsoft C (\n) is equivalent to the ASCII
- linefeed character (hex 0A). Thus, for files opened in text mode,
- CR/LF pairs are read in as newline characters, and newline characters
- are written as CR/LF.
-
- This information applies to STDIN, STDOUT, and STDERR, which are
- opened in text mode by default.
-
- When using strtok() to extract tokens separated by CR/LF in a file
- opened in text mode, only \n must be used as a token delimiter.
-
-
- 473. Cast of Float to Long Truncates Value to 1 Less Than Expected
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickAsm
- Last Modified: 7-DEC-1989 ArticleIdent: Q48928
-
- Question:
-
- When I cast a float to a long integer, the result is one less than the
- expected value.
-
- The following is an example:
-
- double i, j;
- char r[] = "16.49";
-
- i = atof(r) * 100;
- printf ("%ld\n", (long)i);
-
- What causes this code to produce 1648 instead of 1649?
-
- Response:
-
- When a float or double value is converted to an integer number, the
- value is truncated. You are getting 1648 and not 1649 because the
- float value is not stored exactly as 1649.0000. The value is stored as
- 1648.99999...999. When you cast the double value to a long integer,
- the number is truncated at the decimal point to 1648.
-
- This is expected behaviour for C Version 5.10, QuickC Versions 1.01
- and 2.00, and QuickC with QuickAssembler Version 2.01.
-
- The workaround for this constraint is to add 0.5 to the double value
- before converting to an integer value. The following code produces the
- correct result:
-
- Sample Code
- -----------
-
- #include <stdio.h>
- #include <math.h>
-
- double i, j;
- char r[] = "16.49";
-
- main ()
- {
- i = atof(r) * 100;
- printf ("%ld\n", (long)(i + 0.5));
- }
-
-
- 474. qsort() Appears Extremely Slow in Worst-Case Situations
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 16-JAN-1990 ArticleIdent: Q48965
-
- Question:
-
- When using qsort() in a worst-case situation (e.g. the array is
- already sorted in reverse order), the qsort() library routine appears
- to take an extremely long time. Have I done something wrong in my
- program or does a problem exist with Microsoft's qsort() algorithm?
-
- Response:
-
- The qsort() routine that was provided by Microsoft was optimized for
- both speed and stack usage [stack space is important because qsort()
- is heavily recursive]. Therefore, in a worst-case situation, which
- could recurse up to the number of elements in the list, qsort()
- sacrifices speed for stack space. This behavior allows larger lists to
- be sorted without stack overflow problems. Furthermore, Microsoft's
- qsort() routine is very competitive in sorting random files, the type
- of array for which quick sorts are designed.
-
- If used judiciously, Microsoft's qsort() is a very effective sort
- routine. In worst-case situations, Microsoft's qsort() is slower than
- some other sorting routines, but successfully sorts larger arrays
- without stack overflow problems.
-
- Microsoft is researching this problem and will post new information as
- it becomes available.
-
-
- 475. Confusion Regarding the /Zs Switch
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickAsm
- Last Modified: 16-JAN-1990 ArticleIdent: Q48967
-
- The /Zs switch instructs the compiler to scan your code and check for
- syntax errors. This switch does not generate any code. Switches that
- assume code will be generated do not have any effect when used in
- conjunction with /Zs.
-
- Therefore, if you are using the /Zs switch and are unaware of the fact
- that it does not generate any code, it may appear that other switches,
- such as the /Fa switch, which generates an assembly listing, do not
- function.
-
-
- 476. DOS APPEND Is Not Utilized with access() Function
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC
- Last Modified: 16-JAN-1990 ArticleIdent: Q49006
-
- The Microsoft C run-time library function, access(), determines
- whether or not a specified file exists and can be accessed in read
- and/or write mode(s). The access() function searches the current
- working directory for the particular file or the directory specified
- by a path to the file.
-
- The DOS APPEND command, which establishes a search path for data files
- and works similarly to the PATH environment variable, appears to be a
- way to assist access() in finding files outside the current working
- directory without having to supply a path. However, the APPEND command
- does not search the data path when locating a file to be used by the
- access() function. Consequently, access() fails when searching for a
- file issued with no path and that is not in the current working
- directory.
-
- As documented in the "Microsoft MS-DOS User's Guide and User's
- Reference" on Page 30, APPEND searches the data path for all files
- with only the following MS-DOS system calls:
-
- Code Function
- ---- --------
-
- 0FH Open File (FCB)
- 23H Get (FCB) File Size
- 3DH Open Handle
- 11H FCB search first (with /x switch only)
- 4EH Handle find first (with /x switch only)
- 4BH Exec (with /x switch only)
-
- The access() function makes an MS-DOS system call to interrupt 21H
- function 43H, which sets and retrieves file attributes. Since this is
- not a system call listed above, APPEND does not perform file
- searching.
-
- The following program illustrates the APPEND limitation. The program
- uses access() to determine whether the file named TEST exists. Assume
- that the TEST data file is not in the current working directory, but
- instead is in a directory called c:\foo, and that the APPEND command
- "APPEND=c:\foo" was issued previously to set the appropriate search
- path.
-
- Sample Program
- --------------
-
- #include <io.h>
- #include <fcntl.h>
- #include <stdio.h>
-
- FILE * stream;
-
- void main( void )
- {
- /* check for existence of TEST fails despite having APPEND set */
- if ((access( "TEST", 0 )) == -1 )
- {
- printf( "file was not found with APPEND set\n\n" );
-
- /* however, fopen() recognizes APPEND for successful access */
- if ((stream = fopen( "TEST", "r")) != NULL )
- printf( "file opened successfully using APPEND" );
- }
- }
-
-
- 477. Declaring a Pointer to a Function: C4071
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickAsm
- Last Modified: 16-JAN-1990 ArticleIdent: Q49064
-
- The following usual method of declaring a pointer to a function
-
- type (*ptr)();
- ptr = function;
-
- causes the following compiler warning when compiling with the "/W3"
- option:
-
- C4071: 'ptr' : no function prototype given
-
- Use one of the following methods to avoid the error message:
-
- 1. Use the warning level flag "/W2" instead of "/W3".
-
- 2. Prototype the function itself and then specify actual parameters
- when declaring the pointer, as follows:
-
- type (*ptr)(parameter_list);
- ptr = function;
-
- Note: The parameter list must be exactly the same parameter list with
- which the function was declared.
-
- The following program compiles and links with NO warnings when
- compiling with the '/W3' warning level flag set:
-
- /* Must have 'stdio.h' to prototype 'printf' */
- #include <stdio.h>
-
- void main (void)
- {
- /* Declare 'fun_ptr' as a pointer to a function */
- int (*fun_ptr)(const char *, ...);
- int other_args;
-
- /* Assign pointer to the specific function, 'printf' */
- fun_ptr = printf;
-
- /* Standard usage in calling environment */
- fun_ptr("format string goes here", other_args);
- }
-
-
- 478. Error in Run-Time Reference to _getcursorposition
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr S_QuickC S_QuickASM
- Last Modified: 16-JAN-1990 ArticleIdent: Q49428
-
- Appendix B of the "Microsoft C Run-Time Library Reference" and
- "Microsoft QuickC Run-Time Library Reference" lists routines that are
- specific to MS-DOS. The lists in both references refer to the
- _getcursorposition routine. The routine referred to should be
- _getcurrentposition.
-
- The error can be found in the C run-time library reference on Page
- 655. The same error is found on Page 655 of the QuickC Versions 1.00
- and 1.01 run-time library reference. This manual is sent upon request
- to QuickC 2.00 or 2.01 customers who desire a hard copy of the
- reference.
-
- The list shown in Appendix B in the manuals is not included in the
- QuickC 2.00 and 2.01 on-line help references.
-
-
- 479. Ftime: C Function -- Documentation Supplement
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickASM docsup
- Last Modified: 17-JUL-1990 ArticleIdent: Q49501
-
- The ftime function takes a pointer to a timeb structure as its only
- parameter and has no return value. Ftime calculates the current time
- and returns it by modifying the timeb structure. The structure
- contains the following elements in the given order:
-
- Name Type Description
- ---- ---- -----------
-
- time time_t(long) The time in seconds since 00:00:00 Greenwich
- mean time, January 1, 1970. This time is
- calculated under MS-DOS by calling Int 21,
- function 2Ah (Get Date), converting the
- results to seconds, and adding the current
- time, which is also converted to seconds.
-
- millitm USHORT Fraction of a second in milliseconds. This
- value is actually not milliseconds on most
- systems. On most IBM PCs and compatibles, the
- clock speed is not fast enough to compute
- milliseconds, or indeed, hundredths of
- seconds. The ftime function calls interrupt
- 21, function 2Ch (under DOS), which returns,
- among other information, the seconds in
- hundredths. The hundredths information is an
- estimation based on the clock speed, which is
- approximately 18.2 ticks per second on most
- PCs. The hundredths value is then multiplied
- by ten to get the millisecond value.
-
- timezone short The difference in minutes, moving westward,
- between Greenwich mean time and local time.
- This is equal to the global variable
- timezone, from a call to the tzset function.
-
- dstflag short This flag is nonzero if daylight savings
- time (DST) is currently in effect for the local
- time zone. This is done by a call to the
- internal function _isindst. This function
- takes a timeb structure as a parameter and
- returns an integer flag. This is the rule for
- years before 1987; a time is in DST if it is
- on or after 02:00:00 on the last Sunday in
- April and before 01:00:00 on the last Sunday
- in October. This is the rule for years
- starting with 1987; a time is in DST if it
- is on or after 02:00:00 on the first Sunday
- in April and before 01:00:00 on the last
- Sunday in October. (See tzset for more
- information on DST.)
-
- Other sources of information include the Version 5.10 "Microsoft C for the
- MS-DOS Operating System: Run-Time Library Reference," Pages 308-9 and
- the ftime function in the "C Run-Time Library Source Routines".
-
-
- 480. sscanf with %i and a Leading 0 Gives Octal Conversion Results
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickASM scanf sscanf fscanf
- Last Modified: 22-NOV-1989 ArticleIdent: Q49573
-
- Question:
-
- Why does sscanf return incorrect results when I use the %i switch, yet
- it returns correct results when I use the %d switch?
-
- Response:
-
- The %i switch has the capability of reading in decimal, octal, and
- hexadecimal numbers. Hexadecimal numbers are specified with the 0x in
- front of the number, while octal numbers are specified with the 0
- (zero) in front of them. If you want only decimal numbers to be read
- in, use the %d switch.
-
- This is expected behavior and occurs with the entire scanf family.
-
-
- 481. Inconsistent Use of fscanf %x.xf Formatting May Produce Errors
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_C S_QuickC
- Last Modified: 17-JUL-1990 ArticleIdent: Q49823
-
- Using the Microsoft C 5.10 run-time library function fscanf() with the
- format specifier %x.xf to read floating-point values usually produces
- undesirable results. This happens especially if the file contains
- floating point information that was not recorded using the same %x.x
- specifier that is being used to read.
-
- This is not a problem with the fscanf() function (see below).
-
- The following code can be used as an example of expected behavior:
-
- #include<stdio.h>
-
- void main( void )
- {
- float a = 3.104f, b = 34.23534f, c = 834.3432f, d = 5968.394f;
- float e = 34253.2f;
- float ar, br, cr, dr, er;
- FILE *stream;
-
- if( (stream = fopen( "file.tst", "a" )) == NULL )
- printf( "ERROR: Unable to open output file" );
- else
- fprintf( stream, "%f,%f,%f,%f,%f\n", a, b, c, d, e );
- fclose( stream );
- if( (stream = fopen( "file.tst", "r" )) == NULL )
- printf( "ERROR: Unable to open input file" );
- else
- /* NOTE: %x.x format specifier */
- { /* | */
- printf("Values: %2.4f, %f, %f, %f, %f\n", a, b, c, d, e );
- fscanf( stream, "%4f,%4f,%4f,%4f,%4f", &ar, &br, &cr, &dr, &er);
- printf("After Read: %f, %f, %f, %f, %f\n", ar, br, cr, dr, er );
- }
- }
-
- The output from the program is as follows:
-
- Values: 3.104000, 34.235340, 834.343201, 5968.394043
- After Read: 3.1000, 0.000000, 0.000000, 0.000000
-
- The unwanted behavior is obvious, as the "Values" above are what is
- contained in the output file "file.tst" and these are definitely not
- the values that are read back in.
-
- However, this is not a problem with the fscanf() function. The first
- value is read in correctly. After the first value is read, the file
- pointer points to the second 0 (zero) in 3.104000. When the second
- value is read, the information in the file does not conform to
- floating-point format, and zeros are read after that. The compiler has
- no way of knowing how far to move the file pointer to get to the next
- value.
-
- If the %2.4f in the fscanf() line in the code above were replaced by
- %f, the program output would be as follows:
-
- Values: 3.104000, 34.235340, 834.343201, 5968.394043
- After Read: 3.104000, 34.235340, 834.343201, 5968.394043
-
- To read truncated or formatted floating-point values from a file, use
- the %f format specifier and modify the values after they are read.
-
-
- 482. Use of the /Gt Switch in C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 7-DEC-1989 ArticleIdent: Q49840
-
- Question:
-
- I am using large memory model and the /Gt switch when programming and
- I still get the message "stack plus data larger than 64K." Could you
- give me some pointers about where data goes when using large model? Do
- heap and stack still remain in DGROUP when I use /Gt?
-
- Response:
-
- What goes out of the default data segment depends on how you use /Gt.
- /Gt alone is the same as /Gt256, which means that ONLY data items of
- size 256 and greater get moved out. If you have a lot of data items
- smaller than that, that data will NOT get moved out. With /Gt256, it
- is still possible that the data left in DGROUP plus the stack could
- exceed 64K.
-
- As the value on the /Gt switch becomes smaller, more and more data
- gets pushed out. /Gt0 pushes all of the data generated by your program
- out. However, it also generates some constants in the logical segment
- _CONST in DGROUP, 2 bytes for each extern or uninitialized variable
- moved. The following classes of variables will generate a 2-byte
- segment address in DGROUP for EACH variable of that class declared
- when /Gt0 is used:
-
- 1. All extern declarations, such as "extern int i;"
-
- 2. All declarations without storage class that are not initialized,
- such as "int i;"
-
- Initialized variables such as "int i = 0;", provided that the sum of
- their sizes is less then 64K, are treated as a group and generate only
- one segment address in DGROUP per module. Therefore, the optimal
- number for minimizing DGROUP space is /Gt3. /Gt3 is better than /Gt0
- for uninitialized and extern variables because /Gt0 will move out 1-
- and 2-byte data elements to the far heap, replacing them with 2-byte
- segment addresses. Not only does this NOT save you space in DGROUP
- V.S. /Gt3, but it will increase the overall size of the executable
- V.S. /Gt3 as you also have to pay 2 bytes in the far heap per data
- element moved. Another reason to use /Gt3 over /Gt0 is that although
- the size of DGROUP will remain the same, /Gt0 will cause character and
- integer data elements to be addressed with far pointers, slowing
- execution. With /Gt0, all that remains in DGROUP is the stack, several
- kilobytes of variables associated with the run-time library, the near
- heap (from which will be allocated some file buffers and the local
- copy of the environment), and the 2-byte segment addresses for data
- items moved out as needed.
-
-
- 483. Installing In-Line 80 x 87 Assembly Instructions
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | docerr appnote
- Last Modified: 16-JAN-1990 ArticleIdent: Q49842
-
- The assembler code on Page 168 of the "Microsoft C Optimizing Compiler
- User's Guide," Version 5.10, is incorrect. When assembled and linked
- with your C application, this code will cause divide by zero and
- overflows to be masked.
-
- This behavior occurs because the code on Page 168 is incomplete. The
- correct code is listed below. Case is important, so assemble with the
- -Mx switch. You should also link with the /NOE switch. This code is
- provided to produce in-line 8087 instructions on FORTRAN Versions 4.x
- and C Versions 5.x.
-
- This application note is also available from Microsoft Product Support
- Services by calling (206) 454-2030.
-
- ;************************************************************************
- ;rmfixups.asm -
- ;
- ; Copyright (c) 1988-1988, Microsoft Corporation. All Rights Reserved.
- ;
- ;Purpose:
- ; Link with rmfixups.obj in order to prevent floating point instructions
- ; from being fixed up.
- ; The case of these names is important so assemble with the -Mx switch.
- ;
- ;*************************************************************************
-
- public FIWRQQ,FIERQQ,FIDRQQ,FISRQQ,FJSRQQ,FIARQQ,FJARQQ,FICRQQ,FJCRQQ
-
- FIDRQQ EQU 0
- FIERQQ EQU 0
- FIWRQQ EQU 0
- FIARQQ EQU 0
- FJARQQ EQU 0
- FISRQQ EQU 0
- FJSRQQ EQU 0
- FICRQQ EQU 0
- FJCRQQ EQU 0
-
- extrn __fpmath:far
- extrn __fptaskdata:far
- extrn __fpsignal:far
-
- CDATA segment word common 'DATA'
- dw 0
- dd __fpmath
- dd __fptaskdata
- dd __fpsignal
- CDATA ends
-
- end
-
-
- 484. Mixing Case of LINK Option Causes Error L1093 or D4002
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 30-NOV-1989 ArticleIdent: Q49871
-
- When specifying linker options from the CL or the QCL command line,
- the word "link" must be all lowercase letters. If the word "link" is
- not all lowercase, the error that occurs is either:
-
- Command line warning D4002 : ignoring unknown flag '-xxxx'
-
- or
-
- LINK : fatal error L1093: xxxx.OBJ : object not found
-
- Note: xxxx is the four letters keyed in after the "/" (forward slash)
- or the "-" (hyphen).
-
- For example, issuing the following command from the MS-DOS or OS/2
- command prompt
-
- cl file.c /Link graphics.lib
-
- produces the following error:
-
- Command line warning D4002 : ignoring unknown flag '-Link'
-
-
- 485. Fread() Can Read More Than 64K at a Time
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 30-NOV-1989 ArticleIdent: Q49872
-
- It is possible to read more than 64K at a time with the fread()
- function by specifying an item size greater than 1 and a count from 1
- to 64K. The resulting number of bytes read will be the product of size
- and count.
-
- The follow code demonstrates how to read a file 200K in length:
-
- /* Must be compiled in huge memory model */
- #include <stdio.h>
-
- char huge buffer[205000];
-
- void main(void)
- {
- FILE *fp;
-
- fp=fopen("testfile.dat","r");
-
- fread(buffer,4,51200,fp); /* 51200*4=204,800 */
-
- /* The value returned from the line above will be the number of
- items read. This number is limited to 64K because it is of
- type size_t. But remember, the total number of bytes read is
- equal to the number of items times the size of each item, which
- is 4 bytes in this case. Therefore, the total bytes read
- is 4 times 51200 or 204,800 bytes. */
- }
-
-
- 486. /Ol Causes Constant Overflow Warnings c4057 c4056
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-JUL-1990 ArticleIdent: Q50251
-
- The following small program, when compiled with loop optimization
- (/Ol), produces the following warnings on the auto-decrement statement
- in the second for loop:
-
- warning C4057: overflow in constant multiplication
- warning C4056: overflow in constant arithmetic
-
- The warnings occur as a side effect of the optimization of the second
- loop. Because the second loop has no functional value, it is optimized
- to the loop-terminating conditions by the compiler. The warnings
- appear to be benign; the program runs as expected. It is recommended,
- however, that if you encounter these errors you generate an assembly
- listing of the code and check the loop for correctness. These warnings
- do not occur in any version of QuickC, QCL, or QuickAssembler.
-
- Sample Code
- -----------
-
- #include<stdio.h>
-
- void main(void)
- {
- unsigned char *p1,
- *start,
- i,
- j;
-
- start = "abcdefgh";
- for(i = 0, p1 = &start[7]; i < 7; i++){
- p1--;
- j = *p1;
- }
- for(i = 0, p1 = &start[7]; i < 7; i++){
- p1--;
- }
- }
-
-
- 487. Calculating Available Memory in Large Model
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickAsm
- Last Modified: 17-JUL-1990 ArticleIdent: Q50297
-
- Question:
-
- I am using large-memory model (C Version 5.10). My program makes a
- call to the _memavl() function to see how much memory is remaining. I
- get back some number (for example, 29,320 bytes). Then I malloc some
- buffers for linked lists, data structures, and place another call to
- _memavl. I get back the same number.
-
- Shouldn't the number get smaller after I have malloc'd memory?
-
- Is there a way for me to find out how much free memory (total) is
- available?
-
- Response:
-
- There are two memory-allocation heaps when you're using large model.
- The near heap is the unused portion of the 64K DGROUP segment. The far
- heap is the unused memory above your program. malloc() uses the near
- heap for small and medium models and the far heap for compact, large,
- and huge models. [You can choose which heap to use by using _fmalloc()
- for the far heap and _nmalloc() for the near heap.]
-
- The _memavl() function measures only the amount of memory available on
- the near heap. Because the near heap is not used in far model until
- the far heap is exhausted, _memavl() does not necessarily change.
-
- To measure the amount of memory available on the far heap, you can use
- the _dos_allocmem() function. (This function calls the DOS
- memory-allocation function.) Pass the function 0xFFFF for the number
- of 16-byte paragraphs to allocate (which is 1 megabyte more memory
- than the machine has) and the address of an unsigned int. When the
- function returns, the unsigned int whose address you passed will
- contain the paragraph size of the largest contiguous block in the far
- heap. To find the number of bytes, multiply this by the 16L, which is
- the size of a paragraph. (Use 16L rather than 16 so that the
- multiplication will be done using long math, avoiding possible
- overflow.)
-
- The total memory available is the sum of the amount available on the
- far and near heaps. For best accuracy, you should do this calculation
- immediately after your program begins.
-
- The following are a few traits of the malloc() allocation family of
- which you should be aware:
-
- 1. malloc() does NOT call DOS for each small allocation. Instead, it
- asks DOS for an 8K block (this size can be set by setting the
- global variable _amblksiz, as described on Page 33 of the
- "Microsoft C Run-Time Library Reference"), then allocate from this
- block. If the requested allocation is more than than 8K, malloc
- allocates enough 8K blocks to fulfill the allocation. Before
- malloc() asks DOS for memory, it first tries to allocate the
- request from memory it already has.
-
- 2. free() NEVER returns memory to DOS. So, if you allocated a block,
- checked the far heap space using _dos_allocmem(), free()'d the
- block and checked again, the amount of memory available to DOS
- would NOT increase on the second call. You can get a better idea of
- how much memory is available by using _heapwalk() to find out how
- much memory is available to malloc() but not to DOS.
-
- Note: halloc() calls DOS directly and frees directly [using hfree()]
- back to DOS.
-
- A program that calculates an estimate of the total amount of free
- memory follows:
-
- Sample Program
- --------------
-
- #include <malloc.h>
- #include <dos.h>
- #include <stdio.h>
-
- void main(void)
- {
- long farheap = 0, total_free, available;
- unsigned farparaavail;
- struct _heapinfo hinfo;
- int heapstatus;
-
- /* Calculates the total memory available in the far heap */
-
- hinfo._pentry = NULL;
- while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
- if (!hinfo._useflag)
- farheap += hinfo._size;
-
- /* _dos_allocmem will return the maximum block size available */
- /* _memavl() will return the maximum memory in the near heap */
-
- _dos_allocmem(0xFFFF, &farparaavail);
- available = (long)farparaavail * 16L + _memavl();
-
- /* Total memory available for allocation */
-
- total_free = farheap + available;
- printf("Total memory available is about %ld bytes\n", total_free);
- }
-
- The total memory calculated in the far heap may not be in a contiguous
- block. To see whether or not memory has been fragmented, add the
- following line to the while loop:
-
- printf ("%6s block at %p of size %4.4X\n,
- (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
- hinfo._pentry, hinfo._size);
-
- To see how fragmented the near heap is, change the _heapwalk() in the
- while statement to _nheapwalk(). This forces the function to do a heap
- walk on the near heap. The _heapwalk() defaults to the following:
-
- _fheapwalk in Compact and Large model
- _nheapwalk in Medium and Small model
-
-
- 488. atexit() Returns Zero if Successful
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER| | docerr S_QuickC
- Last Modified: 30-NOV-1989 ArticleIdent: Q50334
-
- Question:
-
- The "Microsoft C for the MS-DOS Operating System: Run-Time Library
- Reference" has conflicting statements regarding the return code from
- atexit(). What is the proper return code?
-
- Response:
-
- There is an error in the run-time library reference for the atexit()
- function (Page 124) under DESCRIPTION. The correct return values are
- described in the RETURN VALUE section. atexit() should return a value
- of zero (0) if successful and nonzero (-1) on error.
-
-
- 489. Passing a Stream File Pointer (FILE *) Between DLLs
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 17-JUL-1990 ArticleIdent: Q50336
-
- Question:
-
- Regarding single-thread DLLs built with the C 5.10 single-thread
- DLL support library LLIBCDLL.LIB:
-
- My main() function calls a function in my first DLL, which fopen()s a
- buffered stream file. The function in my first DLL calls a function
- in my second DLL, passing the stream pointer (FILE *) as an argument.
- When the function in my second DLL attempts to fread() the stream for
- the first time (which causes the allocation of the stream buffer), a
- General Protect fault (segment violation Trap 13 or 0xD) occurs. What
- went wrong, and how can I work around the problem?
-
- Response:
-
- This procedure cannot be done with LLIBCDLL-created DLLs because the
- second DLL has no way to know where the internal C run-time library
- data structures are, which in this case would be the data structures
- for the file stream that was opened in the first DLL.
-
- To share file streams between DLLs or between an .EXE and DLLs, use
- the dynamically linked, multithread support C run-time function
- CRTLIB.DLL. The correct way to do this is to have one of your DLLs
- export a version of the fread() function and/or fopen() function. The
- fopen() and fread() that get called must be in the same DLL.
-
-
- 490. Internal Compiler Error: ctypes.c:1.107, Line 474
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 30-NOV-1989 ArticleIdent: Q50337
-
- The program below generates the following error when compiled with the
- default command-line options under the Microsoft C optimizing compiler
- Version 5.10:
-
- intr.c(12) : fatal error C1001: Internal Compiler Error
- (compiler file '@(#)ctypes.c:1.107', line 474)
- Contact Microsoft Technical Support
-
- The following program demonstrates the internal compiler error:
-
- #define interrupt_number = 0x62 /* any number will do */
-
- struct interface {
- int counter;
- char signature[8];
- } far interface;
-
- void far*far*interrupt_vector = ( void far * )0L;
-
- int main( void )
- {
- /* offending line--invalid */
- interrupt_vector[interrupt_number] = interface;
-
- /* replace with this line */
- // interrupt_vector[interrupt_number] = &interface;
- }
-
- The program is not syntactically valid: the offending line attempts to
- assign a structure (rather than a pointer to the structure) to a void
- function pointer.
-
- Modifying the offending line of code to a pointer rather than a
- structure [i.e., using the "address of" operator ("&") on the
- interface structure] eliminates the internal compiler error and makes
- the program correct.
-
-
- 491. C and Pascal Mixed Language: Declare C Libraries First
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_PASCAL S_LINK
- Last Modified: 30-NOV-1989 ArticleIdent: Q50703
-
- When doing mixed language programming with C Version 5.10 and Pascal
- Version 4.00, be sure to use the /NOD and /NOE linker switches, and
- then specifically link with the C libraries before the Pascal
- libraries. This will prevent the linker from finding multiply defined
- symbols.
-
- The linker will often report error L2025 when linking with the Pascal
- library first, depending on what functions are called from C. The
- printf() function is one example of a run-time function that will
- cause this problem. The problem occurs because some of the low-level
- routines involved in both libraries have the same name.
-
- The following example typifies the problems encountered:
-
- For instance, say that the Pascal library contains an object module
- with a routine called A, and the C library contains an object module
- with routine A as well as routine B.
-
- Furthermore, suppose the Pascal code makes a call to the A library
- routine and the C code makes a call to the B library routine.
-
- If the Pascal libraries are linked first, the A .OBJ will be found in
- the Pascal library, then the A and B .OBJ will be brought in from the
- C library to resolve the call to B. This results in the linker
- receiving two copies of routine A, which causes the error. By linking
- the C library first, only the one object module (with both A and B)
- will be found, and the symbol will not be multiply defined.
-
-
- 492. Preprocessor Condenses Multi-Line Macro Invocations
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-JUL-1990 ArticleIdent: Q50341
-
- The preprocessor of the Microsoft C Optimizing Compiler versions 5.00
- and 5.10 does not preserve the source code structure of macro
- invocations upon expansion. Preprocessor macro expansion is carried
- out on one line at a time, in a left to right fashion, until the
- end-of-line is reached. Thus, when multiple-line macro invocations are
- expanded, they are converted into a single line of code.
-
- The following example defines a simple macro and displays this
- conversion of multi-line macro invocations:
-
- #define macro( arg1, arg2, arg3 ) arg1 + arg2 + arg3
-
- Source Code Preprocessor Listing
- _____________ ____________________
-
- value = macro ( param1, value = macro( param1 + param2 + param3 );
- param2,
- param3 );
-
- Note that the preprocessor listing replaces the three lines of code
- in the source file with only one line. As a result, the line numbers
- between the two files are different because the preprocessor does not
- perform any line number adjustment.
-
- This may cause problems if one must compile preprocessor listings to
- avoid errors generated by .C source files (i.e., insufficient heap
- space). When the preprocessor listing is compiled, the subtle side
- effect becomes more obvious in the form of discrepancies between
- original source-code line numbers and line numbers associated with
- compiler errors or debugger maps. This result can make debugging
- original source code difficult and can be a general nuisance when
- trying to locate erroneous lines in source code indicated by the
- compiler.
-
- The #line directive and the __LINE__ predefined macro can be used to
- redefine preprocessor listing line numbers and eliminate such
- differences. To compensate for the preprocessor single-line expansion
- of macro invocations, place the directive "#line __LINE__" in the
- source code line following the macro invocation.
-
- The #line directive, which accepts an integer constant as an argument,
- instructs the preprocessor to change the compiler's internally stored
- line number to the integer argument specified. The __LINE__ macro,
- which is supplied as the argument to the #line directive, evaluates to
- the current line number generated during preprocessing. Working
- together, they force the compiler to generate consistent line numbers
- between the the source file and the preprocessor listing.
-
- The program below illustrates the macro expansion behavior of the C
- preprocessor and how it can be modified to generate
- line-number-compatible source and preprocessor listings.
-
- /* TEST.C */ | /* TEST.I */
- |
- /*1*/ #define sum( a,b,c) a+b+c | /*1*/ #define sum(a,b,c) a+b+c
- /*2*/ | /*2*/
- /*3*/ void main( void ) | /*3*/ void main( void )
- /*4*/ { | /*4*/ {
- /*5*/ int i; | /*5*/ int i;
- /*6*/ i = sum( 1, | /*6*/ i = sum( 1, 2, 3 );
- /*7*/ 2, | /*7*/ /* #line __LINE__ */
- /*8*/ 3 ); | /*8*/ i = 100000;
- /*9*/ /* #line __LINE__ */ | /*9*/ }
- /*10*/ i = 100000; | /*10*/
- /*11*/ } | /*11*/
- |
-
- When the program, TEST.C, above is compiled under warning level three,
- a data conversion warning is generated for line 10, indicating
- overflow of the integer variable i. TEST.C is then run through the
- preprocessor using the /P compiler option, where TEST.I (above) is
- generated. Compiling TEST.I under warning level three generates the
- same data conversion warning, but on line 8. The line number
- difference between TEST.C and TEST.I is quite obvious.
-
- By uncommenting line 9 in the TEST.C, both the source file and
- preprocessor listing contain consistent line numbers following the
- macro invocation because the line number is reset to the proper value
- (seven) after the preprocessor pass.
-
-
- 493. mktemp() Creates a Maximum of 27 Unique Filenames
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC docerr
- Last Modified: 30-NOV-1989 ArticleIdent: Q50351
-
- It is unclear in the documentation for the mktemp() function in the
- Version 5.10 "Microsoft C Optimizing Compiler for the MS-DOS Operating
- System Run-Time Library Reference" (Page 432) exactly how many
- filenames mktemp() creates. The reference states the following:
-
- When creating new names, mktemp uses, in order, "0" and the
- lowercase letters "a" to "z".
-
- This is correct; however, the documentation fails to mention that
- these are the only filenames that are created. Any further calls to
- mktemp (after "z" has already been placed in the template) fail.
- Therefore, this limits the number of unique filenames to 27.
-
-
- 494. Compiling isatty() Sample Program Gives C2146: Syntax Error
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | DOCERR
- Last Modified: 30-NOV-1989 ArticleIdent: Q50704
-
- On Page 376 of the "Microsoft C Run-Time Library Reference" for C
- Versions 5.00 and 5.10, the sample program for the function isatty()
- will generate a syntax error when compiled. The zero in the printf()
- statement should be changed to a double quotation mark (i.e., %s0
- should be %s"). The following is the printf() statement with the
- correct syntax:
-
- printf ("Is stdout redirected? %s", interactive ? "no" : "yes");
-
-
- 495. Run-Time Routines Assume That Direction Flag Is Clear in C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | DOCERR S_QUICKC S_QUICKASM
- Last Modified: 30-NOV-1989 ArticleIdent: Q50712
-
- The C run-time routines assume that the direction flag is cleared. If
- you are using other functions with the C run-time functions, you must
- ensure that the other functions leave the direction flag alone or
- restore it to its original condition. Expecting the direction flag to
- be clear upon entry makes the run-time code faster and more efficient.
-
- The run-time functions that use the direction flag include the string
- manipulation and buffer manipulation routines.
-
- This is documented on Page 365 of the "Microsoft Macro Assembler
- Programmer's Guide," Versions 5.00 and 5.10:
-
- Under DOS, the direction flag will normally be cleared
- if your program has not changed it.
-
- This information is not included in the C 5.10 or QuickC 2.00 or 2.01
- manuals.
-
-
- 496. R6009 Not Enough Space for Environment -- Possible Workarounds
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickasm s_quickc
- Last Modified: 21-FEB-1990 ArticleIdent: Q50714
-
- The "Not Enough Space For Environment" error is caused when a program
- successfully loads into memory and then attempts to load a copy of the
- environment and the argument list into the near heap. If the near heap
- does not have enough room for one or the other, or both, R6009 is
- generated.
-
- In standard Microsoft C programs, the functions _setargv and _setenvp
- attempt to set up the argument vector and the environment vector,
- respectively. Both of these vectors are allocated in the near heap. If
- the program has a full or nearly full near heap, the vectors will not
- be set up, thereby giving the error.
-
- A few ways to get around the problem are as follows:
-
- 1. Lower the amount of environment space, with the following statement
- in the CONFIG.SYS file. This assumes that environment space is
- being allocated.
-
- shell=command.com /p /e:xxxx
-
- 2. Use the large memory model when compiling in conjunction with the
- /Gt switch to get some of the global data out of DGROUP, thus
- freeing up room for the environment and/or the argument list.
-
- 3. If there is no need for command line arguments, _setargv can be
- rewritten as follows:
-
- _setargv() {}
-
- 4. If there is no need for a copy of the environment, and if the
- spawn or exec function is not needed, _setenvp can be rewritten
- as follows:
-
- _setenvp() {}
-
- For more information on workarounds 3 and 4, see Section 5.2.2,
- "Suppressing Command Line Processing," in the C user's guide.
-
-
- 497. No Compiler Errors Produced When Assigning to Missing struct
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 30-NOV-1989 ArticleIdent: Q50732
-
- Code that assigns a value to a nonexistent structure compiles without
- warning or error in Microsoft C 5.10 and QuickC Versions 2.00 and
- 2.01. This is correct behavior.
-
- Note that dereferencing a pointer to an undefined structure, or
- attempting to use a field will produce errors. In general, you are
- allowed to make a reference to an undefined struct as long as the
- operation doesn't have to know the size of that struct or the names of
- its fields. This method of declaration is commonly used in linked
- lists.
-
- void main (void)
- {
- struct non_existant *ptr; // legal
- struct x{
- struct x *previous; // legal, note that struct x is
- struct x *next; // not yet defined
- }
- .
- .
- .
- .
- }
-
-
- 498. Huge Indirection May not Cross Segment Boundaries
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC
- Last Modified: 30-NOV-1989 ArticleIdent: Q50733
-
- Microsoft C will never generate an array element that spans a segment
- boundary. If a customer generates a scenario where this situation
- occurs, Microsoft C will generate incorrect addresses for the element
- that crosses the segment boundary. Placing elements such that they
- could cross a segment boundary is an incorrect coding technique, not a
- problem with Microsoft C and huge pointer addressing.
-
- For instance, if a huge character buffer has been allocated and
- structure data has been copied to this buffer, it is possible to
- access this data in structure format by first setting a huge pointer
- to the address of the structure you want and then specifying the huge
- pointer followed by the structure pointer operator (->) and the name
- of element you want to access.
-
- However, if the structure you are looking at crosses a segment
- boundary, then the indirection will fail. If the element of the
- structure you are referencing is in another segment, your pointer will
- usually end up offsetting by the correct number of bytes, but in the
- current segment and not the next segment.
-
- Code Example
- ------------
-
- char huge buffer[70000]; /* Any huge buffer larger than 64K */
- struct x { int x,y,z; }; /* Any structure */
-
- /* Assume that buffer has been filled with many structures of type x.
- Since the structures were put into the buffer via byte copy, it
- is very likely that one of the structures will cross over the segment
- boundary. */
-
- struct x huge *test_ptr; /* A huge pointer to x */
-
- test_ptr = (struct x huge *)(buffer+( 65536 - sizeof(struct x) ) );
-
- /* test_ptr is now equal to some offset into huge character buffer.
- It is assumed that the user has given test_ptr a legitimate address
- of a structure that is contained in the buffer in an attempt to access
- that structure. */
-
- test_ptr->z = 5;
-
- /* The line above will create an incorrect address for the element z if
- z is in a segment other than the one specified by the huge pointer.
- This address will probably end up as the correct offset but in the
- same segment because, although the pointer is huge, it still will not
- compute the segment when used with indirection. This is also why
- huge structure arrays are padded and why huge arrays larger than
- 128K must have elements whose size is a power of two. */
-
- Note: This problem can avoided by simply creating a huge array of
- structures instead of characters. The compiler will take care of
- padding the array so that an array element (a structure) will not
- cross a segment boundary.
-
- This would seem to be a bug in the compiler since the huge pointer
- cannot access data beyond a segment boundary. The situation where an
- array element crosses a segment boundary would never be generated by
- Microsoft C, however. Accordingly, the huge pointer arithmetic does
- not account for such a situation. This is not a bug in the compiler,
- but an error in the code.
-
-
- 499. Graphics Mode: Getting More Than One Background Color
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER| | S_QuickC S_QuickASM
- Last Modified: 17-JUL-1990 ArticleIdent: Q50411
- It is not possible to display more than one background color on the
- screen when working in graphics mode. However, it is possible to
- present the illusion of creating different background colors for
- various windows overlaid on top of the current background color. Use
- _rectangle and _floodfill to create the windows, and either _outtext
- or _outgtext to output the text. A common application is the creation
- of a screen similar to the following:
-
- |-----------------------------------------------------------------|
- | |
- | Light Blue Background |
- | |
- | |------------------------| |
- | | | |
- | | Dark Blue | |
- | | Background | |
- | | | |
- | |------------------------| |
- | |
- | |
- |-----------------------------------------------------------------|
-
- This is not difficult. The primary problem is getting around the fact
- that, when using _outtext, the text always outputs on blocks of the
- current background color. The result of this is that inside of your
- dark blue window, you will have text surrounded by borders of light
- blue (not very attractive!). To work around this, you can rely on the
- fact that _floodfill() uses the foreground color as its boundary, and
- not the background color. Therefore, you can set the background and
- foreground color equal to the color of the inner window (Dark Blue
- above), and draw a rectangle with _GFILLINTERIOR to the size of the
- window you desire. Then, change the foreground color with _setcolor().
- Next, you can use _floodfill() from point (0,0) with the boundary
- color set to the same color index as the rectangle. After this, you
- can use _settextcolor() and _outtext to put text in the inner window
- without problem. An sample program, WINDOW.C, can be found in the
- "More Information:" section of this article.
-
- An easier alternative is to use QuickC's fonts. _outgtext does not
- reset the character background to the current background color.
- Instead, it draws the character over any existing images already on
- the screen. Therefore, all that is necessary is to create a filled
- rectangle of the desired size, register and set the desired font, and
- output text to that area of the screen by using _outgtext. An sample
- program, FONTS.C, can be found in the "More Information:" section of
- this article.
-
- -----------------------------------------------------------------------
- /* WINDOW.C: A sample program that illustrates changing the */
- /* color for a window using _outtext, _floodfill, and _rectangle. */
-
- #include <graph.h> /* for the graphics functions */
- #include <conio.h> /* for getch() */
-
- void main(void)
- {
- _setvideomode(_ERESCOLOR); /* set to graphics mode */
- _setbkcolor(_BLUE); /* change background color */
- _setcolor(1); /* set drawing color */
- _settextcolor(3); /* set text color */
- _rectangle(_GFILLINTERIOR,100,100,540,250); /* draw a window */
- _setcolor(9); /* change color for fill */
- _floodfill(0, 0, 1); /* fill in the background */
- _settextposition(12, 35); /* coordinates inside square */
- _outtext("scribble"); /* output text inside square */
- getch(); /* wait for a key hit */
- _setvideomode(_DEFAULTMODE); /* reset the video mode */
- }
-
- /*--------------------------------------------------------------------*/
- /* FONTS.C : a slight modification to the "fonts.c" program from the */
- /* QuickC 2.00 online help system, which outputs the fonted text onto */
- /* a "window" of a different color, easily producing the effect of */
- /* a secondary, window-area-only background color. */
-
- #include <conio.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <graph.h>
-
- #define NFONTS 6
-
- unsigned char *face[NFONTS] =
- {
- "Courier", "Helvetica", "Times Roman", "Modern", "Script", "Roman"
- };
- unsigned char *options[NFONTS] =
- {
- "courier", "helv", "tms rmn", "modern", "script", "roman"
- };
-
- main ()
- {
- unsigned char list[20];
- char fondir[_MAX_PATH]="d:\qc2\bin"; /* modify path!!!!! */
- struct videoconfig vc;
- struct _fontinfo fi;
- short fontnum, x, y, mode = _VRES16COLOR;
-
- /* Read header info from all .FON files in given directory. */
- if( _registerfonts( fondir ) <= 0 )
- {
- _outtext( "Error: can't register fonts" );
- exit( 1 );
- }
-
- /* Set highest available graphics mode and get configuration. */
- while( !_setvideomode( mode ) )
- mode--;
- if( mode == _TEXTMONO)
- exit( 1 );
- _getvideoconfig( &vc );
-
- /* Display each font name centered on screen. */
- for( fontnum = 0; fontnum < NFONTS; fontnum++ )
- {
- /* Build options string. */
- strcat( strcat( strcpy( list, "t'" ), options[fontnum] ), "'");
- strcat( list, "h30w24b" );
-
- _clearscreen( _GCLEARSCREEN );
- if( !_setfont( list ) )
- {
- /* Use length of text and height of font to center text. */
- x = (vc.numxpixels / 2) - (_getgtextextent( face[fontnum] ) / 2);
- if( _getfontinfo( &fi ) )
- {
- _outtext( "Error: Can't get font information" );
- break;
- }
- y = (vc.numypixels / 2) - (fi.ascent / 2);
- _moveto( x, y );
- if( vc.numcolors > 2 )
- /* set up the background window & fill before text output */
- _setcolor( fontnum + 2); /* set window color */
- _rectangle(_GFILLINTERIOR,100, 100, 540, 250);
- _setcolor(fontnum+1); /* set color for text */
- _outgtext( face[fontnum] ); /* output fonted text */
- getch();
- }
- else
- _outtext( "Error: Can't set font" );
- }
- _unregisterfonts(); /* free up memory used by fonts*/
- exit( !_setvideomode( _DEFAULTMODE ) );
- }
-
-
- 500. With /CP:1, _memavl() Still Shows Memory Available
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_LINK
- Last Modified: 30-NOV-1989 ArticleIdent: Q50472
-
- Using the /CP:1 (/CPARMAXALLOC - set maximum memory allocation) link
- option does not always leave 1 byte available for allocation in the
- near heap allocation. This becomes apparent when making a call to
- _memavl().
-
- Code Example
- ------------
-
- /* test.c */
-
- #include <malloc.h>
- #include <stdio.h>
-
- void main(void)
- {
- /* _amblksiz=1; */
- /* The above line uncommented will cause only a couple
- bytes to become available (see More Information:). */
- printf("Available memory in near heap = %d\n",
- _memavl());
- }
-
- /* The following options were used to create the program:
-
- cl /c test.c
- link /CP:1 test
-
- This program will show approximately 4K available when
- executed. */
-
- What happens is that _memavl() itself is causing the near heap to
- grow. The library functions _memavl, _freect, and _memmax all require
- the heap to be initialized for them to work. If the heap is not
- initialized then a malloc(0) call is made. The malloc call causes
- DGROUP to grow to the next _amblksiz boundary (8K by default). This
- usually does not cause a problem because malloc is usually called
- either before or after the _memavl.
-
- To reduce the amount of memory taken by DGROUP initialization, set
- _amblksiz to some smaller amount in order for malloc(0) to grab only
- as much it absolutely needs.
-
-
- 501. GRAPHICS.LIB Not Supported in C for OS/2
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 30-NOV-1989 ArticleIdent: Q50474
-
- GRAPHICS.LIB is a real-mode library and its use in a protected mode
- application leads to a general protection fault or a protection
- violation.
-
-
- 502. BX Register Is Popped Twice for a C Interrupt Function
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickAsm 2.00 2.01
- Last Modified: 21-MAR-1990 ArticleIdent: Q50518
-
- The interrupt keyword is used to designate specific C functions as
- interrupt service routines and instructs the compiler to generate
- appropriate entry and exit instructions.
-
- If you compile code with the /G1 or /G2 options (80186 or 80286 code
- generation) then the compiler produces pusha and popa instructions
- that save and restore all vital registers.
-
- However, if you compile with the default /G0 (8086 code generation)
- then the registers are each explicitly pushed and popped. One
- difference in this code, which may at first appear to be a bug, is
- that the BX register is popped twice, but the SP register is not
- popped at all.
-
- This is not a problem. The SP register is saved in the following
- instruction sequence:
-
- mov bp, sp
- .
- . ISR code
- .
- mov sp, bp
-
- The peculiar double popping of BX can be explained by the following:
-
- The registers are pushed AX, CX, DX, BX, SP, BP, SI, DI, DS, ES
- (left to right)
-
- The registers are popped AX, CX, DX, BX, BX, BP, SI, DI, DS, ES
- (right to left)
-
- Notice that ES receives the old ES; DS the old DS, but BX receives the
- old SP, then BX receives the old BX.
-
- The first pop of SP to BX is necessary to remove the previous value of
- SP from the stack. The second pop of BX is necessary to restore the
- old BX value.
-
- The old value of SP was restored in the "MOV SP,BP" instruction,
- which immediately proceeds the popping of all the registers.
-
- This ensures that the state of the registers are saved and then
- restored in the Interrupt Service Routine.
-
-
- 503. Loader Uses Return Value from a DLL's Initialization Routine
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 21-MAR-1990 ArticleIdent: Q50519
-
- Question:
-
- How is the return value from a DLL's initialization routine used?
-
- Response:
-
- The return value from a DLL's initialization is used by the loader.
-
- Using an initialization routine for your DLL is optional. The
- initialization routine can be global or instance. The initialization
- routine is called when the DLL is loaded. [This is not necessarily the
- same time as when a DLL-exported function is called. For example, if
- you load the DLL using DosLoadModule() and DosGetProcAddr(), the
- initialization routine is run and the return value is examined at that
- time.]
-
- Every time you run a program that uses DLLs, the loader goes through
- the import list in the exehdr and attempts to load all the DLLs. As it
- tries to load each DLL, it runs its initialization routine (depending
- on whether the init routine is instance or global). If the
- initialization routine fails (even if the DLL is found) the system may
- display a message, or simply terminate at that point.
-
- Initialization routines are mentioned in Ray Duncan's book, "Advanced
- OS/2 Programming," in Chapter 19, "Dynamic Link Libraries," Pages
- 459-469.
-
-
- 504. Floating-Point Initialization Occurs at Link Time
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 21-MAR-1990 ArticleIdent: Q50523
-
- Floating-point initialization occurs at link time. If the compiler has
- generated any floating-point instructions, it lists an external
- symbol. When the linker sees the external symbol, it brings in the
- necessary segment.
-
- In C 5.10, the external symbol is __fltused. The linker brings in a
- module that has a common CDATA segment that defines the correct values
- of fpmath, fpdata, and fpsignal. If this module is not brought in, the
- CDATA segment defaults to all zeros. This is why CDATA is defined as
- common and not public.
-
- This process causes the floating-point support to be linked only if
- floating point is used.
-
-
- 505. C Run-Time Routines Cannot Be Placed in an Overlay
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 30-NOV-1989 ArticleIdent: Q50524
-
- Problem:
-
- I want to extract a routine from the C Run-Time Library and put it in
- an overlay. The program compiles and links without warnings or errors,
- but when I run the program, my machine hangs.
-
- Response:
-
- The run-time routines for medium and large models (the only ones that
- overlays deal with) are compiled with /NT _TEXT. This puts all the
- routines in the same named segment. The linker cannot split a segment
- between the root and overlay. Segmentation takes precedence over
- overlays. The linker constructs overlays from segments, not individual
- functions.
-
- The first request for the segment (in an .OBJ that goes in root or in
- an overlay) determines where the linker will place the entire segment
- (root or overlay). If your extracted .OBJ is in the overlay, all the
- run time gets put into the overlay.
-
- Consequently, the entry point of the overlay manager is put into the
- overlay and not in the root, so the overlay manager code (also in
- _TEXT) is not present in memory at start up. This causes the machine
- to hang.
-
-
- 506. Calling C Run-Time from a Single-Threaded DLL Init Routine
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 17-JUL-1990 ArticleIdent: Q50759
-
- You can call the C run-time routines from within your initialization
- code for a single threaded dynamic link library (DLL).
-
- To accomplish this, you must ensure that the C run time itself is
- initialized prior to any run-time function call. This is easiest to do
- if you write your base initialization in assembly (as required), but
- then call a routine written in C that will perform the majority of
- your init code. This C routine must be declared as a extrn, far call
- in your assembly code, and defined/prototyped as such in your C init
- code.
-
- The following is a code example:
-
- extrn MYINIT: far in the assembly init module.
- int far pascal MYINIT (...) ; in the C init module.
-
- Once you have satisfied these items, you must then call C_INIT() from
- within your C init module. This must be done before any C run-time
- calls have been made. The C_INIT routine must also be prototyped as
- follows:
-
- int far pascal C_INIT (void) ;
-
- Note: This information applies to single-threaded DLLs only. You
- cannot call the C run time from the init code of a multi-threaded DLL.
-
- The example below details the steps necessary to call any C run-time
- routine from within your single-threaded DLL initialization code.
-
- This example involves the following files:
-
- PROJ.C Source to the EXE that calls the DLL routine
- PROJ.LIB Library created by IMPLIB (based on DLL.DEF)
- [resolves the exported routine(s) from DLL.DLL]
- DLL.C Source to the DLL, and the function FOOPER()
- DLL.DEF Definitions file for the DLL
- ASMINIT.ASM Assembly Init code
- CINIT.C C Init code
-
- The source files to the .EXE and .DLL are standard for this type of
- programming.
-
- The initialization routines and their requirements are discussed
- below:
-
- ASMINIT.ASM
- -----------
-
- .model large
- extrn MYINIT:far ; Declare the C init routine as far.
- .code
- INIT proc far ; Declare init proc....
-
- call MYINIT ; Call my C init code..
- ret ; MYINIT exit code is in AX, so return.
-
- INIT endp
- end INIT ; <--Specifies Entry Point for Init
- ; routine (reason why this must be
- ; in assembly).
-
- CINIT.C
- -------
-
- #include <stdio.h>
-
- // Prototype C Run-Time init function, and my C init code...
- int far pascal C_INIT (void) ;
- int far pascal MYINIT (void) ;
-
- int far pascal MYINIT (void)
- {
- int RetVal ;
-
- // Call the C Run-Time Initialization code..
- RetVal = C_INIT () ;
-
- // Calls to the C Run-Time are now valid...
- printf ("Hello from the DLL init code...\n") ;
-
- // other C Run-Time calls can be made here...
-
- // exit with return value from this initialization code...
- return (RetVal) ;
- }
-
- The source to the remaining files are listed below:
-
- PROJ.C
- ------
-
- #include <stdio.h>
-
- void far pascal FOOPER (int, int) ;
- void main (void)
- {
- printf ("Hello from Main(). Calling DLL routine...\n") ;
- FOOPER (1, 2) ;
- printf ("\nDone.\n") ;
- }
-
- DLL.C
- -----
-
- #include <stdio.h>
-
- void far pascal FOOPER (int, int) ;
- void far pascal FOOPER (int x, int y)
- {
- printf ("Hello from DLL routine 'Fooper'.\n") ;
- }
-
- DLL.DEF
- -------
-
- LIBRARY DLL INITINSTANCE
- DESCRIPTION 'single threaded DLL showing C Run-Time in Init Code'
- DATA MULTIPLE
- EXPORTS FOOPER
-
- These files must be compiled and linked together as follows:
-
- cl /Alfu /G2s /c dll.c
- masm /mx asminit.asm;
- cl /Od /AL /G2 /c cinit.c
-
- link /CO dll asminit cinit,dll.dll/NOI,, \
- llibcdll.lib doscalls.lib, dll.def;
- copy dll.dll c:\os2\dll
-
- cl /AS /G2 /c proj.c
- implib proj.lib dll.def
-
- link /CO proj.obj, /NOI,, slibcep.lib proj.lib doscalls.lib/NOD ;
-
-
- 507. Why After Edit, fopen with Mode "a" Doesn't Appear to Append
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 30-NOV-1989 ArticleIdent: Q50793
-
- Problem:
-
- If I use edlin or Wordstar to edit a file, then call the fopen
- routine with the "a" option and append to the file, the appended
- text doesn't show up when I type the file.
-
- Response:
-
- Edlin and Wordstar are examples of editors that place a CTRL+Z
- character at the end of the file. Opening a file with the "a" option
- writes to the file beginning after the last character in the file (in
- this case, the CTRL+Z). If you then edit the file again with the same
- editor, the editor ignores all characters after the CTRL+Z.
-
- The DOS TYPE command will display all characters up to the first EOF.
- However, if you bring the file up in the M editor or Word, which
- display the CTRL+Z character as a normal character, you can see the
- appended text and, if you want, delete the CTRL+Z character.
-
- If you fopen a file with the "a+" mode, the CTRL+Z character is
- deleted at the end of the file, and appended text can be seen in any
- editor or by using the DOS TYPE command.
-
- The following code demonstrates this behavior:
-
- #include <stdio.h>
- #include <time.h>
-
- void main(void)
- {
- FILE *fp;
- int num;
- time_t system_time;
-
- fp = fopen("out.dat","a"); /* change to "a+" to fix */
- time(&system_time); /* to demonstrate last append */
- num = fprintf(fp, "Writing to file at %s\n",
- ctime(&system_time));
- num = fclose(fp);
- }
-
- Run this program once to write the current system time to the output
- file. Then edlin "out.dat". You do not need to add any lines, just
- open the file and then end the session. Then run the program again.
- Type "out.dat", and notice that you still see only the first output
- time.
-
- Changing the fopen "a" to "a+" and rebuilding the program will
- demonstrate the solution.
-
-
- 508. Time and Date Are Written When File Is Flushed
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 30-NOV-1989 ArticleIdent: Q51123
-
- Changing the time and date of a file with _dos_setftime may appear to
- fail if the file is opened for write and all data has not been written
- to disk. The DOS and OS/2 update file dates whenever a file gets
- modified. Therefore, changing a file date before the operating system
- has written all data to the physical disk may appear to be ignored.
- This is because the date is changed again when the file is closed or
- flushed if there is data still to be written.
-
- For example, the following program will try and modify the date and
- time of the output file to 6-1-89 10:00. Because the file has not been
- flushed or closed, it is likely that there is still data in the file
- buffer waiting to be written to disk. When the file is closed, the
- program will flush all remaining data to the disk, changing the date
- and time to the current date and time in the process.
-
- void main(void)
- {
- FILE *fp;
- fp = fopen( "outfile.txt", "wt" );
- fprintf( fp, "Start of file\n" );
- fprintf( fp, "End of file\n" );
- _dos_setftime( fileno( fp ), 0x12c1, 0x5000) // 10:00 6-1-89
- fclose(fp);
- }
-
- One way to get around this feature of the operating system is to put a
- flush statement before the call to _dos_setftime. This ensures that
- all remaining data has been written to disk before the date is changed
- and the file is closed. The following program changes the date to
- 6-1-89 10:00 successfully.
-
- void main(void)
- {
- FILE *fp;
- fp = fopen( "outfile.txt", "wt" );
- fprintf( fp, "Start of file\n" );
- fprintf( fp, "End of file\n" );
- fflush(fp); // <---- flush the data to disk
- _dos_setftime( fileno( fp ), 0x12c1, 0x5000) // 10:00 6-1-89
- fclose(fp);
- }
-
-
- 509. Formal Parameters Default to Type int
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC
- Last Modified: 30-NOV-1989 ArticleIdent: Q51198
-
- Question:
-
- Why doesn't the compiler generate an error for the following code?
-
- void main (voida)
- {
- }
-
- The variable "voida" is not referenced.
-
- Response:
-
- The C and QuickC compilers don't generate an error because the
- variable "voida" defaults to a variable of type int. The compilers
- understand the above function definition since they recognize the "old
- style" of ANSI C declarations as well as the new. In general, the
- equivalents of the above code are as follows:
-
- Old Style New Style
- --------- ---------
-
- void function (voida) void function (int voida)
- int voida <- default if missing {
- { }
- }
-
- Please refer to "The C Programming Language" by Brian Kernighan and
- Dennis Ritchie for a discussion on differences between old and new
- style with regards to function definition.
-
-
- 510. C 5.00 and C 5.10 Compiler Exit Codes
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_EDITOR
- Last Modified: 30-NOV-1989 ArticleIdent: Q51297
-
- The return codes from the compiler are documented in the "Microsoft C
- Optimizing Compiler User's Guide," Appendix A.3. They are as follows:
-
- Code Meaning
- ---- -------
- 0 No fatal error
- 2 Program error (such as compiler error
- 4 System level error (such as out of disk
- space or compiler internal error)
-
- The compiler returns the same exit codes when you run it from inside
- the Microsoft Editor Version 1.00.
-
-
- 511. tmpfile() Creates Temporary File in the Root Directory
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC Novell docsup
- Last Modified: 30-NOV-1989 ArticleIdent: Q51326
-
- The Microsoft C Version 5.10 run-time library function tmpfile()
- creates a temporary file in the root directory of the current drive.
- This file has read/write access and is automatically deleted when the
- file is closed.
-
- The documentation for this function implies that the file will be
- created in the current working directory. This is not the case; the
- file will exist only in the root directory. To create a temporary file
- in a different directory, use the functions tmpname() or tempname() in
- conjunction with fopen().
-
- Some obscure side effects can occur on some systems as a result of
- tmpfile() creating a file in the root directory. On a network, you
- must have read/write privileges for the root directory of your current
- drive. Without these rights, tmpfile() will fail to open the temporary
- file, returning a NULL in the process.
-
- Another possible reason tmpfile() might fail is if the root directory
- is full. DOS only allows a limited amount of file entries in the root
- directory depending on the disk format; therefore, if the root is
- full, you must delete some files before you use tmpfile().
-
-
- 512. strtok(): C Function -- Documentation Supplement
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QuickC docsup
- Last Modified: 30-NOV-1989 ArticleIdent: Q51327
-
- The strtok() function takes two strings as arguments. The first is a
- series of zero or more tokens separated by delimiters defined by the
- second string. The first call to strtok() returns a pointer to the
- first token in the first argument. To get the next token in the
- original string, a call to strtok() must be made with NULL as the
- first argument that tells strtok() to search for the next token in
- the previous token string.
-
- Keep the following information in mind when using strtok():
-
- 1. strtok() will replace a delimiter in the original string with a
- NULL each time the function is called using the same string, so the
- original string is modified by the use of strtok().
-
- 2. The second argument to strtok() can be changed at any time to a
- different delimiter.
-
- 3. Only single characters are considered to be delimiters.
-
- On the first call to strtok(), the function searches the string
- argument given as the first parameter for any token delimiter defined
- in the second string argument. Any further call to strtok() with NULL
- as the first argument will return a pointer to the next token in the
- original string. The following sample program from Page 603 of the
- "Microsoft C Run-Time Library Reference" manual for Version 5.10 shows
- how strtok() searches a token string:
-
- #include <string.h>
- #include <stdio.h>
-
- char *string = "a string,of ,,tokens";
- char *token;
-
- void main(void)
- {
- token = strtok(string," ,"); /*there are two delimiters here*/
- while (token != NULL){
- printf("The token is: %s\n", token);
- token = strtok(NULL," ,");
- }
- }
-
- The output of this program is as follows:
-
- The token is: a
- The token is: string
- The token is: of
- The token is: tokens
-
- The following is a sample representation of the area in memory around
- the token pointer during execution of the above program. Note the
- replacement of the delimiter with a NULL character each time a token
- is found:
-
- -------------------------------------------------------------
- |a | |s |t |r |i |n |g |, |o |f | |, |, |t |o |k |e |n |s |
- -------------------------------------------------------------
- This is the original string before the first call to strtok()
-
- -------------------------------------------------------------
- |a |\0|s |t |r |i |n |g |, |o |f | |, |, |t |o |k |e |n |s |
- -------------------------------------------------------------
- ^----- token will point here on the first call
-
- -------------------------------------------------------------
- |a |\0|s |t |r |i |n |g |\0|o |f | |, |, |t |o |k |e |n |s |
- -------------------------------------------------------------
- ^------ token will point here on the second call
-
- -------------------------------------------------------------
- |a |\0|s |t |r |i |n |g |\0|o |f |\0|, |, |t |o |k |e |n |s |
- -------------------------------------------------------------
- ^----- token will point here on
- the third call
-
- (etc.)
-
-
- 513. How to Calculate Available File Handles at Run Time
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC
- Last Modified: 14-MAR-1990 ArticleIdent: Q51434
-
- The following piece of code allows you to find out how many file
- handles are available at run time for a particular process. The
- function makes use of the predefined pointers _iob and _lastiob, which
- are set to point to the first and the last input/output information
- blocks, respectively. The I/O blocks are examined to determine whether
- they are in use, and a total number of available file handles is
- produced. There is no equivalent C library function currently
- available.
-
- Note: This is not necessarily an indication of the maximum number of
- physical files that can be opened. The system-wide limit is set in DOS
- by the FILES=?? in the CONFIG.SYS file. In OS/2, it is arbitrarily
- governed by system resources and is modified for each process by
- DosSetMaxFH().
-
- Code Example
- ------------
-
- #define FILE struct _iobuf
- #ifndef NO_EXT_KEYS /* extensions enabled */
- #define _CDECL cdecl
- #define _NEAR near
- #else /* extensions not enabled */
- #define _CDECL
- #define _NEAR
- #endif /* NO_EXT_KEYS */
-
- #define _IOREAD 0x01 /* Open for read bit */
- #define _IOWRT 0x02 /* Open for write bit */
- #define _IORW 0x80 /* Open for read/write bit */
-
- FILE /* File handle table entry */
- {
- char *_ptr;
- int _cnt;
- char *_base;
- char _flag;
- char _file;
- }_NEAR _CDECL _iob[], /*Set to first I/O block at runtime*/
- _lastiob[]; /* Set to last I/O block */
-
- /*
- All of the above definitions were taken from the STDIO.H header
- file except for _lastiob[], which is not defined. This information
- was extracted to make the example more clear.
- */
-
- /*
- The following macro will check the availability of a file handle
- by examining the _flag member of the I/O block
- */
-
- #define inuse(s) ((s)->_flag & (_IOREAD|_IOWRT|_IORW))
-
- /*
- The following routine loops through the total number of I/O blocks
- and checks the flags to see if it is used or not. The number of
- unused handles is returned, which can be 1 to the maximum number of
- file handles as set by the operating system or the FILES=xx command
- in the CONFIG.SYS file.
- */
-
- int Number_Of_Handles(void)
- {
- FILE *stream = _iob;
- int count;
-
- count = 0;
- do
- if (inuse(stream)) count++;
- while(stream++ < _lastiob);
-
- return(((_lastiob - _iob)+1)-count);
- }
-
- void main(void)
- {
- int i;
-
- i = Number_Of_Handles();
- /* i is now set to the number of available file handles */
- }
-
- The table of I/O blocks that is being checked here was allocated at
- run time according to the maximum number of file handles allowed per
- process.
-
-
- 514. Character Parameters May Be Prototyped As Integers
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC
- Last Modified: 14-MAR-1990 ArticleIdent: Q51474
-
- There are some functions in the run-time library that take character
- values as parameters (i.e., memccpy, memset, etc.) and that are
- prototyped as taking integers. This is not a documentation error and
- your program will work correctly if a character value is passed in the
- place of the integer parameter (automatic casting takes care of this).
-
- The integer value is specified because when the compiler pushes
- parameters on the stack so that the function being called can use
- them, it always pushes them in word increments. In other words,
- regardless of whether the value is an integer or a character, 2 bytes
- will be pushed on the stack. Therefore, to simplify, the function is
- prototyped as receiving an integer.
-
-
- 515. Missing Semicolon in Sample Average() Function
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 14-MAR-1990 ArticleIdent: Q51486
-
- In the "Microsoft C Run-Time Library Reference," Page 634, there is a
- missing semicolon (;) in the sample function called average(). Add a
- semicolon at the end of the for-loop and the sample program will work
- properly.
-
- Note: There are two average() functions on Page 634, both need a
- semicolon at the end of the for-loop.
-
-
- 516. OS/2 1.1 EXE May Fail under 1.2 Due to Small Thread Stack Size
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 20-DEC-1989 ArticleIdent: Q51512
-
- If a multithread program runs correctly under OS/2 Version 1.10, but
- the identical program fails under OS/2 Version 1.20, the problem may
- be the size of the thread stack. Under OS/2 1.20, a thread has more
- overhead and requires more space. If you maintain the recommended 2K
- minimum stack size for each thread, then you should never run into
- this problem.
-
- If your program has been running successfully under OS/2 1.10 with a
- thread stack that is smaller than 2K, and the program fails under OS/2
- 1.20, then the first thing you should try is a larger thread stack
- size.
-
- Some of the early examples of multithreaded programming that were
- included in the OS/2 SDK used a thread stack size of 400 bytes. These
- programs run fine on the previous versions of OS/2, but fail with a
- trap 000C under OS/2 1.20. A check of the Intel 80286 documentation
- shows that 000C is a stack overflow problem.
-
- The exact increase necessary in thread stack size between OS/2 1.10
- and 1.20 was not determined, but increasing the stack to 1000 bytes
- allowed these SDK examples to run without problem. Regardless of the
- actual difference needed, the best thing to do is to maintain the
- minimum of at least a 2K thread stack to prevent problems in general.
-
-
- 517. The /Gm Switch Really Does Move Constants to _CONST
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 20-DEC-1989 ArticleIdent: Q51613
-
- Question:
-
- I am using the /Gm switch to move near string constants into the
- _CONST segment, but it doesn't seem to work properly. My program is
- shown below:
-
- char foo[] = "hello";
-
- void main(void)
- {
- }
-
- When I examine the map file generated, it tells me that foo is stored
- in _DATA. Why isn't the string constant "hello" being stored in
- _CONST?
-
- Response:
-
- The /Gm switch is behaving as it should. In the above case, the string
- constant "hello" is not stored as a constant, it is merely a shorthand
- way of initializing the array foo. For example,
-
- char foo[] = "hello";
-
- is equivalent to saying the following:
-
- char foo[] = {'h','e','l','l','o','\0'};
-
- The data in the array foo is not a string constant, and therefore,
- should not be moved to the _CONST section with the /Gm switch.
-
- The following code demonstrates a few string constants:
-
- #include <stdio.h>
-
- void main(void)
- {
- char array[] = "This is NOT a string constant.";
-
- char *foo = "This would be moved out to _CONST with /Gm";
- printf("This string will be moved to _CONST\n");
- }
-
-
- 518. C4056: Overflow in Constant Arithmetic
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-JAN-1990 ArticleIdent: Q51615
-
- The following code, when compiled at warning level 1 or greater,
- causes the Microsoft C 5.10 optimizing compiler to produce warning
- C4056:
-
- test.c(5) : warning C4056: overflow in constant arithmetic
-
- This warning occurs because the compiler is reordering the addition of
- the unsigned constants. This practice is no longer allowed according
- to the ANSI standard.
-
- To work around the problem, perform the arithmetic using long integer
- constants where necessary (use 65535L rather than 65535u, for
- example).
-
- QuickC Versions 2.00 and 2.01 handle this code correctly because these
- versions conform to more recent releases of the draft ANSI standard.
-
- The following is the code that produces the error:
-
- void
- test ( unsigned dummy )
- {
- dummy = 65535u - (dummy - 1);
- }
-
-
- 519. Recursive CL Setting Can Cause D2002 Command-Line Error
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 20-DEC-1989 ArticleIdent: Q51616
-
- The command-line error D2002 is produced by the Microsoft C 5.10
- optimizing compiler under certain circumstances when the CL
- environment variable is set recursively.
-
- The following situations cause the error:
-
- SET CL=CL
- CL -Ax woof.c where x is M, C, or L
-
- SET CL=CL -Ax where x is M, C, or L
- CL -Ay woof.c where y is S, M, C, or L
-
- The error is produced even if -Ax is the same as -Ay in the latter
- case.
-
- D2002 will, of course, also occur when CL is set to a model other than
- the one specified or implied (-AS) on the command line.
-
- The following is the exact text of the error message:
-
- Command line error D2002 : a previously defined model
- specification has been overridden
-
-
- 520. No Warning When Passing Long to Int Prototyped Function
-
- Product Version(s): 5.10 | 5.00
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 21-MAR-1990 ArticleIdent: Q51620
-
- If you prototype a function to accept an integer, and then pass a long
- integer to the function, Microsoft C Version 5.01 and Microsoft QuickC
- Versions 1.00, 1.01, 2.00, and 2.01 fail to give a warning about the
- data conversion if the value being passed is between -65536 and
- +65535. Instead, the value is converted to a valid integer (between
- -32768 and 32767) and passed to the function, causing unexpected
- results.
-
- This is also a problem with the Microsoft QuickAssembler Version 2.01.
-
- The following code demonstrates this problem:
-
- #include <stdio.h>
-
- void func(int,int);
-
- void main(void)
- {
- func(50000L,1L); /* Can also pass in (long)50000,long(1) */
- } /* and have no warnings. */
- /* Try changing to 100000, notice correct */
- /* warning. */
- void func(int a, int b)
- {
- printf("a=%d b=%d",a,b);
- }
-
- If you declare two long integers and pass them to func, as in the
- following, you receive a data conversion warning as expected:
-
- long a=50000,b=1;
- func(a,b);
-
-
- 521. How to Use the Token Pasting Operator in Microsoft C
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC S_QUICKASM 2.00 2.01
- Last Modified: 15-MAR-1990 ArticleIdent: Q51712
-
- The token pasting operator (##) is used to replace tokens within a
- preprocessor string. The (##) can be used to mark off the first
- portion of the string as a token, the last part of the string as a
- token, or the middle of a string as a portion. See the examples shown
- below.
-
- The token pasting operator cannot be the first or the last token in a
- preprocessor string (see Page 197 of the "Microsoft C Language
- Reference" manual for Version 5.10). The first example below (GLUE)
- demonstrates the use of the token pasting operator to concatenate two
- tokens. There is a replaceable token in front of the operator and one
- following the operator. The token pasting operator effectively divides
- the string into the two pieces.
-
- A more complex situation arises when using the token pasting operator
- to replace a token embedded within a string (for example,
- THIS_IS_A_size_TOKEN, where size could be replaced with either large
- or small); the token to be replaced must be surrounded by token
- pasting operators (##). This is necessary only when the token to be
- replaced is completely embedded in another string (see Example 2).
- Normally, the space character is used as one of the token markers,
- while the (##) marks the other end. Only in this specific case (an
- embedded token) is more than one token pasting operator needed.
-
- For more information, please see the ANSI Draft Proposal for the C
- programming language (Document Number X3J11/88-159, 7 December 1988),
- Page 93, or the "Microsoft C Language Reference" manual for Version
- 5.10, Page 197.
-
- /*
- PASTE.C: Demonstrates the use of the token pasting operator.
- */
- /*
- Example 1 definition.
- This definition will replace the token "a" from the beginning
- of the string and "b" from the tail of the string.
- */
-
- #define GLUE(a,b) a##b
-
- /*
- These are the defines for Example 2.
- Calling print with either LARGE or SMALL will then change
- the PRINT macro to call the proper PRINT_..._SIZE macro.
- */
- #define PRINT_LARGE_SIZE(val) printf("The large size is %d\n",val)
- #define PRINT_SMALL_SIZE(val) printf("The small size is %d\n",val)
- #define PRINT(size,val) PRINT_##size##_SIZE(val)
-
- void main ( void )
-
- {
- char *varsrc = "Hello!" ;
- char *vardest = " " ;
-
- /*
- Example #1: Tokens at beginning and end of string
- */
-
- strcpy(GLUE(var,dest),GLUE(var,src)) ;
- printf("%s\n", GLUE(var,dest)) ;
-
- /*
- Example #2: Token embedded in string
- */
-
- PRINT(LARGE, 2) ; /* Calls the printf() for large sizes. */
- PRINT(SMALL, 1) ; /* Calls the printf() for small sizes. */
- }
-
- The following is the corresponding .i (preprocessed file). This file
- can be generated by using -P option at compile time (cl -P paste.c).
-
- void main ( void )
-
- {
- char *varsrc = "Hello!" ;
- char *vardest = " " ;
-
- strcpy(vardest,varsrc) ;
- printf("%s\n", vardest) ;
-
- printf("The large size is %d\n",2) ;
- printf("The small size is %d\n",1) ;
- }
-
-
- 522. Clarification of the /H Identifier Length Option
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | S_QUICKC docerr
- Last Modified: 15-MAR-1990 ArticleIdent: Q51724
-
- The /H option is used to set the maximum length of identifiers in
- Microsoft C Version 5.10. Using /H can only decrease the maximum
- allowable length of identifiers, not increase it. An identifier
- declared with the CDECL type has an underscore (_) appended to the
- front at compile time. This character is part of the identifier and
- takes a significant location. Therefore, the maximum length of an
- identifier declared with the standard C declaration syntax is 32
- characters (the compiler limit on Page 280 of the "Microsoft C User's
- Guide" for Version 5.10 specifies 31 characters, which does not
- include the underscore).
-
- The following example shows how using /H can actually introduce errors
- if identifier lengths are limited to much:
-
- /* When compiled with /H5, the following code will produce
- the error 'L2025: _func : symbol defined more than once'. */
-
- void func1(void);
- void func2(void);
-
- void main(void)
- {
- func1();
- }
-
- void func1(void)
- {
- }
-
- void func2(void)
- {
- }
-
- You must also be careful when using the /H option because of
- predefined compiler identifiers. If the maximum identifier length is
- too small, certain predefined identifiers will be unresolved as well
- as certain library function calls. For example, if the printf function
- is used and the option /H5 is specified at compile time, the symbol
- _prin will be created in order to reference printf, and this will not
- be found in the library.
-
-
- 523. Manual Correction for MASM Returning Single or Double to BASIC
-
- Product Version(s): 5.00 | 5.00
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr B_BasicCom H_MASM B_QuickBas
- Last Modified: 15-MAR-1990 ArticleIdent: Q51728
-
- The following information is relevant to BASIC programmers who want
- their BASIC programs to correctly invoke assembly language functions
- that return single- or double-precision floating-point values.
-
- The following two corrections apply to Page 78 of the "Microsoft
- Mixed-Language Programming Guide," which comes with Microsoft C
- Compiler Version 5.00 and with Microsoft Macro Assembler (MASM)
- Version 5.00 (but does not come with BASIC):
-
- 1. In Section 6.1.6, in the second paragraph, the phrase "BASIC or"
- should be deleted.
-
- 2. In the third paragraph, change the phrase "FORTRAN or Pascal"
- to "BASIC, FORTRAN, or Pascal".
-
- This documentation error was corrected in the "Microsoft
- Mixed-Language Programming Guide" supplied with Versions 5.10 of
- Microsoft C and Microsoft Macro Assembler.
-
- The first sentence in the second paragraph in Section 6.1.6 on Page 78
- should thus read as follows:
-
- When the return value is larger than 4 bytes, a procedure called
- by C must allocate space for the return value and then place its
- address in DX:AX.
-
- The first sentence in the third paragraph in Section 6.1.6 on Page 78
- should thus read as follows:
-
- If your assembly procedure is called by BASIC, FORTRAN, or Pascal,
- then it must use a special convention in order to return
- floating-point values, records and arrays, and values larger than
- 4 bytes.
-
- For a complete guide for passing parameters and invoking functions
- between BASIC and assembly language, search in the Microsoft Knowledge
- Base for the following word: BAS2MASM.
-
-
- 524. Clock Function Sets errno
-
- Product Version(s): 5.00 5.10 | 5.00 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 16-JAN-1990 ArticleIdent: Q51735
-
- Question:
-
- Why does the clock function set errno?
-
- Response:
-
- The clock function uses intdos() to read the system date and time.
- When intdos() calls the date/time interrupt, the carry flag is set
- upon return. The intdos() function interprets the carry flag as an
- error and sets errno to the value in AL. In the case of a request for
- the system date, AL (and therefore, errno) contains the day of the
- week.
-
-
- 525. Spawned Process Runs Out of Environment Space
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 20-DEC-1989 ArticleIdent: Q51742
-
- Using spawn to create a child process, then attempting to increase the
- environment space of the child (by adding a new environment variable
- or expanding an existing environment variable) results in an "Out of
- Environment Space" error.
-
- This problem does NOT happen under OS/2.
-
- The following program(s) illustrates this behavior:
-
- /*-----------------------------------------------------------------*/
- /*-----------------------------------------------------------------*/
- parent.c This will call the child process (child) with the spawnlp
- function.
- /*-----------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <process.h>
-
- void main (void);
-
- void main (void)
- {
- printf ("In the parent process\n");
-
- spawnlp (P_WAIT, "child.exe", "child", NULL);
-
- printf ("\nAnd back to the parent process.\n");
- }
-
- /*-----------------------------------------------------------------*/
- child.c Called by parent.c, uses the system function to call a batch
- file (BATCH.BAT) to attempt to set a new environment variable.
-
- /*-----------------------------------------------------------------*/
- #include <stdio.h>
- #include <process.h>
- #include <conio.h>
- #include <errno.h>
-
- void main (void);
-
- void main (void)
- {
- printf ("At child process...\n");
- system ("batch.bat");
- getch ();
- }
-
- /*-----------------------------------------------------------------*/
- BATCH.BAT The batch file, which is called by the child process
- (CHILD.EXE). It just shows the environment variables,
- attempts to set another environment variable, then shows
- the environment variables one more time.
- /*-----------------------------------------------------------------*/
- set
- set blah=thisisatestonlyatestsoitdoesnotreallymatter
- set
- /*----------------------------------------------------------------------*/
-
- Parent will spawn child, which in turn spawns (through system)
- BATCH.BAT. The idea is to show that when BATCH.BAT is called, an "Out
- of Environment Space" error will be given. Yet, if BATCH.BAT is run
- from DOS, no such error is issued.
-
- To work around this problem, set up a dummy environment variable that
- is large enough to hold the new environment variable you plan to use
- in the spawned process. When the child process is called, you can then
- set the dummy variable to null (with a "set dummy="), then you can set
- your processes environment variable. Please note that this will change
- the dummy environment variable for the child only, not the parent
- process.
-
- Under DOS, the child will get only enough space to hold the current
- environment variables, while under OS/2, the segment that holds the
- environment can usually be expanded.
-
-
- 526. spawn Ignores arg0 with DOS 3.00 and Later
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | S_QuickC S_QuickASM
- Last Modified: 16-JAN-1990 ArticleIdent: Q51768
-
- Question:
-
- Why is arg0 ignored when I use a spawn command under DOS?
-
- Response:
-
- Under DOS Versions 3.00 and later, the first argument (arg0) is used
- to hold the path and name of the program. The third parameter in a
- spawn command is arg0. Regardless of what you specify arg0 to be, DOS
- passes the path and name of the program to the child function. Under
- DOS 2.x, arg0 is not defined.
-
- Under OS/2, this is not the case; arg0 is passed as specified with the
- spawn command.
-
-
- 527. Casting Large Double to Float Gives Compile or Run-Time Error
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 10-JAN-1990 ArticleIdent: Q52103
-
- Casts of double numbers (greater than 3.4E+38) to float numbers can
- cause serious problems at compile time or at run time. Although this
- is expected behavior, it is inconsistent with typical overflow casting
- in that no errors or warnings are produced by the compiler when
- nonfloat overflow casts are made.
-
- In addition, overflowing a float by casting it to a double constant
- may cause the compiler to generate several lines of random characters.
-
- Microsoft has confirmed this random character generation to be a
- problem with C Version 5.10. We are researching this problem and will
- post new information as it becomes available.
-
- If a constant that is greater than 3.4E+38 (the maximum float) is cast
- to a float, the compiler will fail with the following error:
-
- fatal error C1045: floating point overflow
-
- The following code sample demonstrates the compile error:
-
- /* This code when compiled will produce compiler error code
- C1045. */
-
- void main(void)
- {
- float f;
-
- f = (float)6e39;
- /* All numbers up to 3.4e38 work fine */
- }
-
- If a double return value (greater than 3.4E+38) is cast to a float,
- the following run-time error message is displayed:
-
- run-time error M6104: MATH
- -floating-point error: overflow
-
- This following code sample demonstrates the run-time error:
-
- /* This code will compile fine but produces a run-time error
- M6104. */
-
- #include <stdlib.h>
-
- void main(void)
- {
- float f;
-
- f = (float)atof("6e39");
- /* Once again, all numbers up to 3.4e38 work fine */
- }
-
- On the other hand, the following integer cast overflow demonstrates
- that on a nonfloating point cast overflow, no errors are produced:
-
- /* The following code produces no compiler errors, warnings
- (even at warning level 3), or run-time errors. */
-
- #include <stdio.h>
-
- void main(void)
- {
- int i;
-
- i = (int)70000;
- /* The signed integer i is overflowed in this case and will
- probably produce unintended results. */
- }
-
- There is no workaround regarding the casting of double constants to
- floats at compile time other than eliminating the offending cast from
- the code. On the other hand, the problem with the floating point
- overflow error at run time can be caught by using the signal()
- function to trap floating point exceptions. However, both problems can
- be avoided if you ensure that a value greater than 3.4E+38 (maximum
- float value as determined by the IEEE standard for 4 byte floating
- point numbers) is never assigned to a float.
-
-
- 528. Calling a User-Written Function from an ISR
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1990 ArticleIdent: Q52122
-
- It is possible to call a user-written function from an Interrupt
- Service Routine (ISR). However, there a few caveats, as shown below:
-
- 1. Do not make any calls to stack checking routines.
-
- 2. Do not assume DS=SS.
-
- There are other considerations that must be taken into account, such
- as which stack a program is running on, availability of space on the
- stack, etc. Because of these restrictions, there is a limit as to
- which C run-time functions can be used.
-
- Recommended reading for ISR programming is the "Microsoft Systems
- Journal," September 1988, Volume 3, Number 5. This issue of the MS
- Systems Journal contains an article for writing TSR (terminate and
- stay resident) programs with Microsoft C and covers such issues as
- stack considerations and program size. Also, see the Microsoft "MS-DOS
- Encyclopedia," Article 11, for more information.
-
- The following code provides a demonstration of an ISR calling a
- user-written function. The code revectors the keyboard interrupt (INT
- 9H) and then waits for a hotkey to be pressed. If the hotkey is
- pressed, a message is displayed. Because of the above restrictions,
- the printf() family cannot be used. Therefore, a user-written
- function must be called to write the string.
-
- Note: The sample program does not go TSR because this would complicate
- the code. If the you want to modify it for TSR usage, please read the
- above articles.
-
- Sample Code
- -----------
-
- /* Compile with /Gs /Au */
-
- #include <dos.h>
- #include <bios.h>
-
- union REGS inregs, outregs;
-
- void (interrupt far *oldint9)();
-
- /* HOTKEY is CTRL+W */
-
- #define HOTKEY_CODE 0x11
- #define HOTKEY_STAT 0x4
- #define KEYPORT 0x60
-
- #define DOS_INT 0x21
- #define KEYSVC_INT 0x9
- #define DOS_PRINTSTRING 0x9
-
- void dos_puts( char *msg);
- void interrupt far newint9(void);
-
- void dos_puts( char *msg )
- {
-
- (void) _bios_keybrd( _KEYBRD_READ );
-
- inregs.h.ah = DOS_PRINTSTRING; /* DOS INT 21 Function 9h is */
- /* Display String */
-
- inregs.x.dx = (int)msg; /* inregs.x.dx gets the segment */
- /* value of string to be output to crt */
-
- intdos( &inregs, &outregs ); /* INT 21 call to output string */
- }
-
- void interrupt far newint9(void)
- {
- static unsigned char keycode;
- static char active = 0;
-
- if (active)
- _chain_intr(oldint9);
-
- keycode = inp(KEYPORT); /* Check for key at keyboard */
-
- if (keycode != HOTKEY_CODE ) /* If key isn't HOTKEY, */
- _chain_intr(oldint9); /* pass to old handler */
-
- if ( _bios_keybrd(_KEYBRD_SHIFTSTATUS) & HOTKEY_STAT )
- {
- active = 1;
- (*oldint9)();
- dos_puts("HOTKEY was pressed\r\n$");
- active = 0;
- }
- else
- _chain_intr(oldint9);
- }
-
- void main(void)
- {
- long x;
- /* Save old keyboard ISR */
- oldint9 = _dos_getvect( KEYSVC_INT );
- /* Set new keyboard ISR */
- _dos_setvect( KEYSVC_INT, newint9 );
- /* Loop awhile to let program run */
- for(x=0L; x <= 200000L; x++)
- /* Restore old ISR and exit */
- _dos_setvect( KEYSVC_INT, oldint9 );
- }
-
-
- 529. C 5.1 Run-Time Reference Example for atan2() Is Missing ")"
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 15-JAN-1990 ArticleIdent: Q57233
-
- On Page 123 in the "Microsoft C 5.1 Optimizing Compiler Run-Time
- Library Reference," there is a right parenthesis missing in the last
- line of the example program for the atan() and atan2() functions. The
- line should read as follows:
-
- printf("%.7f\n",atan2(-1.0,1.0));
-
-
- 530. Workaround for Converting a Float/Double to a String
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 15-JAN-1990 ArticleIdent: Q57244
-
- Question:
-
- The gcvt() function returns an exponential number in the string even
- if the number fits in the specified precision when the number is of
- the form 0.0x, where x is any digit(s). Because of this behaviour with
- the gcvt() function, I am unable to convert my floating point number
- to a string in the format that I want. Is there another function I can
- use to convert a floating point number to a string?
-
- Response:
-
- Another function that converts a floating point number to a string is
- fcvt(). Unfortunately, it does not do all the conversion for you
- because it leaves out both the decimal point and the sign of the
- number.
-
- You can also use the sprintf() or printf() functions with the "%lf"
- format specifier to obtain the correct results. However, if you do not
- want to use any printf() constructs, supporting code is needed to
- completely convert the floating point number to a string. The
- following program shows one possible way this can be done, and the
- printf() statements can be replaced by puts() statements:
-
- Sample Program
- --------------
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <string.h>
-
- #define PRECISION 8
-
- char *double_to_char (double) ;
-
- char *temp2 ;
-
- void main (void)
- {
- temp2 = (char *) malloc (100) ;
- if (temp2 == NULL)
- printf ("Hey, it didn't work (the malloc for temp)\n") ;
-
- temp2 = double_to_char ((double) 0.0004567891) ;
- printf ("temp = %s\n", temp2) ;
- temp2 = gcvt ((double) 0.0004567891, PRECISION, temp2) ;
- printf ("temp = %s\n", temp2) ;
-
- temp2 = double_to_char ((double) 123.564) ;
- printf ("temp = %s\n", temp2) ;
- temp2 = double_to_char ((double) -43.7864383846738) ;
- printf ("temp = %s", temp2) ;
- }
-
- /* Translates a double to an ASCIIZ string
- */
-
- char *double_to_char (double number)
- {
- char *buffer,
- *temp ;
-
- int decimal_spot,
- sign,
- count,
- current_location = 0 ;
-
- buffer = (char *) malloc (PRECISION + 3) ;
- temp = (char *) malloc (PRECISION + 1) ;
- if (buffer == NULL || temp == NULL)
- {
- printf ("Memory allocating attempt has failed in"
- "'double_to_char'\n") ;
- exit (-1) ;
- }
-
- temp = fcvt (number, PRECISION, &decimal_spot, &sign) ;
-
- /* Force the number to be precise to only PRECISION digits, notice
- that no rounding is done here...
- */
- temp [PRECISION] = '\0' ;
-
- /* Is this a negative number ?, if so add a negative sign.
- */
- if (sign)
- buffer [current_location++] = '-' ;
-
- /* Now we need to put the decimal point in the correct place,
- followed by the rest of the digits.
- */
- if (decimal_spot > 0)
- {
- strncpy (&buffer [current_location], temp, decimal_spot) ;
- buffer [decimal_spot + current_location] = '.' ;
- strcpy (&buffer [decimal_spot + current_location + 1],
- &temp [decimal_spot]) ;
- }
- else
- {
- buffer [current_location] = '.' ;
- for (count = current_location;
- count < abs (decimal_spot);
- count++)
- buffer [count + 1] = '0' ;
- strcpy (&buffer [count + 1], temp) ;
- }
-
- return (buffer) ;
- }
-
-
- 531. Intel Phone Number for Information About EMS Specifications
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 9-JAN-1990 ArticleIdent: Q57480
-
- Question:
-
- Can I access any memory beyond the base 640K on my machine within DOS?
-
- Response:
-
- If you have expanded memory and you have an EMS (Expanded Memory
- Specification) driver that conforms to LIM (Lotus/Intel/Microsoft)
- specifications, you can access memory beyond the base 640K available
- on your machine. For information about accessing this memory, contact
- Intel at (800) 538-3373 or (503) 629-7362.
-
- Intel will send you EMS specifications and documentation discussing
- writing code that uses EMS specifications, including a reprint of the
- March 1987 Microsoft Systems Journal article, "Expanded Memory:
- Writing Programs That Break the 640K Barrier."
-
-
- 532. C Can Recognize up to 31 Characters of Any Name
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 9-JAN-1990 ArticleIdent: Q57481
-
- On Page 83, Section 6.3, Number 3, in the mixed-language guide of
- "Microsoft C 5.1 Optimizing Compiler CodeView and Utilities, Microsoft
- Editor, Mixed-Language Programming Guide," the following is
- incorrectly stated:
-
- C recognizes only the first eight characters of any name, so
- do not make names shared with C longer than eight characters.
-
- This statement is not true. C can recognize up to 31 characters.
-
-
- 533. Displaying Only the Subdirectories with _A_SUBDIR
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1990 ArticleIdent: Q57549
-
- Question:
-
- I am using _dos_findfirst and _dos_findnext and using the _A_SUBDIR
- file attribute to find only the subdirectories. But I am getting not
- only the subdirectories, but also the filenames. Is there any way to
- have _dos_findfirst and _dos_findnext return just the subdirectories?
-
- Response:
-
- You can use _dos_findfirst and _dos_findnext, and by using _A_SUBDIR
- you can find just the subdirectories. Since the _A_SUBDIR attribute
- returns information about normal files as well as files with the
- subdirectory attribute, you must check each file to determine whether
- or not it is an actual subdirectory or a normal file. The following
- program demonstrates how to display just the subdirectories:
-
- Code Example
- ------------
-
- #include <stdio.h>
- #include <dos.h>
- #include <direct.h>
-
- void display_directory ( struct find_t *find ); /* Prototypes */
-
- void main( void )
- {
- struct find_t find;
- char buffer[67];
-
- getcwd (buffer, 66);
- printf ("Current Working Directory: %s\n", buffer);
-
- /* Find first matching file, then find additional matches. */
- if ( !_dos_findfirst( "*.*", _A_SUBDIR, &find ))
- display_directory ( &find );
- while( !_dos_findnext ( &find ))
- display_directory ( &find );
- }
-
- /* Displays Subdirectories in Current Directory */
-
- void display_directory ( struct find_t *pfind )
- {
- /* Determines whether the file is a subdirectory */
- if( pfind->attrib & _A_SUBDIR )
- printf ( "<DIR> %-8s\n", pfind->name );
- }
-
-
- 534. Float Data Type May Cause Problems in TSR Applications
-
- Product Version(s): 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 26-FEB-1990 ArticleIdent: Q57586
-
- The following TSR (terminate and stay resident) interrupt handler does
- not execute properly when invoked. The floating point values produced
- are invalid. If you change the data type "float" to "double", the
- problem disappears.
-
- Code Example
- ------------
-
- #include <stdio.h>
- #include <conio.h>
- #include <math.h>
- #include <dos.h>
-
- void foo (void);
- void interrupt far myint (void);
- void main (void);
-
- /* Change the next line of code to "double a = 10.0"
- and the problem will go away. */
- float a = (float) 10.0;
-
- void foo (void)
- {
- cprintf("The sqrt of %lf is %lf.\n\r",(double) a,sqrt((double) a));
- }
-
- void interrupt far myint (void)
- {
- foo();
- }
-
- void main (void)
- {
- foo();
- _dos_setvect (0x65, myint);
- _dos_keep (0, 2000);
- }
-
- The above program is a TSR interrupt handler for INT 65h, which prints
- out the values 10.0 and sqrt(10.0) to the console when invoked. To see
- the problem with the above program, follow these steps:
-
- 1. Compile with the large memory model (/AL), and run.
-
- 2. Invoke interrupt 65h through the DOS DEBUG.EXE utility, as follows:
-
- a. debug Press ENTER.
-
- b. a Press ENTER.
-
- c. int 65 Press ENTER.
-
- d. ret Press ENTER.
-
- e. Press ENTER.
-
- f. g Press ENTER.
-
- g. q Press ENTER.
-
- The problem disappears if you change the variable "a" from type
- "float" to type "double".
-
-
- 535. Exemod Shows Min Alloc Greater Than Max Alloc with Link /CP:1
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | cvpack
- Last Modified: 15-JAN-1990 ArticleIdent: Q57607
-
- Problem:
-
- Looking at the header of a .EXE file, compiled with C Version 5.10
- with the following
-
- cl foo.c
-
- and linked with
-
- link /CP:1 /E foo;
-
- EXEMOD shows that the value of the minimum allocation(para) is higher
- than the value for maximum allocation(para).
-
- The description of EXEMOD implies that this is not possible (Page 323
- of the Microsoft "CodeView and Utilities, Microsoft Editor,
- Mixed-Language Programming Guide" manual, under the description of
- /MAX).
-
- Response:
-
- Under normal circumstances, the minimum allocation size cannot be
- larger than the maximum allocation size. However, on Page 324 of the
- Microsoft "CodeView and Utilities, Microsoft Editor, Mixed-Language
- Programming Guide" manual, it states the following:
-
- If either the /MIN or the /STACK option is used, the value is
- CORRECTED as necessary to accommodate unpacking of the modified
- stack. The /MAX option operates as it would for unpacked files.
-
- In other words, the minimum allocation value listed in a packed file
- is corrected to allow for the unpacked stack space. Since the maximum
- allocated value does not change for packed files, this COULD result in
- the minimum value being much larger than the maximum value. Note that
- this is the same whether the file is packed using the /E switch with
- LINK, or separately with EXEPACK.
-
-
- 536. Example of Older FORTRAN Main to Newer C Procedure Call
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | H_FORTRAN 4.00
- Last Modified: 21-JAN-1990 ArticleIdent: Q57652
-
- When you link a mixed-language program, you must specify the newer
- version of the run-time library before the earlier version library on
- the link line, even if the earlier version of the library belongs to
- the main procedure in a mixed-language call.
-
- The following code is an example of a mixed-language program that uses
- a FORTRAN main program to call a C procedure to handle the graphics
- for the program. The code is intended to demonstrate correct compile
- and link switches when a FORTRAN routine is compiled with an earlier
- version of the FORTRAN package, which calls a C routine compiled with
- a newer version of the C package.
-
- The code begins execution in the FORTRAN main, then calls the C
- routine to handle elementary graphics routines. Notice the order of
- libraries specified on the link line.
-
- C***************** FORMOD.FOR *****************
- C FORMOD.FOR - FORTRAN 4.0 module to be used with CGRAPH
-
- INTERFACE TO SUBROUTINE CGRAPH[C, ALIAS:'_cgraph']
- END
-
- PROGRAM FORMOD
- CALL CGRAPH
- END
-
- /****************** CGRAPH.C ***************** */
- /* CGRAPH.C - C Graphics module. Used with FORMOD. */
-
- #include <stdio.h>
- #include <graph.h>
- #include <conio.h>
-
- void cgraph(void)
- {
- int i;
-
- i = _setvideomode(_MRES16COLOR);
- printf("return = %d", i); /* check for failed return */
- getch();
- _setvideomode(_DEFAULTMODE);
- }
-
- # ****************** FORMOD.MAK ***********************
-
- formod.obj: formod.for
- fl /Od /Zi /c /AL formod.for
-
- cgraph.obj: cgraph.c
- cl /Od /Zi /W3 /c /AL cgraph.c
-
- formod.exe: cgraph.obj formod.obj
- link /CO /NOE /NOD
- formod cgraph,,,llibcer.lib+llibfore.lib+graphics.lib;
-
- Note: The C graphics calls will fail if the earlier libraries (in this
- case, the FORTRAN libraries) are specified first on the link line.
- This is expected, as you always want newer definitions of the repeated
- code linked into your EXE file.
-
- For more information about FORTRAN and C mixed-language programming,
- see the "Mixed-Language Programming Guide" in your compiler
- documentation.
-
-
- 537. Converting PL/M-386 Code to MSC
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 12-FEB-1990 ArticleIdent: Q57748
-
- Microsoft does not make any PL/M conversion programs or utilities, nor
- do we know of any products for converting PL/M to C or MASM code that
- are explicitly compatible with Windows development. There are,
- however, several third-party vendor products (seen on a December 1988
- bulletin board).
-
- Microsoft has not tested these products, and therefore, we make no
- guarantees about them. You may want to contact the respective vendors
- for more information.
-
- Product: PL/M to C
- Korzeniewski: Frank Korzeniewski Consulting
- 1564-A Fitzgeral Dr. #137
- Pinole, CA 94564
- (415) 799-1819
-
- Product: name not listed
- Lexeme Co.
- Richard Cox
- 4 Station Square #250
- Commerce Court
- Pittsburg, PA 15219-1119
- (412) 281-5454
-
- Another less convenient possibility is to use CodeView (CV) to view
- the assembly code from the PL/M .EXE files. CV may be able to detect
- PUBLIC symbols, such as _main in Microsoft C or Pascal, which would
- allow you to skip start-up code and perhaps to keep track of where you
- are in your code. This will not result in complete or correct
- assembler, but it may ease the conversion process.
-
- You can use PRINT SCREEN to print the assembly code in 17 line blocks.
- Or you can invoke CodeView in sequential mode (/t), redirect to a
- file, and unassemble (U). For details, query on the following words:
-
- disassemble and codeview and listing
-
-
- 538. Return Value for getch() on Extended Characters
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 22-JAN-1990 ArticleIdent: Q57888
-
- When reading extended characters, you must make two calls to getch()
- because the first call returns a value indicating that the key is an
- extended character. The second call returns the actual key code. This
- is how extended keys are detected.
-
- When you are reading an extended character, the first return value
- will be either 0xE0 or 0x00, depending on which extended key is
- pressed.
-
- Sample Program
- --------------
-
- #include <stdio.h>
- #include <conio.h>
- void main(void)
- {
- int ch, scan;
-
- do {
- ch = getch(); /* 1st getch() gets ASCII code */
- printf("Character is %d\n", ch);
- if (ch == 0x00 || 0XE0) { /* if extended key */
- scan = getch(); /* 2nd getch() gets "scan code" */
- printf("\tExtended character: scan is %d\n", scan);
- }
- } while (ch != 27); /* exit loop on ESC */
- }
-
- For a discussion of keystrokes and scan codes, refer to "The New Peter
- Norton Programmer's Guide to the IBM PC & PS/2," Pages 128 to 130.
-
-
- 539. File Buffering Can Hide Out-of-Disk-Space Condition
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 22-JAN-1990 ArticleIdent: Q57889
-
- If disk space is exceeded, file buffering fails when buffering is done
- by the stream I/O functions. For example, if a file buffer for a
- stream is set to 10K by setvbuf() but only 2K disk space is available,
- all data written to the buffer above 2K will be lost. This problem can
- occur even when setvbuf() and fwrite() return successful return codes.
-
- In the case where there is less space on the disk than there is in the
- stream buffer, all stream I/O functions will seem to work properly
- until the stream buffer is filled [for example, fwrite() returns the
- number of bytes written as if it were successful]. However, the status
- of these functions is valid only for the data going to the buffer and
- is not reflected in the file that is written to the disk.
-
- The problem is due to the existence of both the C run-time buffers and
- the DOS buffers. Only when the DOS buffers try to write to disk does
- it become evident that the disk is full. Then, the next return value
- from fwrite() will indicate failure.
-
- The following is the series of events that leads to the loss of data
- with buffered stream I/O functions:
-
- 1. The stream is opened with fopen().
-
- 2. Buffering is set on the stream, either 512 bytes default or the number
- of bytes selected by the user with setvbuf().
-
- 3. There is less disk space than the size of the buffer set by Step 2.
-
- 4. Bytes are written to the file [for example, fwrite()], with
- successful return codes.
-
- 5. The buffer is filled and then the stream I/O function attempts to
- write all data to DOS.
-
- 6. The bytes that can fit on the disk are written and all remaining
- data that was in the buffer is lost.
-
- 7. Successive calls to write data to the file fail.
-
- The following are possible workarounds:
-
- 1. Turn buffering off by setting the file buffer to NULL, using
- setvbuf().
-
- 2. Use nonbuffered I/O functions, such as open(), read(), and write().
-
- 3. Check the result of closing the stream with fclose(), which flushes
- all buffers associated with the given stream prior to closing.
-
- 4. Set buffering to the same size as the records that are being
- written. The third workaround will force fwrite() to return a
- "failure" return code at a point where the program can easily
- recover because the program knows exactly which records were
- successfully written to disk and which one was not.
-
-
- 540. "UNKNOWN WARNING" May Result from Bad Error Message File
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 8-MAR-1990 ArticleIdent: Q57942
-
- If a number of compiler warning messages contain the description
- "UNKNOWN WARNING", the cause may be the use of an incorrect or
- corrupted error message file. The compiler generates the correct error
- number, but since the messages are retrieved from a separate file, the
- compiler displays "UNKNOWN WARNING" when it cannot find a match.
-
- The error message files for C 5.10 should contain messages for all
- errors and warnings generated. If you look up the number of a compiler
- error in the documentation and find a normally documented error, then
- you should be suspicious of your .ERR error message files.
-
- The simplest check is to reinstall the error message files from the
- original C 5.10 disks and then recompile to see if the error messages
- appear correctly. The .ERR files to recopy are CL.ERR and C23.ERR from
- the Setup disk and C1.ERR from the disk labeled Compiler Disk 1.
-
-
- 541. Err Msg: C1064 Too Many _text Segments
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 25-JUL-1990 ArticleIdent: Q58522
-
- Question:
-
- When I compile my program, I get a fatal error message "C1064 : too
- many _text segments". What is wrong?
-
- Response:
-
- This error is caused by using the alloc_text pragma to define more
- than 10 distinct _text segments in a single "compilation unit". The
- following code reproduces the error message:
-
- Sample Code
- -----------
-
- /*******************************/
- /* Define _text segments here. */
- /*******************************/
-
- #pragma alloc_text(foo_1,foofunct_1)
- #pragma alloc_text(foo_2,foofunct_2)
- .
- .
- .
- #pragma alloc_text(foo_11,foofunct_11)
-
- /*******************************/
- /* Define Prototypes */
- /*******************************/
-
- void main(void);
- void foofunct_1(void);
- void foofunct_2(void);
- .
- .
- .
- void foofunct_11(void);
-
- /********************/
- /* Define functions */
- /********************/
-
- void main(void)
- {
- printf("Here we go. Eleven alloc_text pragmas: \n");
- }
-
- void foofunct_1(void)
- {
- }
- void foofunct_2(void)
- {
- }
- .
- .
- .
- void foofunct_11(void)
- {
- }
-
- See the "Microsoft C Optimizing Compiler: User's Guide" Version 5.1
- manual. The alloc_test pragma is detailed on Page 159. The error
- message (C1064) is documented in the "Microsoft C for MS-DOS and OS/2
- Operating Systems: Version 5.1 Update" on Page 59.
-
-
- 542. Escape Character Erases First Characters in gets() String
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm 1.00 1.01 2.00 2.01
- Last Modified: 26-JAN-1990 ArticleIdent: Q57948
-
- If you enter the escape character (ASCII 1Bh) from the keyboard
- (console) into a string that gets(), cgets(), or fgets() is reading,
- all of the string previously read in is erased. The string pointer is
- reset so that characters following the escape character are read into
- the beginning of the string. This is consistent with the action done
- by the operating system (OS) to parse the input-line.
-
- However, if the escape character is input from a file by redirection,
- the entire string including the escape character will be read into the
- string.
-
- Code Example
- ------------
-
- #include <conio.h>
- #include <stdio.h>
-
- char buf[22];
- char *result;
-
- void main(void)
- {
- int i;
- buf[0] = 20;
-
- printf("Enter your text: \n");
- result = gets(buf);
-
- printf ( "Resulting String: %s\n", result );
- for( i = 0; i < 20; i ++ )
- {
- printf("Buf[%2d] = %c (char)\n", i, buf[i]);
- }
- }
-
- Enter the following string as a test:
-
- abcdef<esc>ghijk
-
- Note that the resulting string is output as:
-
- ghijk
-
- Now, using a text editor that will accept an escape character embedded
- in a string, create a data file with the same string. If the above
- program is run with input redirected from the data file, for example
-
- program <test.dat
-
- the resulting string is output as follows:
-
- abcdef<esc>ghijk
-
- This behavior occurs in the entire gets() family of routines,
- including gets(), cgets(), and fgets(). If the input is coming from
- the console, the run time will use the standard MS-DOS OS/2 keyboard
- read routines. On the other hand, if the input is coming from a file
- (through redirection) there is no editing performed by the OS and the
- file is read in literally.
-
-
- 543. Use of the Stringizing Operator (#) in Macros
-
- Product Version(s): 3.x 4.x 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm 1.x 2.00 2.01
- Last Modified: 7-MAR-1990 ArticleIdent: Q57949
-
- When you are writing a preprocessor macro that takes an argument that
- must appear in quotation marks, you can use the # sign to expand the
- argument. One implementation of this preprocessor directive is the use
- of printf() in the macro. The following code demonstrates an example:
-
- Code Example
- ------------
-
- #define PR(fmt,value) printf("value = %" #fmt "\n", (value))
-
- #include <stdio.h>
-
- void main(void)
- {
- float afl;
-
- afl = 3.14f;
- PR(5.2f, afl);
- }
-
- The sample code outputs the following string:
-
- value = 3.14
-
- The # sign in front of the fmt variable allows the macro to be
- expanded out with quotation marks. Note that the preprocessor
- concatenates consecutive pairs of double quotation marks so that the
- following string
-
- "value = %""5.2f""\n"
-
- is translated into the following:
-
- "value = %5.2f\n"
-
-
- 544. Why External References Are Created When They're Not Needed
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 15-MAY-1990 ArticleIdent: Q57961
-
- Problem:
-
- In the following example, Microsoft C compiler versions 5.00 and 5.10
- generate an extern reference to printf(); therefore, the function is
- included at link time. This apparently is a bug since the compiler
- correctly ignores generating any code for the "if" statement.
-
- The following is code example:
-
- #define VERBOSE 0
-
- int function(void)
- {
- if (VERBOSE) printf("hello world\n");
-
- return 1;
- }
-
- Response:
-
- The way it works now is by design. The extern reference is generated
- in the first pass of the compiler and the "if" code is removed in pass
- two. Furthermore, according to ANSI specifications (Section 3.7,
- "External Definitions" in December 7, 1988 draft), the extern is
- required.
-
- If your purpose is to provide conditional code for debugging reasons,
- the preprocessor is much better suited to the task.
-
- The above code fragment should be changed to the following:
-
- #define VERBOSE 0
-
- int function(void)
- {
- #if (VERBOSE)
- printf("hello world\n");
- #endif
-
- return 1;
- }
-
-
- 545. Unresolved Externals from GRAPHICS.LIB
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 26-JAN-1990 ArticleIdent: Q57971
-
- When linking a program with a version of GRAPHICS.LIB newer than the
- one supplied with your compiler, the following unresolved externals
- will occur:
-
- LINK : error L2029: Unresolved externals:
-
- __aDBdoswp in file(s):
- d:\lib\GRAPHICS.LIB(..\gr\qcswap.asm)
- ___aDBswpchk in file(s):
- d:\lib\GRAPHICS.LIB(..\gr\qcswap.asm)
- ___aDBswpflg in file(s):
- d:\lib\GRAPHICS.LIB(..\gr\qcswap.asm)
-
- There were 3 errors detected
-
- Code Example
- ------------
-
- #include <stdio.h>
- #include <graph.h>
-
- void main(void)
- {
- _clearscreen ( _GCLEARSCREEN );
- _settextcolor ( 1L );
- _outtext ("Hello");
- getch();
- }
-
- Following are the steps to re-create the unresolved externals:
-
- 1. Compile the program using Microsoft C 5.10 compiler and link the
- object file with GRAPHICS.LIB from either FORTRAN 5.00, QuickC
- 2.00, or QuickC 2.01.
-
- 2. Compile the program using Microsoft QuickC 2.00 or 2.01 and link
- the object file with GRAPHICS.LIB from FORTRAN 5.00.
-
- To determine which GRAPHICS.LIB came with which package, check the
- size of the GRAPHICS.LIB file (shown below):
-
- C 5.10 - 59357 bytes 3-07-88 5:10a
-
- QuickC 2.00 - 75337 bytes 12-13-88 10:19a
-
- QuickC w/QuickAssembler 2.01 - 75871 bytes 3-08-89 11:17a
-
- FORTRAN 5.00 - 76467 bytes 3-24-89 8:56p
-
- It is recommended that you use the version of GRAPHICS.LIB that comes
- with the compiler to avoid any problems.
-
-
- 546. C2144 May Be Caused by Executable Code Between Declarations
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 12-FEB-1990 ArticleIdent: Q58559
-
- Compiler Error C2144 is defined as follows:
-
- syntax error : missing 'token' before type 'type'
-
- You may receive this error message if your program places executable
- code before a data declaration, a practice which was acceptable in
- Kernighan and Ritchie C, but has since been outlawed in later versions
- of the ANSI drafts.
-
- This error message will normally occur if a required closing curly
- brace (}), right parenthesis [)], or semicolon (;) is missing.
-
- The following code demonstrates this error message:
-
- /* Program : foo.c */
-
- #include <stdio.h>
-
- void main(void)
- {
- int i;
- printf("Beetlejuice\n");
- int j;
- }
-
- Compiling this code with Microsoft C Version 3.00, 4.00, 5.00, or
- 5.10, or QuickC Version 1.00, 1.01, 2.00, or 2.01 will return the
- following error message:
-
- foo.c
- foo.c(7) : error C2144: syntax error : missing ';' before
- type 'int'
-
- Placing all data declarations before all executable code corrects the
- programming error.
-
-
- 547. Changing a Drive's Volume Label
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm h_masm
- Last Modified: 14-MAR-1990 ArticleIdent: Q58650
-
- Changing a drive's volume label involves the use of FCB (File Control
- Block) file processing, and therefore, is not supplied with the C
- run-time libraries. However, one of the ways to do this is through DOS
- int 21h calls for FCB file manipulation.
-
- Below is an assembly routine written with Microsoft MASM Version 5.10
- to change a drive's volume name. To do this, it first sets up an
- extended FCB to allow for manipulating files with attributes. Offset 6
- of the FCB is set to 8 (_A_VOLID defined in dos.h) to specify a
- volume. The old volume is searched for with "*.*" as a pattern and
- deleted, then the volume is re-created with the new volume label
- passed by the C caller. The function returns the error code supplied
- from the DOS API that creates the volume label.
-
- Use the following:
-
- rc = NewVol( iDrive, szName ); // iDrive = Drive number ( 1, 2, ... )
- // szName = Up to 11 chars. DOS filename
- // rc = Return Code from function.
-
- The new volume label must be passed with 11 characters for the name.
- Anything less MUST be padded with spaces.
-
- Sample Code
- -----------
-
- ; unsigned NewVol( int, char * ) will delete a disk volume and
- ; create one with the new name.
- ;
- ; Assemble with /Dmodel={SMALL MEDIUM COMPACT LARGE}
- ; /Dlang={C FORTRAN BASIC PASCAL}
-
- %.MODEL model,lang
-
- .DATA
- maxlen EQU 11 ;Maximum name length
- datasz EQU 2 ;Size of Data Pointers
- ; Setup an extended FCB
- fcb DB 255, 0, 0, 0, 0, 0, 8, 1
- DB 37 DUP (?)
- default DB '* * ' ;Equivalent to "*.*"
-
- .CODE
- NewVol PROC USES si di es, Drive:WORD, VolName:WORD
- mov bx,Drive ;Get drive number ( 1 byte )
- mov fcb+7,bl ;...and store in FCB offset 7
- mov ax,ds
- mov es,ax
- cld ;Upward move
- mov cx,maxlen ;Size of move
- mov si,OFFSET default ;Source string to
- mov di,OFFSET fcb+8 ;...filename offset in 8 FCB
- rep movsb ;Move maxlen bytes of vol name
- mov dx,OFFSET fcb ;Delete volume off drive
- mov ah,13H
- int 21H
- mov cx,maxlen
- mov si,VolName ;New name passed by C caller
- mov di,OFFSET fcb+8
- rep movsb ;Copy 11 chars for new label
- mov dx,OFFSET fcb ;Create the new volume
- mov ah,16H
- int 21H
- mov dx,OFFSET fcb ;Close the file
- mov ah,10H
- int 21H
- mov ah,0
- ret
- NewVol ENDP
- END
-
-
- 548. Redirecting stdout to and from a File Using C
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 26-FEB-1990 ArticleIdent: Q58667
-
- Question:
-
- How do I redirect stdout to a file from a C program, then get the
- original stdout back at a later time in the same program?
-
- Response:
-
- The C function typically used to redirect stdout or stdin is
- freopen(). To redirect stdout to a file called FOO.TXT, use the
- following call:
-
- freopen( "foo.txt", "w", stdout );
-
- This statement causes all subsequent output, which is typically
- directed towards stdout, to go to the file FOO.TXT.
-
- To get stdout back to the keyboard (the default stdout), use the
- following call:
-
- freopen( "CON", "w", stdout );
-
- In both of these cases, check the return value of freopen() to make
- sure that the redirection actually took place.
-
- Below is a short program to demonstrate the redirection of stdout:
-
- #include <stdio.h>
- #include <stdlib.h>
-
- void main(void)
- {
- FILE *stream ;
-
- if((stream = freopen("foo.txt", "w", stdout)) == NULL)
- exit(-1);
-
- printf("this is stdout output\n");
-
- stream = freopen("CON", "w", stdout);
-
- printf("And now back to the console once again\n");
- }
-
- This program assumes that stdout is to be redirected toward the
- console at the end of the program.
-
-
- 549. Using _dos_findfirst() Function to Retrieve Disk Volume
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc 2.00 s_quickasm 2.01
- Last Modified: 26-FEB-1990 ArticleIdent: Q58800
-
- Question:
-
- I am using the _dos_findfirst() function to find my disk volume. I use
- the _A_VOLID attribute to get the disk volume and it works correctly,
- except when I get a volume name greater than eight characters. Then, I
- get a period embedded in the middle of my string. For example, if my
- volume name is "VOLUMENAME", _dos_findfirst returns "VOLUMENA.ME". Why
- does the period get embedded in the string?
-
- Response:
-
- Volume labels are a specific type of directory entry specified by
- setting bit 3 in the attribute field to 1 or 0x08. They are a special
- type of file that can only be in the root directory. The maximum
- number of characters a volume label can have is 11 characters (8
- characters for the filename followed by a three-character extension).
-
- The C run-time function _dos_findfirst() will return the volume label
- in a file format since DOS stores the volume label in the file format.
-
-
- 550. Cannot Allocate More Than 64K with Calloc()
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 8-MAR-1990 ArticleIdent: Q58933
-
- Although calloc() takes two unsigned integers as parameters, it does
- not allocate more than 64K. Calloc() determines the size you are
- attempting to allocate by multiplying the two arguments. If the size
- is greater than 64K, it will return NULL.
-
- The confusion typically arises because, with malloc(), it is
- impossible to ask for more than 64K due to the size of the argument
- malloc() takes. Malloc() takes an unsigned int as an argument;
- therefore, the largest number you can pass it cannot be greater than
- 64K. This is not the case with calloc() -- so one might make the
- assumption that you COULD allocate more than 64K with calloc(). This
- is simply not the case.
-
-
- 551. If .DLL Is Linked with CRTLIB, Then .EXE Must Be Linked, Too
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 6-MAR-1990 ArticleIdent: Q58961
-
- When you write a program that uses a DLL that has been linked with
- CRTLIB.DLL, then the program itself must also link with CRTLIB.DLL.
- The diagram and text in Section 5.2 of MTDYNA.DOC explain this close
- relationship in detail.
-
- Also in MTDYNA.DOC, the table in Section 6 is very useful for
- identifying which components to use for which type of output file
- (.EXE or .DLL). The following is a diagram of the library
- relationships in the table:
-
- +---------+ | +---------+
- / | xLIBCyP | | / | LLIBCDLL|
- single +---------+ | single +---------+
- +-----+/ thread | +-----+/ thread
- | EXE | | | DLL |
- +-\---+\ | +-----+\
- multiple | multiple
- thread +---------+ | thread +---------+
- \ \ | LLIBCMT | | \ | CRTLIB |
- \ (or) +---------+ | +---------+
- \ ________________________________________________/
-
- As long as the .EXE is independent of any DLLs, it links with either
- xLIBCyP.LIB or LLIBCMT.LIB, depending on whether the .EXE is single or
- multithreaded. When the .EXE uses a DLL, the .EXE links with either
- xLIBCyP.LIB or CRTLIB.LIB, depending on whether the DLL is single or
- multithreaded.
-
- Additional .OBJs and .LIBs are linked for multithreaded .EXEs and for
- single and multithreaded DLLs. You can find complete detailed
- information about compiling and linking multithreaded programs and
- dynamic link libraries in MTDYNA.DOC, which is provided on the C 5.10
- disks.
-
- For further information, query on the following words:
-
- CRTLIB and DLL
-
-
- 552. Pointer Arithmetic Wraps Around Segment Ends
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 1-MAR-1990 ArticleIdent: Q58987
-
- When you increment or decrement a pointer beyond a segment boundary,
- the offset of the pointer will wrap around the end. For example, if
- the pointer is sitting at FFFF and you increment it by 1 (one), the
- resulting value of the offset is 0000. This wraparound behavior is
- expected behavior in all memory models except huge. The example below
- demonstrates the "hidden" wraparound.
-
- The C language permits writing beyond array boundaries and heap
- allocations. Consequently, C compilers do not generate warning or
- error messages if an index or pointer goes out of bounds. It is up to
- the programmer to monitor indices and pointers.
-
- If you have an array that is larger than 64K, use the huge keyword or
- compile in the huge memory model. Pointer arithmetic for huge data is
- performed on the full 32 bits of segment and offset address. For
- complete information on huge model programming, refer to Chapter 6 in
- the "Microsoft C Optimizing Compiler User's Guide."
-
- Sample Code:
-
- /* wrap.c */
- #include <stdio.h>
- #include <dos.h>
- #include <malloc.h>
-
- void main (void)
- {
- char *ptr;
-
- ptr = (char*) malloc (100);
- printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
-
- FP_OFF(ptr) = 0x0000;
- printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
- ptr--;
- printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
-
- FP_OFF(ptr) = 0xFFFF;
- printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
- ptr++;
- printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
- }
-
-
- 553. Buffer Size for fcvt, ecvt Is 349 Bytes
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 15-MAR-1990 ArticleIdent: Q59070
-
- Question:
-
- The run-time references to the ecvt and fcvt routines say that they
- use a single, statically allocated buffer while converting floating
- point numbers to character strings. How large is this buffer?
-
- Response:
-
- The buffer is currently defined as 349 bytes. However, the largest
- double-precision variable that can be used is 309 bytes, with 40 bytes
- for padding.
-
- Note: This size may change in future releases of Microsoft's C
- compilers, so you should not rely on the consistency of this size.
-
-
-
- 554. Changing a Compaq's CPU Speed
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 15-MAR-1990 ArticleIdent: Q59071
-
- There are no C run-time functions that change the CPU speed, but there
- is an interrupt that will change the speed of the CPU. This interrupt,
- shown below, works only on Compaq computers.
-
- INT 16h:
-
- AH = F0h
- AL = speed
- 00h equivalent to 6 MHz
- 01h equivalent to 8 MHz
- 02h full 16 MHz
- 03h toggles between 8 MHz -- equivalent and speed set by
- system board switch (AUTO or HIGH)
- 08h full 16 MHz except 8 MHz during floppy disk access
- 09h specify speed directly
- CX = speed value, 1 (slowest) to 50 (full), 3 ~= 8088
-
- To read the current CPU speed, set AH = F1h and call interrupt 16h.
-
- INT 16h:
- AH = F1h
- RETURN:
- AL = speed code (see function F0h for speed code)
- if AL = 09h, CX = speed code
-
-
- 555. Determining Size of Memory Block Referenced by a Pointer
-
- Product Version(s): 5.00 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 15-MAR-1990 ArticleIdent: Q59087
-
- Question:
-
- Is there a function in the Microsoft C run-time library that returns
- the amount of memory that has been allocated to a pointer by malloc()?
- If not, is there a way I can write my own?
-
- Response:
-
- There is no C run-time library function that explicitly returns the
- amount of memory that has been allocated to a pointer by malloc().
- However, it is possible to retrieve this information indirectly
- through the Microsoft C run-time library function _heapwalk(). The
- _heapwalk() function returns a heap information structure of the
- following form:
-
- struct _heapinfo {
- int far * _pentry;
- size_t _size;
- int _useflag;
- } _HEAPINFO;
-
- The information returned in this structure can be accessed directly or
- used in writing a function that gives the size information you want.
- The following is sample code:
-
- #include <stddef.h>
- #include <malloc.h>
-
- size_t msize(void * pointer, int * error)
- {
- struct _heapinfo info; /* Heap info structure */
- int heap_status; /* Heap status */
- size_t ret_val; /* msize() return value */
-
- info._pentry = NULL; /* Initialize heap info structure */
-
- do {
- heap_status = _heapwalk(&info); /* Step through heap until */
- } while ((pointer != info._pentry) /* desired entry is found */
- && (heap_status == _HEAPOK)); /* or a heap error occurs. */
-
- if(heap_status == _HEAPOK)
- if(info._useflag != _FREEENTRY)
- ret_val = info._size; /* no errors */
- else {
- ret_val = -1; /* entry has been freed */
- *error = _FREEENTRY;
- }
- else {
- ret_val = -1; /* a heap error occurred */
- *error = heap_status;
- }
- return(ret_val);
- }
-
- Note: The msize() function takes as a parameter a pointer pointing to
- the base memory that was allocated. For msize() to work correctly,
- this pointer MUST point to the base of the allocated block, and not
- anywhere within that block.
-
- The msize() function returns the size of the allocated block or -1 if
- an error occurs. If -1 is returned, an error code is returned through
- the error parameter. The error parameter will be one of the following
- manifest constants:
-
- _FREENTRY _HEAPEMPTY _HEAPBADPTR
- _HEAPBADBEGIN _HEAPBADNODE _HEAPEND
-
- These error codes are actually generated by the Microsoft run-time
- library function _heapwalk(). Refer to your Microsoft C Compiler's
- documentation on _heapwalk() for more information on the meaning of
- these error codes.
-
- Following is a sample program that uses of the msize() function to
- find the amount of memory allocated to a pointer. This function is
- designed to work in any memory model:
-
- #include <stdio.h>
- #include <malloc.h>
-
- size_t msize(void *, int *);
-
- void main (void)
- {
- char * p;
- int error;
- size_t size;
-
- p = (char *)malloc(sizeof(char) * 11)
- if(p = NULL) {
- printf("Memory allocation error\n");
- return;
- }
-
- size = msize(p,&error);
- if(size == -1)
- printf("An msize error has occurred\n");
- else
- printf("Size = %u\n", size);
- }
-
- Note: The malloc() function allocates 11 bytes of memory for use by
- the pointer p. Surprisingly, msize() returns 12 as the size of the
- allocated block. Actually, this is an expected result. Malloc() always
- allocates even-byte amounts as a result of PC architecture.
- Consequently, msize()'s return value always is an even amount.
-
-
- 556. How to Do a Print Screen within a Program
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 7-MAR-1990 ArticleIdent: Q59380
-
- The code below demonstrates how to do a print screen from within a
- program under MS-DOS. This is done by executing INT 5 within a
- program.
-
- The interrupt service directs all its output to the default printer.
- The print-screen service prints text or graphics. In graphics mode,
- GRAPHICS.COM must be loaded before invoking the print-screen service.
-
- INT 5 does not return any values but the status code is available at
- memory location 0050:0000. The values are as follows:
-
- 00 no error occurred
- 01 indicates that a print-screen operation is in progress
- FF the previous print screen was not successful.
-
- Code Example
- ------------
-
- #include <stdio.h>
- #include <dos.h>
-
- void main (void)
- {
- int *result;
- struct REGS inregs, outregs;
-
- /* inregs and outregs are never used but necessary
- for the int86 function.
- */
-
- puts("This is a test of prtscr() function.");
- int86(0x5, &inregs, &outregs);
-
- *result = (int *) 0x00500000;
- switch( *result )
- {
- case 0:
- puts("No error occurred.");
- break;
- case 1;
- puts("Print Screen in progress....");
- break;
- case 0xFF;
- puts("ERROR occurred during print screen");
- break;
- }
- }
-
-
- 557. Cannot Open Compiler Intermediate File
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 17-DEC-1990 ArticleIdent: Q59479
-
- In DOS mode, the error number for the "cannot open compiler
- intermediate file" message is C1042; in OS/2, the error number is
- C1043. This is caused by an incorrect setting of the TMP environment
- variable, when a semicolon ends the path. For example:
-
- TMP=C:\TMP;
-
- This causes the compiler to return the following error message:
-
- fatal error C1042: cannot open compiler intermediate file -- DOS
-
- or
-
- fatal error C1043: cannot open compiler intermediate file -- OS/2
-
- The correct way to set up the TMP environment variable is as follows:
-
- >SET TMP=C:\TMP<RETURN>
-
- It is important that the environment string does not end with a
- semicolon because the compiler appends the intermediate filename to
- the TMP path. By removing the semicolon from the path, the compiler
- can create the file correctly.
-
- Since there are other Microsoft products that utilize the TMP
- environment variable, it is safe to remove the semicolon from the end
- of the TMP environment variable path.
-
- This is true only for the TMP variable because other environment
- variables are used only for a search path.
-
-
- 558. L2022, L2029 on PM Functions Not Prototyped As EXPENTRY
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER | o_os2sdk
- Last Modified: 15-MAR-1990 ArticleIdent: Q59489
-
- Problem:
-
- I receive the following error messages when I link my PM (Presentation
- Manager) program:
-
- LINK : error L2022: ClientWndProc (alias ClientWndProc) :
- export undefined
-
- LINK : error L2029 : 'ClientWndProc' : unresolved external
-
- Response:
-
- Most frequently, this problem is caused by having an /NOI linker
- option, which forces the linker to distinguish between uppercase and
- lowercase. For more information, search the knowledge base using the
- following query:
-
- L2022 and L2029 and /noi
-
- These linker error messages may also occur if you forget to prototype
- your functions with the EXPENTRY keyword. The EXPENTRY keyword is
- defined in OS2DEF.H as follows:
-
- #define EXPENTRY far pascal
-
- The "pascal" keyword instructs the compiler to use left-to-right
- calling sequences for the function it modifies. The keyword also
- causes the conversion of the function's name to uppercase letters.
-
- Not using the EXPENTRY keyword means that your function names are not
- converted to uppercase, so even though you declare a .DEF file, which
- includes the following line
-
- EXPORTS ClientWndProc
-
- the linker cannot resolve definitions for the function because it does
- not see ClientWndProc and CLIENTWNDPROC as being equal.
-
-
- 559. A2071 and A2006 with Assembly Code from a C Program
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | h_masm s_quickc s_quickasm fixlist6.00
- Last Modified: 15-APR-1990 ArticleIdent: Q59608
-
- When using the /Fa switch (generate assembly language listing) and the
- /AL switch (large memory model) with C 5.10, the compiler will
- generate some slightly incorrect assembly code in the .ASM file. When
- this assembly code is run through MASM, MASM will give the following
- errors:
-
- A2071: Forward needs override or FAR
- A2006: Phase error between passes
-
- Specifically, these errors occur in a module that has a function
- calling another function within the same module. In this case, it is
- possible to make a NEAR call to the specified function. Because the
- function being called is a FAR function (in large memory model), CS
- must be pushed onto the stack to correct problems that arise.
-
- The assembly code produced by C 5.10 does not specify that the call to
- the function is NEAR, although it still pushes CS onto the stack prior
- to calling the function. Because the current memory model is large,
- and the type of call is not specified, a FAR call is assumed.
-
- When the function returns (with a RET), both CS and IP are popped off
- of the stack, which the call automatically put onto the stack. You are
- left with an extra CS still on the stack.
-
- To work around this problem, it is important to force a NEAR call to
- the function.
-
- The following is an example of the C code used to produce the
- assembly code:
-
- #include <stdio.h>
-
- void main (void);
- int r1 (void);
-
- void main (void)
- {
- printf ("Foo\n");
- r1 ();
- printf ("Bar\n");
- }
-
- int r1 (void)
- {
- return (1);
- }
-
- The following is a piece of the assembly code, the important piece in
- this case:
- .
- .
- .
- push cs
- call _r1
- mov WORD PTR [bp-2], ax ; rc
- .
- .
- .
- Because these procedures are both declared as FAR, it is assumed that
- this is a FAR call. Since that is the case, it is not necessary to
- push CS.
-
- To correct the problem, you can change the call to the following:
- .
- .
- .
- push cs
- call NEAR PTR _r1
- mov WORD PTR [bp-2], ax ; rc
- .
- .
- .
- In this case, you are forcing the assembler to notice that only the
- offset is necessary on the stack. When the RET is encountered, both
- words (offset and segment) will be popped off of the stack.
-
- It is necessary to make these changes for each call to a function that
- can be made with a near call. Calls that are made to functions in
- another module are FAR by default because they are external, so they
- aren't a problem.
-
- If the .ASM code is assembled with Quick Assembler, the same errors
- will result if the two-pass option is turned on. With only one pass,
- the phase error is not generated. Either way, the same correction
- applies in both cases.
-
-
- 560. How to Find the Load Size Required for a Program
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 9-APR-1990 ArticleIdent: Q59768
-
- The final allocated segment within a program is stored in the second
- word of its Program Segment Prefix (PSP). To find the size of the
- program in paragraphs, subtract the actual segment of the PSP from
- this segment number. This is useful in a number of applications
- including finding the amount of memory neccessary to store a TSR
- (terminate and stay) program.
-
- In Microsoft C, the segment of the PSP is stored in the global
- variable _psp. This makes program load size easily accessible within C
- programs as demonstrated below. For more information on the PSP, see
- the "MS-DOS Encyclopedia," Pages 108-111.
-
- Sample Code
- -----------
-
- #include<dos.h>
-
- extern unsigned _psp; /* segment of PSP */
- unsigned size; /* size of program in paragraphs */
- unsigned far *psp_pointer; /* pointer to beginning of PSP */
-
- /* psp_pointer[1] will contain the final allocated */
- /* segment of the program stored in the second word */
- /* of the Program Segment Prefix. */
-
- void main(void)
- {
- FPSEG(psp_pointer)=_psp;
- FPOFF(psp_pointer)=0;
-
- size=_psp_pointer[1]-_psp;
- }
-
-
- 561. Determining If Your TSR Has Already Been Installed
-
- Product Version(s): 4.00 5.00 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm appnote
- Last Modified: 23-MAR-1990 ArticleIdent: Q59884
-
- When writing a TSR (terminate-and-stay-resident), it is possible to
- utilize the multiplex interrupt (2fh) to determine whether your TSR
- has already been loaded into memory. Set up an Interrupt Service
- Routine (ISR) for this interrupt, which will compare the AH register
- with a predefined TSR number (ID#) and change the AL register to a
- nonzero value if the two are equal.
-
- When using the interrupt keyword in Microsoft C, registers are pushed
- onto the stack before each function call. To access these register
- values from within an ISR, just define the ISR function as accepting
- these registers as parameters.
-
- Once this is set up, the installation part of the TSR can make a call
- to the multiplex interrupt with the AH register set to the ID# of the
- TSR, and the AL register set to 00h. If the handler is currently
- installed, it will pick up these values in the AX register and then
- change the AL register to 01h and return this "installed" signal to
- the calling program. If the ID# in the AL register is not that of the
- TSR, the TSR can simply chain the interrupt back to its original
- vector.
-
- In summary, to have your TSR check to see if it is already installed,
- do the following:
-
- 1. Make an int86 call with the following:
-
- inregs.h.ah=id#(0xc0-0xff)
- inregs.h.al=0x00
-
- 2. If outregs.h.al != 0x00, program is in memory, don't re-install.
-
- 3. Else, revector INT2fh to your own ISR. This ISR should do the
- following:
-
- a. Take as parameters the registers pushed on the stack by the
- interrupt keyword (see REGPAK below).
-
- b. Check the AH register, hibyte of the AX register, with a TSR
- ID#(0xc0-0xff).
-
- c. If AH=TSR ID#, change al to 0x01.
-
- d. Else, chain to the old INT2fh vector.
-
- 4. Terminate and stay resident.
-
- The following is a simple example of an ISR that would accomplish Step
- 3 (above) nicely with a TSR ID# of 0xc9. For more information about
- the multiplex interrupt and its function, please refer to "The New
- Peter Norton Programmer's Guide to The IBM PC & PS/2," Page 303-306.
- For an example of a TSR, see the application note "TSR Example
- Dirzap.C," which is available from Microsoft Product Support Services
- by calling (206) 454-2030.
-
- Sample Program
- --------------
-
- void (interrupt far *original_int2fh)(); /*set to original*/
- /* int2fh handler*/
-
- #define HIBYTE(x) (((unsigned) (x) >> 8) & 0xff)
-
- #define REGPAK unsigned es, unsigned ds, unsigned di, \
- unsigned si, unsigned bp, unsigned sp, \
- unsigned bx, unsigned dx, unsigned cx, \
- unsigned ax, unsigned ip, unsigned cs, \
- unsigned flags
-
- void interrupt far new_int2fh(REGPAK)
- {
- if (HIBYTE(ax)==0xc9) /* check TSR ID# */
- ax=0xc901; /* set AL to 01 */
- else
- _chain_intr(original_int2fh);
- }
-
-
- 562. Read() Run-Time Function Example Is Incorrect
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 17-JUL-1990 ArticleIdent: Q59885
-
- On Page 481 of the "Microsoft C Optimizing Compiler: Run-Time Library
- Reference," Version 5.1 manual, the sample program for read() is
- incorrect. The conditional statement for the function read() should
- check for the value 65535 (0xFFFF or -1 for a signed int), instead of
- less than or equal to 0 (zero). Since bytesread is declared as an
- unsigned int, the value 0xFFFF is stored as 65535.
-
- Sample Code
- -----------
-
- #include <fcntl.h> /* Needed only for O_RDWR definition */
- #include <io.h>
- #include <stdio.h>
-
- char buffer[60000];
-
- void main (void)
- {
- int fh;
- unsigned int nbytes = 60000, bytesread;
-
- /* Open file for input: */
- if ((fh = open ("data", O_RDONLY)) == -1)
- {
- perror ("open failed on input file");
- exit(1);
- }
-
- /* Read in input: */
-
- bytesread = read (fh, buffer, nbytes);
- if ((bytesread == 0) || (bytesread == 65535))
- perror ("Problem reading file");
- else
- printf ("Read %u bytes from file\n", bytesread);
- }
-
-
- 563. How to Write Directly to Video Memory Under OS/2
-
- Product Version(s): 5.10
- Operating System: OS/2
- Flags: ENDUSER |
- Last Modified: 23-MAR-1990 ArticleIdent: Q59837
-
- Question:
-
- I am porting an application from DOS to OS/2 that writes directly to
- screen memory. If I run it from OS/2, it gives me a protection
- violation whenever I attempt to write directly to screen memory. How
- is this done under OS/2?
-
- Response:
-
- Under OS/2, you can use the VioGetPhysBuf API call to obtain a 16-bit
- segment selector to the physical screen buffer. You can then use the
- MAKEP macro to obtain a 32-bit far pointer to screen memory.
-
- It is important to note that your program MUST be the current
- foreground session when writing to the screen buffer obtained by
- VioGetPhysBuf. If you switch the program to the background, OS/2
- temporarily invalidates the selectors to protect the integrity of the
- display. Any attempt to write to these selectors when the process is
- not in the foreground results in a general protection violation. You
- can use the VioScrLock API to ensure that your process will not be
- swapped to the background while writing to the video buffer.
-
- The following program demonstrates how to write directly to the
- monochrome screen buffer under OS/2.
-
- Sample Code
- -----------
-
- /*
- * MONO.C
- *
- * Writes directly to the monochrome screen buffer.
- *
- * Uses VioScrLock and VioScrUnlock to ensure that the program doesn't
- * get swapped to the background while writing to the video buffer.
- *
- * This program basically clears the monochrome screen buffer.
- *
- */
-
- #define INCL_VIO
- #define INCL_DOSPROCESS
-
- #define MONOBUF (char far *) 0xB0000L /* Address of mono screen
- /* buffer */
- #define BYTE_SIZE 4000 /* 80x25 * 2 */
-
- #include <os2.h>
- #include <stdio.h>
- #include <conio.h>
-
- void main (void)
- {
- VIOPHYSBUF viopbBuf;
- PCH pchScreen;
- USHORT usStatus;
- int i;
-
- viopbBuf.pBuf = MONOBUF;
- viopbBuf.cb = BYTE_SIZE;
-
- /* Lock the video buffer so bad things don't happen. */
- VioScrLock(LOCKIO_NOWAIT, (PBYTE) &usStatus, 0);
-
- if (usStatus != LOCK_SUCCESS) {
- printf ("ERROR: Somebody else has the video buffer.\n");
- DosExit (EXIT_PROCESS, usStatus);
- }
-
- /* Grab the video buffer. */
- usStatus = VioGetPhysBuf(&viopbBuf, 0);
- if (usStatus) {
- printf ("VioGetPhysBuf failed returncode %d.\n",usStatus);
- DosExit (EXIT_PROCESS, usStatus);
- }
-
- /* Make a 32 bit pointer from a segment selector. */
- pchScreen = MAKEP(viopbBuf.asel[0], 0);
-
- /* Loop through memory writing spaces. Jump over attribute byte.*/
- for (i=0; i < BYTE_SIZE; i+=2)
- pchScreen[i] = ' ';
-
- /* We're done, so we can unlock the video buffer. */
- VioScrUnLock(0);
- }
-
-
- 564. Floating-Point Differences Between the 8086 and MC68000
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc s_quickasm h_masm endian
- Last Modified: 15-JAN-1991 ArticleIdent: Q60037
-
- Question:
-
- I am writing a file that will be exchanged between an MC68000 machine
- and an 8086 machine. I want to know how the byte ordering of the IEEE
- (Institute of Electrical and Electronic Engineers) floating-point
- format must be manipulated. In other words, how should the bits or
- bytes be reordered?
-
- Response:
-
- The byte ordering of floating point numbers in the architecture of the
- MC68000 is opposite that of the 8086; that is, the bytes are reversed.
- Microsoft C Version 5.10 conforms to the IEEE standard. The 8086
- stores floating-point numbers low-order byte to high-order byte (known
- as "little end in"). The MC68000 stores floating-point numbers
- high-order byte to low-order byte (known as "big end in"). Except for
- the bytes being reversed, the internal representation of the float is
- the same.
-
- For example, given the following floating-point number in the
- following 4-byte real data type
-
- 5.27E-3
-
- the representation of that number in IEEE format would be
-
- 3B AC AF F7
-
- which is equivalent in binary to the following:
-
- 0011 1011 1010 1100 1010 1111 1111 0111
-
- However, an Intel machine stores this number with the bytes reversed,
- as follows:
-
- F7 AF AC 3B
-
- On the other hand, in MC68000 format, the bytes are not reversed.
- Internally the MC68000 would represent the above number as
-
- 3B AC AF F7
-
- which is the same as the IEEE representation; therefore, no "manual"
- byte reversal needs to be effected.
-
- To summarize the internal interpretation of the above number, the
- following information is valid for both IEEE and MC68000 formats:
-
- The mantissa is bits 0-22, which in this case equals 2928631. The
- mantissa is assumed to be prefixed with an implied "1."; therefore,
- the full mantissa is 1.2928631. Bits 23-30 represent the exponent.
- This exponent must be adjusted by a factor of 127 (80 hex; the "bias"
- adjustment, which must be subtracted from the bitwise representation
- of the exponent). Bit 31 is 0, which implies that the exponent is
- positive. Therefore, the exponent as represented here is 119.
- Performing the following bias subtraction:
-
- 119-127 = -8
-
- While the base in the original number 5.27E-3 is 10, the base of the
- internal representation is 2. Therefore, the above calculation yields
- the final result of
-
- 1.2928631 X 2E-8
-
- which is the original number (allowing for some floating point
- inaccuracies).
-
-
- 565. Error in memchr() Definition
-
- Product Version(s): 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 3-APR-1990 ArticleIdent: Q60045
-
- The following text shown on Page 418 of the "Microsoft C Optimizing
- Compiler: Run-Time Library Reference" for Version 5.1 manual,
- regarding the definition of the memchr() function, contains a
- misleading statement that could be confusing for some customers:
-
- void *memchr(buf,c,count);
- void *buf; Pointer to buffer
- int c; |-----> Character to copy
- size_t count; | Number characters
- |
-
- Instead of "Character to copy," the definition of int c should read
- "Character to search for." Memchr() searches for, but does not copy, a
- character in a string.
-
-
- 566. fscanf() Fails to Read Consecutive Lines
-
- Product Version(s): 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 19-APR-1990 ArticleIdent: Q60336
-
- If you try to read lines of text using fscanf() from a file opened in
- text mode, and define [^\n] as the delimiter, you will find that your
- program will read only the first line of the text file.
-
- Sample Code
- -----------
-
- FILE *fin;
- char Line[80];
-
- while ( ( fscanf(fin,"%[^\n]",line) ) !=EOF )
- {
- printf("Line = %s \n",line);
- }
-
- At first glance, the sample code appears to read and print lines from
- a text file until the end of the file is reached. However, this is not
- the case.
-
- The fscanf() function reads up to but not including the delimiting
- character. Therefore, the file stream is stopped at the first "\n" in
- the file. Subsequent fscanf() calls fail because the file is still at
- the first delimiting character and fscanf() will not move past it.
-
- To move the file stream beyond the delimiting character, the following
- are two workarounds:
-
- 1. Place a fgetc() after the fscanf() to position the file pointer
- past the "\n".
-
- 2. Change the fscanf() call to the following:
-
- fscanf(fin, "%[^\n]%*c", line)
-
- This automatically reads the next character.
-
- The corrected code is as follows:
-
- FILE *fin;
- char Line[80];
-
- while ( ( fscanf(fin,"%[^\n]",line) ) !=EOF )
- {
- fgetc(fin); // Reads in "\n" character and moves file
- // stream past delimiting character
- printf("Line = %s \n",line);
- }
-
-
- 567. C Compiler and Linker Send Errors to Stdout Not Stderr
-
- Product Version(s): 5.10
- Operating System: MS-DOS
- Flags: ENDUSER | s_util s_pascal h_fortran h_masm docsup docerr
- Last Modified: 19-APR-1990 ArticleIdent: Q60750
-
- Current versions of the C compiler and linker send error messages to
- stdout instead of stderr. Use of the ERROUT utility shipped with
- Microsoft C Version 5.10 does not redirect these error messages to a
- file as is suggested in the documentation.
-
- The following example from the Microsoft C Version 5.10 "CodeView and
- Utilities Software Development Tools for the MS-DOS Operating System"
- manual, Page 329, is misleading:
-
- ERROUT /f C_ERRORS.DOC CL /AL /Zi /Od demo.c
-
- In the above example, the only thing printed in C_ERRORS.DOC is the C
- compiler copyright and version message. Neither the compiler or the
- linker errors appear there. This is not an error in the ERROUT
- utility, nor is it an error in C Version 5.10; it is just a change in
- the way error messages are output from the newer compilers.
-
- This new method of sending error output to stdout allows our products
- to function more easily with third-party editors that check only
- stdout for compiler and linker messages.
-
- Note: The ERROUT utility is designed for use only with executable
- programs and batch files. Attempting to use it on DOS commands, such
- as DIR, usually only results in the failure of the command.
-
-
- 568. Bad Conditional Jump Generated in Inline Assembly
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 6-FEB-1991 ArticleIdent: Q69011
-
- Under the following conditions, C 6.00 and C 6.00a will generate bad
- code for conditional jumps in inline assembly blocks. If, prior to the
- conditional jump, an align or even directive is used that causes NOP
- instructions to be inserted into the code, the conditional jump
- address will be off by the number of NOPs inserted into the code. This
- will happen only when using the /Od switch for disabling optimizations
- on the compile. Optimizations should not have an affect similar to
- this on inline assembly.
-
- Using /Os, /Ot, or /Ox will resolve the problem. Removing any align or
- even directives will also eliminate the source of the problem.
- Finally, using the /qc option will also generate correct code;
- however, the /qc option does not generate the NOP instructions for the
- align and even directives as it should.
-
- Microsoft has confirmed this to be a problem in C version 6.00 and
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
- Sample Code
- -----------
-
- void main (void)
- {
- _asm
- {
- even
- push ds
- even
- jb foo
- foo: pop ds
- }
- }
-
-
- 569. Why locking() May Allow Only Twenty Regions to Be Locked
-
- Product Version(s): 4.x 5.x 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 30-JAN-1991 ArticleIdent: Q67485
-
- The DOS SHARE.EXE command installs file sharing and locking capability
- within the DOS environment. If SHARE is executed without any
- parameters, the default number of simultaneous file locks is 20.
- Subsequently, the C locking() function will allow only twenty regions
- to be locked at the same time. To change from the default, SHARE
- should be installed with the following parameter (where n is the
- number of simultaneous regions that can be locked):
-
- SHARE /L:n
-
-
- 570. C 5.00/5.10 Give "Constant Too Large" with Decimal Initializer
-
- Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 6-FEB-1991 ArticleIdent: Q11876
-
- Problem:
-
- When I attempt to use the most negative long integer, my results
- depend on whether I used decimal or hexadecimal to enter the value.
- The results also seem to vary between C version 5.00 and the newer
- compilers.
-
- For example, the following program produces the compiler warning
- "constant too big" when compiled with C 5.00:
-
- long d1, d2;
-
- void main(void)
- {
- long d1 = -2147483648L;
- long d2 = 0x80000000;
- printf("d1 = %ld", d1);
- printf("d2 = %ld", d2);
- }
-
- The compiler assigns the value -2147483647 to d1, although it assigns
- -2147483648 to d2. The internal representation of d1 seems incorrect.
-
- Response:
-
- In C versions 5.00 and earlier, the decimal constant -2147483648L is
- treated semantically as a unary minus sign applied to a positive
- constant, 2147483648L. The positive constant is outside the valid
- range for constants, and therefore, is reduced to the maximum positive
- long integer; thus, the message "constant too large" is issued.
-
- On the other hand, the hexadecimal constant 0x80000000 is treated
- semantically as a series of bits. It has few enough bits to fit into a
- long integer, so no message is issued. Had the constant contained too
- many bits to fit into a long integer, it too would have been reduced
- to 2^31 - 1.
-
- C version 5.10 does not complete compilation in this situation and
- halts with the error, "C2177: constant too large." This ensures that
- you will not be using an unexpected value.
-
- Beginning with C version 6.00, long constants can be initialized to
- decimal values larger than MAX_LONG (as per the ANSI draft standard),
- so this is no longer a problem at compilation time.
-
-
- 571. fread() May Cause Protection Violation Under OS/2
-
- Product Version(s): 6.00 6.00a
- Operating System: OS/2
- Flags: ENDUSER | buglist6.00 buglist 6.00a
- Last Modified: 11-FEB-1991 ArticleIdent: Q69136
-
- Under certain circumstances, fread() may issue a general protection
- violation (GP fault) under OS/2 when compiled in large model with C
- versions 6.00 and 6.00a.
-
- The sample code below allocates a 64K segment, filling it by doing 128
- fread()'s that request 512 bytes per call. In tracing through the
- code, it appears that as fread() is preparing to continue the read, it
- calculates the address of the first unused byte. Finding it to be
- beyond the end of the segment, it adds 0x20 to the segment value and
- places the result in the ES register, resulting in a general
- protection violation.
-
- Sample Code
- -----------
-
- /* Compile with -AL
- *
- */
-
- #define BUFS_PER_BLOCK 128 /* Number of word buffers per block. */
- #define WORD_BUFFER_SIZE 512
-
- #include <stdio.h>
- #include <os2.h>
-
- void main( void)
- {
- SEL usSel; /* Selector for allocated memory. */
- FILE *fp;
- CHAR *ptCurrentBufferAddress; /* Address of current word buffer. */
- INT i;
-
- DosAllocSeg(WORD_BUFFER_SIZE * BUFS_PER_BLOCK, &usSel, SEG_GETTABLE);
- if ((fp = fopen("c:\\os2\\pmfile.exe", "r+b")) == NULL)
- printf("FOPEN FAILED\n");
- else
- printf("FOPEN SUCCEEDED\n");
- ptCurrentBufferAddress = MAKEP(usSel, 0);
- for (i = 0 ; ; i++)
- {
- fread(ptCurrentBufferAddress, WORD_BUFFER_SIZE, 1, fp);
- if (i == BUFS_PER_BLOCK - 1)
- break;
- ptCurrentBufferAddress += WORD_BUFFER_SIZE;
- }
- }
-
- Microsoft has confirmed this to be a problem in C versions 6.00 and
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
-
- 572. Use of OFFSET and SEG on Local Variables in Inline Assembly
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 6-FEB-1991 ArticleIdent: Q69012
-
- Inline assembly allows you to use the SEG and OFFSET operators to get
- the segment and offset address of variables. However, if you use the
- SEG directive on a local variable, you will get the following error
- message in C versions 6.00 and 6.00a or QuickC versions 2.50 and 2.51:
-
- error C2415: improper operand type
-
- You will not get this error with QuickC versions 2.00 and 2.01, and
- incorrect code will be generated. In all versions, using the OFFSET
- directive on a local variable will not directly give you a near
- pointer to the variable.
-
- It is important to remember that a local variable is placed on the
- stack at run time. Therefore, the compiler cannot determine its
- address at compile time. The value returned by OFFSET applied to a
- local variable actually is that variable's position on the stack
- relative to the BP register. Thus, adding the BP register to the
- OFFSET value will create a near pointer into the stack segment.
-
- Because the local variable is on the stack, the segment value of a
- local variable is simply the stack segment (SS) register. The
- following two sample programs demonstrate the incorrect and correct
- method to access a local variable address:
-
- Sample Code
- -----------
-
- // These programs show how you might try to load an address
- // of a local variable into the dx, ax register combination.
-
- // This is the wrong way to get a local variable address.
-
- void main(void)
- {
- int foo;
- _asm
- {
- mov ax, OFFSET foo
- mov dx, SEG foo
- }
- }
-
- // This is the right way to get a local variable address.
-
- void main (void)
- {
- int foo;
- _asm
- {
- mov ax, OFFSET foo
- add ax, bp
- mov dx, ss
- }
- }
-
-
- 573. How Structures Are Packed with /Zp
-
- Product Version(s):
- Operating System: 6.00 6.00a | 6.00 6.00a
- Flags: MS-DOS | OS/2
- Last Modified: 30-JAN-1991 ArticleIdent: Q67735
- ENDUSER | docerr s_quickc
-
- The C compiler contains a command-line option as well as a pragma to
- pack structures, /Zp and pack, respectively. Packing a structure means
- to align an element of a structure on a 1-, 2-, or 4-byte boundary.
- Packing can be used for indexing purposes, as well as to decrease
- processor access times. If /Zp or the pragma is not used, the default
- structure packing value is 2.
-
- The amount of padding used before a particular structure field is
- determined by the field size and packing value. The packing value may
- change the offset of particular members of the structure.
-
- All offsets of structure members are relative to 0 (zero). Each member
- size is compared to the packing value (also called the alignment
- value). The element is then aligned on a boundary of the smallest of
- the field size and packing value.
-
- Finally, the structure itself may be padded to allow for arrays of
- structures to be aligned properly. The rule is simple. All structures
- are padded to a multiple of the pack size except one case. If a
- structure is packed on 4 byte boundaries but doesn't contain any
- elements larger than 2 bytes, it is padded to a multiple of 2.
-
- Below is an example of a structure that was packed with 1-byte packing
- [/Zp1 or #pragma pack (1)]. The structure is shown first, followed by
- a summary of what happens to the structure in memory, and finally the
- generated assembly listing is shown.
-
- Structure
- ---------
-
- struct
- {
- char a;
- int b;
- char c;
- } dummy;
-
- Packed Structure (/Zp1)
- -----------------------
-
- struct
- {
- char a;
- int b;
- char c;
- }
-
- Assembly Code Generated in Small Model
- --------------------------------------
-
- _BSS SEGMENT WORD PUBLIC 'BSS'
- _BSS ENDS
- .
- .
- .
- _BSS SEGMENT
- COMM NEAR _dummy:BYTE:4
- _BSS ENDS
-
- Notice that the size in the assembly listing shows 4 bytes. Because
- the structure is exactly 4-bytes in size, there is no need for padding
- at the end.
-
- The following is an example with 2-byte packing [/Zp2 or #pragma
- pack(2)]:
-
- Structure
- ---------
-
- struct
- {
- char a;
- int b;
- char c;
- } dummy;
-
- Packed Structure (/Zp2)
- -----------------------
-
- struct
- {
- char a;
- (Filler character here)
- int b;
- char c;
- (Filler character here)
- }
-
- Assembly Code Generated in Small Model
- --------------------------------------
-
- _BSS SEGMENT WORD PUBLIC 'BSS'
- _BSS ENDS
- .
- .
- .
- _BSS SEGMENT
- COMM NEAR _dummy:BYTE:6
- _BSS ENDS
-
- In this case, notice that the int is padded to start on a 2-byte
- boundary and the actual structure was padded to be a multiple of 2.
- Therefore, the length is 6 bytes.
-
- The following is an example of a structure packed with /Zp4:
-
- Structure
- ---------
-
- struct
- {
- char a;
- int b;
- long c;
- char d;
- } dummy;
-
- Packed Structure (/Zp4)
- -----------------------
-
- struct
- {
- char a;
- (1 padding character here)
- int b;
- long c;
- char d;
- (3 filler characters here)
- }
-
- Assembly Code Generated in Small Model
- --------------------------------------
-
- _BSS SEGMENT WORD PUBLIC 'BSS'
- _BSS ENDS
- .
- .
- .
- _BSS SEGMENT
- COMM NEAR _dummy:BYTE:12
- _BSS ENDS
-
- This is a little more complex. The first padding occurs with the
- integer. Because the field size for an integer is 2 and the alignment
- value is 4, the integer will be aligned on a 2-byte boundary (field
- size is smaller). The long integer needs to be on a 4-byte alignment.
- However, because it is already on a 4-byte boundary, no padding
- characters are needed. Finally, because we have a long in this
- structure, the entire structure is padded to be a multiple of 4.
-
-
- 574. How to Modify the Environment for a Spawned Process
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1991 ArticleIdent: Q11997
-
- Question:
-
- I use the spawnl() function to allow the user to run other programs
- without exiting mine. Is there a way to change the operating system
- command prompt to remind the user to type EXIT to return to my
- program?
-
- Response:
-
- Since PROMPT is a DOS and OS/2 environment variable, you just need to
- set your own value for PROMPT in the spawned processes environment. C
- allows you to specify the environment to be handed to a child process
- in one of the following two ways:
-
- 1. Use one of the spawn*e() functions. See the C run-time library
- reference or online help supplied with your compiler for specific
- details about the spawn() family of functions.
-
- 2. Use the putenv() function to modify the program's own local copy of
- the environment, then use one of the spawn() functions other than
- spawn*e(). Details on the putenv() function may also be found in the
- C run-time library reference or online help.
-
- In general, a process may only alter the environment to be handed to a
- child process. The C run-time library functions give the illusion of
- being able to alter the environment space but this is accomplished by
- making a copy of the environment strings during start up and,
- thereafter, only altering this copy.
-
-
- 575. How to Change Attributes of Subdirectories in a C Program
-
- Product Version(s): 3.x 4.x 5.x 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 25-FEB-1991 ArticleIdent: Q69216
-
- The C run-time functions _dos_setfileattr() and _dos_getfileattr(), or
- the OS/2 API calls DosSetFileMode() and DosQFileMode(), respectively,
- allow you to set and check the attributes of files. When using the
- same functions on subdirectories, the operating system does not allow
- attributes to be set, and no error codes are returned. However,
- because a subdirectory is a special instance of a file, the system can
- be fooled into thinking that a subdirectory is a file, which will
- allow you to set the attributes of a subdirectory.
-
- Below is a listing of available attribute settings:
-
- C Run-Time OS/2 Description Value
- ---------- ---- ----------- -----
-
- _A_NORMAL FILE_NORMAL A file with no attributes 0x00
- _A_RDONLY FILE_READONLY A read-only file 0x01
- _A_HIDDEN FILE_HIDDEN A hidden file 0x02
- _A_SYSTEM FILE_SYSTEM A system file 0x04
- _A_VOLID * Volume label (special case) 0x08
- _A_SUBDIR FILE_DIRECTORY Subdirectory (special case) 0x10
- _A_ARCH FILE_ARCHIVED An archived file 0x20
-
- * A drive's volume label is another special-case file; there is only
- one per (logical) drive, and it is only in the root directory.
- Under OS/2, volume labels can be changed with DosSetFSInfo. Under
- DOS, there are no C run-time functions to change drive volumes. For
- more information, query on the following words:
-
- volume and attribute and 5.10
-
- From the list above, the only attributes that can be dynamically set
- are FILE_READONLY, FILE_HIDDEN, and FILE_SYSTEM (all files,
- subdirectories, and volumes entail FILE_NORMAL), and this process
- cannot be done on a directory entry that is flagged as a subdirectory
- or volume label. To change the attributes of a subdirectory, the
- attribute flag _A_SUBDIR (or FILE_DIRECTORY) should not be included.
- The code below demonstrates how to do this using either C run-time
- calls (DOS only) or OS/2 API functions (DOS and OS/2 if bound).
-
- Sample Code
- -----------
-
- #define INCL_DOSFILEMGR
- #include <os2.h>
-
- #include <dos.h>
- #include <stdlib.h>
-
- unsigned attr, newattr;
-
- void main(void)
- {
- if (DOS_MODE == _osmode)
- {
- // First get the current attribute of subdirectory '\foo'
- // If successful, 'attr' will contain at least the
- // _A_SUBDIR bit mask
-
- _dos_getfileattr( "\\foo", &attr );
-
- // Mask in new attributes and remove _A_SUBDIR from the old
- // attribute
-
- newattr = (attr | _A_HIDDEN | _A_SYSTEM | _A_RDONLY)
- & ~_A_SUBDIR;
-
- // Set new attribute for 'foo'
-
- _dos_setfileattr( "\\foo", newattr );
- }
- else // Here is the same using OS/2 APIs
- {
- DosQFileMode( "\\foo", &attr, 0L );
-
- newattr = (attr | FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY)
- & ~FILE_DIRECTORY;
-
- DosSetFileMode( "\\foo", newattr, 0L );
- }
- }
-
-
- 576. Getting to the Mouse from a Real-Mode C Program
-
- Product Version(s): 3.00 4.00 5.00 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 6-FEB-1991 ArticleIdent: Q12012
-
- Question:
-
- I am trying to access the mouse from a C program. Do you have an
- example to help get me started?
-
- Response:
-
- Below is a program example to test mouse usage from a C program. The
- mouse driver must be installed first. This type of information is
- described in the "Mouse Programming Interface" chapter of the
- "Microsoft Mouse Programmer's Reference" available from Microsoft
- Press.
-
- Sample Code
- -----------
-
- #include <stdio.h>
- #include <dos.h>
-
- int m1=0,m2=0,m3=0,m4=0;
- union REGS Mouse_regs;
-
- void mouse(void)
- {
- Mouse_regs.x.ax=m1;
- Mouse_regs.x.bx=m2;
- Mouse_regs.x.cx=m3;
- Mouse_regs.x.dx=m4;
- int86(0x33,&Mouse_regs,&Mouse_regs);
- m1=Mouse_regs.x.ax;
- m2=Mouse_regs.x.bx;
- m3=Mouse_regs.x.cx;
- m4=Mouse_regs.x.dx;
- }
-
- void main(void)
- {
- /* Turn on the mouse */
- m1 = 1; /* SHOW MOUSE Opcode -- See reference */
- m2 = m3 = m4 = 0; /* Additional parameters (init=0) */
- mouse(); /* Make it happen */
-
- for (;;) /* loop until both buttons are down */
- {
- m1=3; /* Get mouse status */
- m2=m3=m4=0;
- mouse();
-
- if (m2 & 1)
- printf("Left button down\n");
- if (m2 & 2)
- printf("Right button down\n");
- if (m2 & 1 && m2 & 2)
- {
- printf("BOTH!\n");
- exit(0);
- }
- }
- }
-
-
- 577. Retrieving a Disk's Volume Serial Number from C
-
- Product Version(s): 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 25-FEB-1991 ArticleIdent: Q69223
-
- Beginning with MS-DOS 4.00, a semi-random 32-bit binary identification
- number (ID) is assigned to each disk that DOS formats. The volume
- serial number (or ID) is stored at offset 27H to 2AH in the boot
- sector of each disk. The following program illustrates how to retrieve
- this information:
-
- /***************************************************************/
- /* */
- /* This program reads the volume serial number (or ID) from */
- /* the boot sector of a specified disk. The DOS interrupt 25 */
- /* Absolute Disk Read is used to read in the boot sector. */
- /* */
- /* Note: The volume ID is only implemented from MS-DOS 4.00 */
- /* and later. */
- /* */
- /* The output consists of the OEM name and version of the */
- /* disk-formatting program (stored at offset 03H to 0AH in the */
- /* boot sector), the disk volume label, and the disk-volume */
- /* serial number. */
- /* */
- /***************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include <conio.h>
-
- char bootsector[1024];
- char volume[12];
- char ver[9];
- char block[10];
-
- void main(void)
- {
- int ax, _far *p, drive;
- struct find_t fileinfo;
- char filename[13], _far *foo, _far *q;
- union REGS inregs, outregs;
- struct SREGS segregs;
-
- printf("Enter drive number (0=A,1=B,2=C, ...): ");
- drive=getche() - '0';
-
- /**************************************/
- /* Parameter block for int 25H */
- /* Bytes Description */
- /* ------- ----------- */
- /* 00H-03H 32-bit sector number */
- /* 04H-05H Number of sectors to read */
- /* 06H-07H Offset of buffer */
- /* 08H-09H Segment of buffer */
- /**************************************/
-
- block[0]=block[1]=block[2]=block[3]=0;
- block[4]=1;
- block[5]=0;
-
- foo=bootsector;
-
- p=(int *)&block[6];
- *p=FP_OFF(foo);
-
- p=(int *)&block[8];
- *p=FP_SEG(foo);
-
- q=block;
- inregs.h.al=(char) drive;
- inregs.x.cx=-1;
- inregs.x.bx=FP_OFF(q);
- segregs.ds=FP_SEG(q);
- ax=int86x(0x25, &inregs, &outregs, &segregs);
-
- /*** Error routine ***/
-
- if(outregs.x.cflag)
- {
- printf("\n\nerror on int 25\n");
- printf("this is AX:%04X",ax);
- exit(-1);
- }
-
- /*** Output ***/
-
- printf("\n\nDrive %c\n-------\n\n", drive +'A');
-
- strncpy(ver, &bootsector[3], 8);
- printf("OEM name and version: %s\n", ver);
-
- /* Use _dos_findfirst for the volume label */
-
- filename[0]=(char) (drive + 'A');
- filename[1]='\0';
- strcat(filename, ":\\*.*");
- if(!_dos_findfirst(filename, _A_VOLID, &fileinfo))
- printf("Volume name : %s\n",fileinfo.name);
-
- /* Before printing serial number, check if version >= 4.x */
-
- if((ver[6]=='.')&&(ver[5]>='4')&&(ver[5]<='9'))
- printf("Serial number : %02X%02X-%02X%02X\n\n",
- (unsigned char) bootsector[0x2a],
- (unsigned char) bootsector[0x29],
- (unsigned char) bootsector[0x28],
- (unsigned char) bootsector[0x27]);
- }
-
-
- 578. Comments in .COD Listing Are Wrong When Using _fastcall
-
- Product Version(s): 6.00a | 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00a fastcall
- Last Modified: 30-JAN-1991 ArticleIdent: Q67513
-
- When using the code below with the _fastcall keyword, and compiling
- with the /Fc option for a code listing, the listing generates correct
- code but incorrectly comments the values that are being pushed.
-
- Using the /Gs (recommended for using _fastcall) and /Fc compile-line
- options will generate a code listing that produces wrong comments for
- the following statements:
-
- mov ch, byte ptr top
- mov cl, byte ptr left
- mov dh, byte ptr bot
-
- The code listing below shows the incorrect comments that are
- generated:
-
- ;|*** mov al, byte ptr lines
- ; Line 13
- *** 000018 8a 46 06 mov al,BYTE PTR [bp+6] ;lines
- ;|*** mov bh, byte ptr attr
- ; Line 14
- *** 00001b 8a 7e fe mov bh,BYTE PTR [bp-2] ;attr
- ;|*** mov ch, byte ptr top
- ; Line 15
- *** 00001e 8a 6e fe mov ch,BYTE PTR [bp-8]
- ;|*** mov cl, byte ptr left
- ; Line 16
- *** 000021 8a 4e fa mov cl,BYTE PTR [bp-6] ;top
- ;|*** mov dh, byte ptr bot
- ; Line 17
- *** 000024 8a 76 fc mov dh,BYTE PTR [bp-4] ;left
- ;|*** mov dl, byte ptr right
- ; Line 18
- *** 000027 8a 56 08 mov dl,BYTE PTR [bp+8] ;right
-
- Notice that the comments after the ch, cl, dh mov statements are not
- the same variable names that were actually moved into these registers.
- For instance, the statement
-
- mov ch, byte ptr top
-
- has no comment after it stating what variable was used. However, the
- statement
-
- mov cl, byte ptr left
-
- has a comment of ";top" stating that top was moved in. Obviously,
- "top" was moved into the ch register in the previous statement.
-
- Note: The generated code in this listing, as well as in the OBJ, is
- correct.
-
- Sample Code
- -----------
-
- static void _fastcall scr_scroll
- (int top, int left, int bot, int right, int lines, int dir)
- {
- char attr = 7;
-
- _asm
- {
- mov ah, byte ptr dir
- or ah, ah
- mov ah, 7
- jnz around
- dec ah
- around:
- mov al, byte ptr lines
- mov bh, byte ptr attr
- mov ch, byte ptr top
- mov cl, byte ptr left
- mov dh, byte ptr bot
- mov dl, byte ptr right
- int 0x10
- }
- }
-
- void main(void)
- {
- int t=0,l=0,b=0,r=0,li=0,d=0;
- scr_scroll(t,l,b,r,li,d);
- }
-
- Microsoft has confirmed this to be a problem in the C version 6.00a.
- We are researching this problem and will post new information here as
- it becomes available.
-
-
- 579. Directly Accessing Video Memory from a C Program
-
- Product Version(s): 3.00 4.00 5.00 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 6-FEB-1991 ArticleIdent: Q12010
-
- Question:
-
- How can we access the video memory bytes located in segment B800
- offset 0? We want to move blocks of bytes directly to the graphic
- system memory in a C program.
-
- Response:
-
- When programs access special memory directly, they become less
- portable, and may not run as expected on other or future machines.
- Given this warning, the sample code below is a function that directly
- accesses video memory.
-
- Sample Code
- -----------
-
- /* Video.c -- Function to place a character and its standard
- attribute into the desired video memory page.
-
- Note: This function assumes that the display is set to
- Color or Monochrome, 80 column, text mode.
- */
-
- #include <dos.h>
-
- #define MAKELONG(a, b) ((long)(((unsigned)a) \
- | ((unsigned long)((unsigned)b)) << 16))
- #define COLORTEXT_BUFFER 0XB800
-
- void video(int pageno, int row, int col, char *ch, char attrib)
- /* pageno : page number to load character into (0 to 3) */
- /* row : row of location 0 to 24 */
- /* col : column of location 0 to 79 */
- /* ch : character to be placed there */
- /* attrib : standard character attribute */
- {
- unsigned int offset; /* Offset from the segment address of
- the desired video page */
- char far *y; /* Long Pointer to the position in memory
- where we will put the character and
- it's attribute (next byte) */
-
- /* Calc the in-page offset w/page number offset and segment address */
- offset = (unsigned int) ((row * 160 )+(col*2)+(pageno*4096));
-
- /* Set the character. */
- y = (char far *)MAKELONG( offset, COLORTEXT_BUFFER);
- *y = *ch;
-
- /* Set the attribute byte. See a DOS programmers reference for
- more information on video attributes. */
- offset++;
- y = (char far *)MAKELONG( offset, COLORTEXT_BUFFER);
- *y = attrib;
- }
-
-
- 580. C1001: Internal Compiler Error: regMD.c, Lines 3881 and 3837
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 25-FEB-1991 ArticleIdent: Q69224
-
- The C version 6.00a compiler produces the following internal compiler
- error when the sample program below is compiled with the intrinsic
- optimization (/Oi):
-
- file.c(7) : fatal error C1001: Internal Compiler Error
- (compiler file '@(#)regMD.c:1.110', line 3881)
- Contact Microsoft Product Support Services
-
- With C version 6.00, the error is the same, except it is line 3837.
-
- Using the function version of strlen() eliminates the problem.
-
- Microsoft has confirmed this to be a problem in the C compiler
- versions 6.00 and 6.00a. We are researching this problem and will post
- new information here as it becomes available.
-
- Sample Code
- -----------
-
- #include <stdio.h>
-
- void main(void)
- {
- char * string;
- int j;
-
- j = 8 * strlen(string);
- }
-
-
- 581. Questions and Answers About the Use of malloc() and _fmalloc()
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1991 ArticleIdent: Q12159
-
- Question:
-
- I am designing a product using the medium model, but need some dynamic
- memory larger than the default segment for temporary storage and
- semi-permanent main data structures. Things seem to be working
- properly, but I have the following questions:
-
- 1. Can malloc() and _fmalloc() be used together without restriction,
- for example, using malloc() for the temporary data and _fmalloc()
- for the semi-permanent data?
-
- 2. Are there ever any user-visible delays for garbage collection
- (compression of string space)?
-
- 3. Are there fragmentation risks? In experimenting with _fmalloc(), it
- appears that contiguous blocks freed at different times are
- automatically consolidated, which should reduce the fragmentation
- risk.
-
- 4. Does _fmalloc() ensure that any single assignment is within one
- data segment (so assembly move/access routines need not deal with
- segment boundaries)?
-
- Response:
-
- 1. Yes, malloc() and _fmalloc() may be used together. They both track
- their memory allocation separately and, in fact, you must use two
- different functions to free the allocated data: free() and _ffree()
- respectively.
-
- 2. The malloc() functions do not perform any form of garbage
- collection. You allocate the space and you decide when it is to be
- freed up for later usage. Therefore, there will be no visible or
- unexpected time delays during execution.
-
- 3. The _fmalloc() function will consolidate adjacent free blocks. This
- reduces the risk of fragmentation problems.
-
- 4. The _fmalloc() function will not allocate across segment
- boundaries. Only halloc() (the huge-model memory allocation
- routine) can perform this function. Therefore you are assured that
- no one allocation will cross a segment boundary (because it cannot
- allocate larger then 64K).
-
-
- 582. Use Timer Interrupt to Maintain Time Independent of CPU Speed
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1991 ArticleIdent: Q12131
-
- Question:
-
- Is there a way to set up a function that will pause for n units of
- time without being altered on a faster or slower machine (for example,
- from a PC to an AT).
-
- Response:
-
- Set up a routine to handle the timer tick interrupt. This will be the
- same on all machines (about 18.2 times per second with interrupts
- enabled). The timer tick is interrupt 1C and can be modified for
- access by your own routine.
-
-
- 583. _bheapseg: Return Value Documented Incorrectly
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 25-FEB-1991 ArticleIdent: Q69237
-
- The return value for the _bheapseg function is documented incorrectly
- on page 147 of the "Microsoft C Reference," in the online help for C
- 6.00, and in the online help for QuickC versions 2.50 and 2.51.
-
- On page 147 of the "Microsoft C Reference," the line that reads
-
- Returns The selector for the newly allocated segment
- if successful; -1 if not.
-
- should read as follows:
-
- Returns The selector for the newly allocated segment
- if successful; 0 (_NULLSEG) if not.
-
- The online help mentions the correct return value for the _bheapseg
- function in the "Summary" section, except that it specifies NULLSEG
- instead of _NULLSEG. The paragraph in the "Description" section titled
- "Return Value" incorrectly documents the return value as -1.
-
-
- 584. Call ROM BIOS Routines to Check the Printer Status
-
- Product Version(s): 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 15-JAN-1991 ArticleIdent: Q12110
-
- Question:
-
- We are sending text to the printer using fopen("prn","w"). Many of our
- clients get the following message:
-
- Writing error on device PRN -- abort, retry, ignore.
-
- How can we check the printer status so that we can avoid this?
-
- Response:
-
- Although there is no portable method for checking printer status in C,
- you can get printer status information via the ROM BIOS. You can
- obtain status information by calling _bios_printer(), which is an
- interface to INT 17H, function 2. You can also call BIOS interrupt
- functions through the int86() functions. See the online help or the
- run-time library reference for your version of the compiler for more
- information about these functions.
-
- You may want to handle the error by revectoring the critical error
- handler interrupt (24H), which will allow you to intercept the "abort,
- retry" message before the user receives it. You then can decide
- whether to substitute your own message, such as "Printer off line: set
- printer on line and press Y to continue."
-
- More information on the ROM BIOS routines and interrupt handlers can
- be found in the following two books from Microsoft Press:
-
- 1. "The Peter Norton Programmer's Guide to the IBM PC" (r)
-
- 2. "Advanced MS-DOS" by Ray Duncan
-
-
- 585. C1001: Internal Compiler Error: exphelp.c, Line 617
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 25-FEB-1991 ArticleIdent: Q69289
-
- The Microsoft C Compiler versions 6.00 and 6.00a produce the following
- internal compiler error when the sample program below is compiled with
- default optimization and large memory model (/AL):
-
- mem2.c(4) : fatal error C1001: Internal Compiler Error
- (compiler file '@(#)exphelp.c:1.117', line 617)
- Contact Microsoft Product Support Services
-
- The above error occurs only when using any one of the optimizations
- /Oi, /Oa, /Oc, /On, /Op, /Or, /Os, /Ot, /Ow, /Oz, or using default
- optimizations. Furthermore, the source must be compiled in compact,
- large, or huge memory models.
-
- To work around the problem, compile without using default
- optimizations or any of the above mentioned options. You may elect to
- disable optimizations for the function that is producing the error. Do
- this by using the "optimize" pragma. Another valid workaround is to
- compile using the /qc (Quick Compile) option, which also does not
- produce the error.
-
- Sample Code
- -----------
-
- /* Compile with /AL */
-
- void func(int *memoryPtr,unsigned long pageLow)
- {
- if ((*memoryPtr)>0)
- pageLow=(unsigned long)memoryPtr>>28;
- }
-
- Microsoft has confirmed this to be a problem in C versions 6.00 and
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
-
- 586. Bad Code Generated for Function Returning _self Based Pointer
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 30-JAN-1991 ArticleIdent: Q67612
-
- The C versions 6.00 and 6.00a compilers will generate incorrect code
- for a function that returns a pointer based on self. The code
- generated for the return statement introduces an extra level of
- indirection.
-
- Microsoft has confirmed this to be a problem in C versions 6.00 and
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
- The following program fragment demonstrates this problem. Compile the
- code with the /Fc option to generate an assembly listing, and observe
- the code in the resulting .COD file for the return statement in the
- function test().
-
- struct foo {
- int _based((_segment) _self) *pbs;
- } far *pfoo;
-
- int far *test(void)
- {
- return(pfoo->pbs);
- }
-
-
- 587. Use the signal() Function to Trap Floating-Point Exceptions
-
- Product Version(s): 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1991 ArticleIdent: Q12127
-
- Question:
-
- Is there a way that I can trap all possible floating point exceptions
- in a C program?
-
- Response:
-
- The C signal() function allows the capture of floating-point
- exceptions.
-
- For more information on the signal() function, see the run-time
- library reference or the online help that accompanies your compiler.
-
-
- 588. Promotion of char to int May Add Two Hex Digits in printf()
-
- Product Version(s): 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc hexidecimal conversion
- Last Modified: 25-FEB-1991 ArticleIdent: Q69344
-
- When trying to display a signed char in two-digit hexadecimal format, as
- follows
-
- char hex_byte = 0x80;
- printf( "The Hex value is %X", hex_byte);
-
- four digits will be displayed if the char has a value of 0x80 to 0xFF
- because of promotion of the char to a signed int. The %x and %X
- specifiers designate an unsigned hex integer, but because leading 0's
- (zeros) are dropped, values in the range of 0 to 127 produce the
- desired two digits. See the sample code below.
-
- To preserve the two-digit display for all possible values, just
- typecast the char to an unsigned char in the printf() argument list,
- as shown below:
-
- printf( "The Hex value is %X", (unsigned char)hex_byte);
-
- Another way to achieve this, if sign is of no consequence, is to
- declare the variables as unsigned char.
-
- For ANSI compliance, the compiler promotes all char arguments to
- signed int. If the type is signed char, then the value will be
- sign-extended. Thus, the int will be negative if the left-most bit of
- the char was set, resulting in a different value for the int. When an
- unsigned char is promoted, a 0 (zero) is placed in the high byte so
- that the value is retained.
-
- This promotion may also cause problems with comparisons of signed and
- unsigned chars. This situation, unlike the printf() situation, will
- produce a C4018 (signed/unsigned mismatch) warning at warning level 3
- and above, beginning with C version 6.00.
-
- This behavior is also observed in QuickC versions 2.00 and 2.50 and
- QuickC with QuickAssembler versions 2.01 and 2.51.
-
- Sample Code
- -----------
-
- #include <stdio.h>
-
- void main( void)
- {
- char goo = 127;
- char foo = 128;
-
- printf( "goo = %X\n", goo); /* yields "7F" */
- printf( "foo = %X\n", foo); /* yields "FF80" */
-
- /* correct way to represent the char as two hex digits "80" */
- printf( "foo = %X\n", (unsigned char)foo);
- }
-
-
- 589. File Component Constants Increased Beginning with C 6.00
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 25-FEB-1991 ArticleIdent: Q69349
-
- The following manifest constants (found in STDLIB.H) were changed
- beginning with C version 6.00:
-
- _MAX_PATH 260 /* max. length of full pathname */
- _MAX_DRIVE 3 /* max. length of drive component */
- _MAX_DIR 256 /* max. length of path component */
- _MAX_FNAME 256 /* max. length of filename component */
- _MAX_EXT 256 /* max. length of extension component */
-
- Prior to C 6.00, these constants were defined as follows:
-
- _MAX_PATH 144
- _MAX_DRIVE 3
- _MAX_DIR 130
- _MAX_FNAME 9
- _MAX_EXT 5
-
- These changes may cause unexpected results if filenames longer than
- eight characters are entered for use under DOS. The sample code below
- demonstrates the differences.
-
- The changes in the constants were made to allow for longer filenames
- and extensions in future operating systems, as well as the current
- implementation of the High Performance File System (HPFS) introduced
- in OS/2 version 1.20. The potential for problems is greatest when
- buffers are used that are not as big as the new constant values. This
- generally occurs when porting code from a previous version of the
- compiler to C version 6.00 or later.
-
- There are several ways to protect against problems that may occur in
- your code because of this change:
-
- 1. Always declare filename buffers with the actual constants, for
- example:
-
- char file_name[_MAX_FNAME];
-
- 2. Provide error checking before file operations are performed, such
- as:
-
- #define DOS_FILE_NAME_LENGTH 8
-
- if ( strlen(file_name) > DOS_FILE_NAME_LENGTH )
- printf("File name too long, try again");
-
- 3. In extreme cases, you can change the constants in STDLIB.H back to
- the previous values, but this will also require the purchase of the
- Microsoft C run-time library source code so that you may rebuild
- the affected modules in the run-time library. The one advantage of
- this method is that it saves the memory used by buffers declared
- with the larger values (840 bytes).
-
- The sample program below prompts for a filename to be input. If the
- input file specification is
-
- C:\PATHPATHPATH\NAMENAMENAME.EXTEXT
-
- then the output with C version 5.10 will be
-
- Old path was : C:\PATHPATHPATH\NAMENAMENAME.EXTEXT
- Drive is : C:
- Dir is : \PATHPATHPATH\
- Fname is : NAMENAME
- Extension is : .EXT
- New path is : C:\PATHPATHPATH\NAMENAME.EXT
-
- while, with C version 6.00, the ouput will be:
-
- Old path was : C:\PATHPATHPATH\NAMENAMENAME.EXTEXT
- Drive is : C:
- Dir is : \PATHPATHPATH\
- Fname is : NAMENAMENAME
- Extension is : .EXTEXT
- New path is : C:\PATHPATHPATH\NAMENAMENAME.EXTEXT
-
- Notice that in C 5.10, the name is truncated to eight characters and
- the extension is truncated to three characters (plus the period),
- while in C 6.00 the name and extension are left unchanged.
-
- Note that these same new larger constants are present in QuickC
- beginning with versions 2.50 and 2.51 because these packages share
- the same include files as C 6.00.
-
- Sample Code
- -----------
-
- /* Compile options needed: none
- */
- #include <stdio.h>
- #include <stdlib.h>
-
- void main( void)
- {
- char oldpath[_MAX_PATH];
- char newpath[_MAX_PATH];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char fname[_MAX_FNAME];
- char ext[_MAX_EXT];
-
- printf( "Enter a file name: " );
- gets( oldpath );
-
- _splitpath( oldpath, drive, dir, fname, ext );
- _makepath( newpath, drive, dir, fname, ext );
-
- printf( "Old path was : %s\n", oldpath);
- printf( "Drive is : %s\n", drive);
- printf( "Dir is : %s\n", dir);
- printf( "Fname is : %s\n", fname);
- printf( "Extension is : %s\n", ext);
- printf( "New path is : %s\n", newpath);
- }
-
-
- 590. CHRTDEMO Example Gives C2059 Error with ANSI Compatibility Set
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc chartdemo pgchart
- Last Modified: 25-FEB-1991 ArticleIdent: Q69350
-
- If the C version 6.00 sample Presentation Graphics program CHRTDEMO.C
- is compiled with the ANSI compatibility switch (/Za), the following
- compiler error will be produced:
-
- chrtdemo.h(140) : error C2059: syntax error : '*'
-
- This is correct behavior due to the use of the Microsoft extension
- "far" found on line 140 of CHRTDEMO.H; /Za disables extensions
- specific to Microsoft C.
-
- The supplied CHRTDEMO.MAK makefile is set up to use the default
- setting of /Ze (Microsoft C extensions enabled). The C2059 error will
- only occur if this option is changed to /Za (ANSI compatibility --
- Microsoft C extensions disabled). This change could be made either
- inside the Programmer's WorkBench from the C Compiler Options dialog
- box or by actually modifying the makefile to include /Za in the
- compiler flags macro.
-
- According to the ANSI specification, all keywords that are extensions
- to the language must begin with a leading underscore. Beginning with C
- version 6.00, the Microsoft supplied header files contain this change
- to all keywords, such as _far, _pascal, etc., but the previous
- versions of these keywords without the leading underscores are
- retained for backwards compatibility.
-
- Most of the sample programs were modified to include the new keywords,
- but the line in CHRTDEMO.H was not changed to include _far, instead of
- far, thus resulting in the C2059 error with /Za. If you modify the far
- keyword on line 140 of CHRTDEMO.H so that it includes a leading
- underscore, this will eliminate the C2059 error even when /Za is
- specified.
-
- The QuickC compiler shares the same ANSI compatibility mode as the
- optimizing compiler, as well as a similar chart example program. Thus,
- the same C2059 error may be encountered with /Za in QuickC versions
- 2.00, 2.01, 2.50, and 2.51.
-
-
- 591. Dividing Negative Integers May Give Positive Results
-
- Product Version(s): 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist5.10 buglist6.00 buglist6.00a
- Last Modified: 30-JAN-1991 ArticleIdent: Q67740
-
- In some situations, dividing a negative integer by a positive integer
- may give positive results. For example, when the following code is
- compiled with the /Od option, both printf() statements will generate
- positive answers.
-
- Code Example
- ------------
-
- void foo(void)
- {
- int num1 = -32768,
- num2 = -32751;
-
- printf(" %d ", num1 / 16);
- printf(" %d ", (num2 & 0xfff0) / 16);
- }
-
- When these calculations are performed, the sign bit is lost. The
- output is incorrect for the first printf() statement when -32768 is
- being divided by a power of 2 (for example, 4,8,16,32,64,...16384).
-
- Workarounds for the first printf() statement are:
-
- 1. Compile without the /Od option.
-
- 2. Compile with the /qc option.
-
- With the second printf(), the value (num2 & 0xfff0) must be typecast
- to an integer or separated into another statement. For example,
-
- printf(" %d ", (int)(num2 & 0xfff0) / 16);
-
- -or-
-
- num3 = num2 & 0xfff0;
- printf(" %d ", num3 / 16);
-
- Microsoft has confirmed this to be a problem in the C versions 5.10,
- 6.00, and 6.00a. We are researching this problem and will post new
- information here as it becomes available.
-
-
- 592. C1001: Internal Compiler Error: grammar.c, Line 140
-
- Product Version(s): 6.00a | 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00a
- Last Modified: 31-JAN-1991 ArticleIdent: Q67781
-
- The C version 6.00a compiler produces the following internal compiler
- error when the sample program below is compiled the /Ox or /Oe
- optimizations:
-
- foo.c(9):fatal error C1001:Internal Compiler Error
- (compiler file '../grammar.c', line 140)
- Contact Microsoft Product Support Services
-
- The following are valid workarounds for this problem:
-
- 1. Compile with any optimization not containing /Oe.
-
- 2. Disable the "e" optimization using the optimize pragma.
-
- Sample Code
- -----------
-
- 1 typedef struct utype { char bitmap[10]; } Utype;
- 2 extern Utype utypes[];
- 3
- 4 void InitializeBitmaps(void)
- 5 {
- 6 int cnt,cnt2;
- 7 for(cnt=0;cnt<13;cnt++)
- 8 for(cnt2=0;cnt2<10;cnt2++)
- 9 utypes[cnt].bitmap[cnt2]=(char)~utypes[cnt].bitmap[cnt2];
- 10 }
-
- Microsoft has confirmed this to be a problem in Microsoft C version
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
-
- 593. C1001: Internal Compiler Error: regMD.c, Lines 3101 and 3074
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 25-FEB-1991 ArticleIdent: Q69413
-
- The Microsoft C Compiler versions 6.00 and 6.00a produce the following
- internal compiler errors when the sample program below is compiled
- with default optimization:
-
- With C 6.00a
- ------------
-
- file.c(5) : fatal error C1001: Internal Compiler Error
- (compiler file '@(#)regMD.c:1.110', line 3101)
- Contact Microsoft Product Support Services
-
- With C 6.00
- -----------
-
- file.c(5) : fatal error C1001: Internal Compiler Error
- (compiler file '@(#)regMD.c:1.100', line 3074)
- Contact Microsoft Product Support Services
-
- These errors will occur under any memory model when using any one of
- the following optimizations (although the errors may not occur when
- some of these options are combined):
-
- /Oa, /Oc, /Od, /Oi, /On, /Op, /Or, /Os, /Ot, /Ow, or /Oz
-
- There are several possible ways to work around these errors:
-
- 1. Do not use any of the above options and do not use the default
- optimization for the module where the error occurs.
-
- 2. Add /Oe or /Og; one of these combined with other optimizations
- may eliminate the problem.
-
- 3. Selectively disable optimizations for the particular function that
- is producing the error through use of the optimize pragma.
-
- 4. Rewrite the statement to use an if-else construct instead of the
- ternary operator.
-
- Microsoft has confirmed this to be a problem in C versions 6.00 and
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
- Sample Code
- -----------
-
- /* Compile options needed: none
- */
-
- void func(unsigned char uch1, unsigned char uch2)
- {
- uch2 = uch1 ? (unsigned char)'0' : (unsigned char)(uch1 % 24);
- }
-
-
- 594. Old Compiler Pass May Cause C1007: Unrecognized Flag -Bm in P2
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 25-FEB-1991 ArticleIdent: Q69474
-
- If you receive the following error when compiling a program with C
- version 6.00 or 6.00a
-
- fatal error C1007: unrecognized flag '-Bm' in 'p2'
-
- it may be the result of inadvertently invoking pass 2 (C2.EXE) of an
- earlier version of the compiler, such as C version 5.10. Beginning
- with C version 6.00, the option -Bm is a valid flag for pass 2 of the
- compiler. This was not a valid option in earlier compiler versions.
-
- When looking for an executable file, the operating system will first
- search your current directory, and then search all the directories
- listed in your path. You should make sure that the C 6.00 compiler is
- listed first on your path, before any other versions of the compiler.
- This is especially true when running on a network because network
- search paths sometimes obscure exactly what directories are being
- searched for files.
-
- If you would like to double-check which drive and directory are being
- used when compiling, invoke the compiler with the /d option. This
- option displays the information that is being passed to each phase of
- the compiler, including the name and directory of the compiler file in
- use.
-
-
- 595. _getpixel() Return Value is Not Changed by _setbkcolor() Call
-
- Product Version(s): 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 6-FEB-1991 ArticleIdent: Q67759
-
- In the sample program below, _getpixel() will return a 0 (zero).
- Setting _setbkcolor() to any other color has no effect on the return
- value from _getpixel().
-
- The _getpixel() function is documented as returning a color index for
- a specific pixel. In the example program, there are no colors on the
- screen except the background color (color index 0). When the call to
- _setbkcolor() is made, the color mapped to index 0 is changed;
- however, the color index for the pixel is not changed. Therefore,
- _getpixel() still returns 0. This same behavior is exhibited when
- using the _remappallette() function on index 0 and the
- _remapallpallette() function.
-
- To change the color index at a particular point on the screen, first
- call the _setcolor() function with the desired color index, then use
- one of the graphics drawing functions, for example, _floodfill(),
- _setpixel(), etc.
-
- Sample Code
- -----------
-
- // Note: C 5.10 doesn't support _MAXRESMODE
-
- #include<graph.h>
- #include<stdio.h>
- void main(void)
- {
- short xvar=100,yvar=100,result1=0,result2=0;
- _setvideomode(_MAXRESMODE);
- result1=_getpixel(xvar,yvar);
- _setbkcolor(_BLUE);
- result2=_getpixel(xvar,yvar);
- _setvideomode(_DEFAULTMODE);
- printf("Before _setbkcolor - %d\n",result1);
- printf("After _setbkcolor - %d\n",result2);
- }
-
-
- 596. stdout/stderr Are Buffered When Stack Is Moved Out of DGROUP
-
- Product Version(s): 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 25-FEB-1991 ArticleIdent: Q69476
-
- By following the instructions in the C 6.00 STARTUP.DOC file, you can
- recompile/reassemble the C start-up code and modify existing libraries
- so that the stack will be moved out of DGROUP for programs linked with
- these modified libraries. When using the DOS version of these modified
- libraries, stdout and stderr are unexpectedly buffered. The sample
- code and sample output below illustrate this problem.
-
- The OS/2 versions of the modified libraries perform as expected;
- however, to achieve the correct behavior with the DOS versions of the
- modified libraries, you must add the following line to your code:
-
- setvbuf(stdout, NULL, _IONBF, 0);
-
- This line sets buffering for streams to none.
-
- Information about the predefined stream pointers can be observed by
- compiling the start-up code with CodeView information and placing a
- watch on the _iob2 array. Information about stdout is in _iob2[1].
- After executing the start-up code, the buffer size on stdout is still
- 0 (zero); however, once a function call is made to printf(), the
- buffer size for _iob2[1] is changed to 512 (0x200) bytes. This change
- does not occur when the stack is left in DGROUP.
-
- Microsoft has confirmed this to be a problem in C versions 6.00 and
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
- Sample Code
- -----------
-
- /* Compile options needed: /c /ALw /Zi /Od
- Link options needed: /CO /NOD (plus you must specify the
- modified DOS C run-time library)
- */
-
- #include <stdio.h>
-
- int number;
-
- void main(void)
- {
- /* Uncomment the following line to obtain the desired results */
- /* setvbuf(stdout, NULL, _IONBF, 0); */
-
- printf("\nEnter a number: ");
- scanf("%d", &number);
- printf("\nThe number is %1d\n", number);
- }
-
- Program Output
- --------------
-
- 22 /* user enters a number (without prompt) */
-
- Enter a number: /* printf() output is buffered, so output does */
- The number is 22 /* not appear until exit code flushes buffers */
-
-
- 597. _bios_disk() May Require 3 Tries for Drive to Get Up to Speed
-
- Product Version(s): 4.00 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 25-FEB-1991 ArticleIdent: Q69504
-
- The _bios_disk() routine in the C run-time library uses BIOS interrupt
- 0x13 to provide several disk-access functions. The ROM BIOS does not
- automatically wait for the drive to come up to speed before attempting
- to read the sector, verify the sector, or write to the sector. In the
- book "IBM ROM BIOS" by Ray Duncan, the recommendation given in each
- case is to reset the floppy disk system and try the operation three
- times before assuming an error has occurred.
-
- The following sample program from the C 6.00 online help makes three
- attempts to read the disk before giving up. A printf() statement is
- added to show which read attempt is successful.
-
- Sample Code
- -----------
-
- /* Compile options needed: none
- */
-
- #include <stdio.h>
- #include <conio.h>
- #include <bios.h>
- #include <dos.h>
- #include <stdlib.h>
-
- char _far diskbuf[512];
-
- void main( int argc, char *argv[] )
- {
- int count;
- unsigned status = 0, i;
- struct diskinfo_t di;
- struct diskfree_t df;
- unsigned char _far *p, linebuf[17];
-
- if( argc != 5 )
- {
- printf(" SYNTAX: DISK <driveletter> <head> <track> <sector>");
- exit( 1 );
- }
-
- if( (di.drive = toupper( argv[1][0] ) - 'A' ) > 1 )
- {
- printf( "Must be floppy drive" );
- exit( 1 );
- }
-
- di.head = atoi( argv[2] );
- di.track = atoi( argv[3] );
- di.sector = atoi( argv[4] );
- di.nsectors = 1;
- di.buffer = diskbuf;
-
- // Get information about disk size.
-
- if( _dos_getdiskfree( di.drive + 1, &df ) )
- exit( 1 );
-
- // Try reading disk three times before giving up.
-
- for( count = 1; count <= 3; count++ )
- {
- status = _bios_disk( _DISK_READ, &di ) >> 8;
- if( !status )
- break;
- }
-
- // Display one sector.
- if( status )
- printf( "Error: 0x%.2x\n", status );
- else
- {
- for(p=diskbuf, i=0; p < (diskbuf+df.bytes_per_sector); p++)
- {
- linebuf[i++] = (*p > 32) ? *p : '.';
- printf( "%.2x ", *p );
- if( i == 16 )
- {
- linebuf[i] = '\0';
- printf( " %16s\n", linebuf );
- i = 0;
- }
- }
- }
-
- // Which attempt was successful?
-
- printf( "\nThat was try #%d.\n", count );
-
- exit( 1 );
- }
-
-
- 598. C Compiler May Give Wrong Line Number for a C2125 Error
-
- Product Version(s): 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist5.10 buglist6.00 buglist6.00a
- Last Modified: 25-FEB-1991 ArticleIdent: Q69538
-
- The C compiler will correctly produce a "C2125: allocation exceeds
- 64K" error for an array larger than 64K that is not declared as huge
- or compiled for the huge memory model. However, the line number that
- the compiler displays for the error is incorrect. The sample program
- below demonstrates this problem.
-
- The following error message shows the incorrect line number generated
- when the sample code below is compiled with C version 5.10, 6.00, or
- 6.00a:
-
- file.c(7) : error C2125: 'array' : allocation exceeds 64K
-
- The error is actually generated because of the array declaration on
- line 4, but the compiler always lists the line with the opening brace
- for the main() function as the location of the error (line 7 in this
- case).
-
- When the quick compile (/qc) option is specified under C 6.00 or
- 6.00a, the correct line number (line 4) is generated in the error
- message:
-
- test.c(4) : error C2125: 'array' : allocation exceeds 64K
-
- Note that if you are compiling inside the Programmer's WorkBench
- (PWB), the incorrect line number in the error message will cause PWB
- to take you to an incorrect line in the source code when the compiler
- errors are displayed.
-
- Microsoft has confirmed this to be a problem in C versions 5.10, 6.00,
- and 6.00a. We are researching this problem and will post new
- information here as it becomes available.
-
- Sample Code
- -----------
-
- /* Compile options needed: none
- */
-
- char array[100000]; /* Error should be generated for this line (4) */
-
- void main(void)
- { /* Error message refers to this line (7) */
- }
-
-
- 599. _cexit() Does Not Close Files Correctly
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc buglist6.00 buglist6.00a
- Last Modified: 25-FEB-1991 ArticleIdent: Q69539
-
- As stated in the online help, the _cexit() function performs clean-up
- operations and returns without terminating the process. The _cexit()
- function first calls the functions registered by the atexit() and
- onexit() routines, and then it should flush all I/O buffers and close
- all open files before returning.
-
- The _cexit() function works as described except that it does not close
- all the open files. The sample code below demonstrates this problem.
-
- Microsoft has confirmed this to be a problem in C versions 6.00 and
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
- Sample Code
- -----------
-
- *\
-
- #include<stdio.h>
- #include<stdlib.h>
- #include<process.h>
-
- void foo(void);
-
- void main(void)
- {
- FILE *outfile;
- int retval;
-
- atexit(foo); /* set up function to invoke on exit */
-
- if ( (outfile = fopen("TEST.TXT", "w")) == NULL )
- {
- printf("Could not open test file TEST.TXT");
- exit(-1);
- }
-
- retval = fprintf(outfile, "This is line 1.\n");
- if ( retval >= 0 )
- printf("\nFirst line written successfully to file.\n");
- else
- printf("\nFile write failed on first attempt!\n");
-
- _cexit(); /* Call _cexit() -- files should all be closed */
-
- retval = fprintf(outfile, "This line should not be written!\n");
- if ( retval >= 0 )
- printf("Error - Write to file succeeded for file that should"
- " have been closed!\n");
- else
- printf("File write failed on second attempt as expected!\n");
-
- fclose(outfile);
- }
-
- void foo(void)
- {
- printf("\nThis is the exit function code.\n\n");
- }
-
-
- 600. Local Variable Allocation Is Limited to 32K
-
- Product Version(s): 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc stack
- Last Modified: 15-JAN-1991 ArticleIdent: Q19785
-
- The total amount of space that can be allocated for variables local to
- a function is 32K. Trying to allocate more than this will result in
- the following compiler error:
-
- fatal error C1126: automatic allocation exceeds 32K
-
-
- 601. GRAPHICS.LIB Cannot Be Used with Tiny Model
-
- Product Version(s): 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_quickasm
- Last Modified: 6-FEB-1991 ArticleIdent: Q67761
-
- Programs written in the tiny model cannot use the graphics library
- supplied with Microsoft C versions 6.00 and 6.00a. The graphics
- routines are meant to be model-independent, so they are labeled as far
- procedures. The linker does not allow far references in a tiny model
- program and does not resolve the references to the graphics routines.
-
- The sample source code below demonstrates this problem. The program
- should be compiled with:
-
- cl /AT foo.c graphics.lib
-
- For more information on building .COM files, query on the article
- titled "Use of _far Keyword in Tiny Programs."
-
- Sample Code
- -----------
-
- #include <graph.h>
-
- void main(void);
-
- void main()
- {
- _setvideomode(_DEFAULTMODE);
- }
-
-
- 602. C1001: Internal Compiler Error: regMD.c, Line 1017
-
- Product Version(s): 6.00a | 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00a
- Last Modified: 28-DEC-1990 ArticleIdent: Q67778
-
- When compiling with /Oe optimization under the compact or large memory
- models, the code below generates the following internal compiler error
- with Microsoft C version 6.00a:
-
- fatal error c1001: Internal Compiler Error
- (compiler file '@(#)regMD.c:1.110',line 1017)
- Contact Microsoft Product Support Services
-
- Sample Code
- -----------
-
- char hex_digits[]={"f"};
-
- int x(char *resultp, int item)
- {
- char *s;
- int hundreds;
-
- s=resultp;
- hundreds=100;
- if(hundreds)
- *s++='0';
- *s++=' ';
- *s++=hex_digits[item/16];
- *s++=hex_digits[item%16];
- }
-
- The following are valid workarounds for the problem:
-
- 1. Compile without the /Oe optimization.
-
- 2. Use the #pragma optimize switch in the code to turn off the
- offending optimizations for the particular function.
-
- 3. Compile under the small or medium memory models.
-
-
- 603. Jumping into the Middle of a For Loop Is Not Recommended
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1991 ArticleIdent: Q19972
-
- Question:
-
- Under what conditions can a program perform a jump (via goto) into the
- middle of a for loop?
-
- Response:
-
- The only restriction on the goto statement is that the goto statement
- and its corresponding label be located in the same function. However,
- because different compilers optimize for loops differently, using a
- goto to jump into the middle of a for loop is not considered safe or
- portable.
-
- Also, if you are jumping into an inner loop that uses auto variables,
- an additional problem may occur because different compilers allocate
- space for auto variables in loops in different ways.
-
- Essentially, it is risky and not advisable for a program to jump into
- the middle of a for loop.
-
-
- 604. No More Than 255 Modules May Be Placed in Overlays
-
- Product Version(s): 4.00 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_link
- Last Modified: 15-JAN-1991 ArticleIdent: Q22286
-
- Question:
-
- The "too many overlays" error message indicates that my program
- defines more than 63 overlays. Is there also a limitation on the
- number of total modules that can be in overlays?
-
- I have a large C program that contains more than 255 modules in a
- total of 12 overlays. I receive no error messages, however, my link
- map indicates that all modules after the 255th are placed in the root
- instead of the overlays I specified.
-
- Response:
-
- There is a limit of 255 code segments that can be overlayed. Segments
- beyond this limit are put in the root.
-
-
- 605. The Most Common C Programming Errors
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1991 ArticleIdent: Q22321
-
- The following is a list of the most common C programming errors. Any
- of these items could cause unpredictable results, such as trashed data
- or a system hang.
-
- 1. Using auto variables that have not been initialized.
-
- 2. Leaving out the closing comment delimiter.
-
- 3. Over-indexing an array.
-
- 4. Leaving out a semicolon (;) or brace ({}).
-
- 5. Using uninitialized pointers.
-
- 6. Using break with an IF block, since break does not exit out of IF
- blocks. It only breaks you out of WHILE, FOR, or SWITCH loops.
-
- 7. Comparing a char variable against EOF, as in the following
- example:
-
- char c;
- while ((c=getchar()) != EOF)
- {
- }
-
- If c is a char, you cannot test c against EOF because a -1 cannot
- fit into a character, so c must be an int.
-
- 8. Using a forward slash instead of a backslash (for example, /n
- instead of \n).
-
- 9. Using = instead of == in a comparison.
-
- 10. Overwriting the null terminator (the last byte) in a string by
- indexing 1 byte too far.
-
- 11. Placing a semicolon improperly, as in the following example:
-
- void foo(int a,char b); /* semicolon does not belong here */
- { }
-
- 12. Forgetting that scanf() expects addresses.
-
- 13. Using the wrong return value for a function. For example, a
- function that returns a real, but is not declared, will return an
- int by default.
-
- 14. Using expressions with side effects. For example, a[i] = i++; is
- ambiguous.
-
- 15. Forgetting that static variables inside functions are initialized
- only once.
-
- 16. Unintentionally omitting a break from a case label in a switch
- statement, and therefore, falling through to the next case.
-
-
- 606. Internal Representation for NAN or INF Is Coprocessor Specific
-
- Product Version(s): 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | 8087 80x87 80287 80387
- Last Modified: 15-JAN-1991 ArticleIdent: Q22320
-
- The internal representation for a NAN (Not A Number) or INF (Infinity)
- is coprocessor dependent. To obtain this information, we recommend
- that you consult the "Numeric Supplement" in the "Intel iAPX
- Programmer's Reference Manual" for the specific coprocessor chip.
-
-
- 607. "Invalid Object Module" Usually Caused by Old Version of LINK
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 4-DEC-1990 ArticleIdent: Q22331
-
- In many cases, an "invalid object module" error message from the
- linker indicates that an incorrect version of LINK is being utilized.
- Most DOS systems contain a DOS directory listed near the beginning of
- the PATH. Because DOS ships with a version of LINK, this version is
- often picked up instead of the correct version.
-
- To indicate if the wrong linker is the source of an "invalid object
- module" error, perform the following steps:
-
- 1. Change into the language product directory where the version of
- LINK.EXE that came with the compiler you are currently using
- resides.
-
- 2. Type "link" at the DOS prompt.
-
- 3. The copyright banner for LINK will appear. Note the version number
- of LINK that is indicated. (This is the correct version of LINK
- that you should be using.)
-
- 4. Press CTRL+C to exit out of LINK.
-
- 5. Switch to the work directory where you normally compile and link
- your program.
-
- 6. Perform steps 2 through 4 again.
-
- If the version of LINK that comes up in your work directory is
- different than the correct version you first noted in the language
- directory, then you have another version of LINK in a directory in
- your PATH that comes before the directory with the correct version.
-
- If you do find that you are picking up another LINK.EXE on your
- system, you will need to determine where it resides. Most likely, it
- is a DOS linker that came with the operating system because these are
- older versions of LINK that are not well-matched to the newer language
- products. Be aware, however, that it also could be the linker from
- another Microsoft language product. In either case, you should do one
- of the following to correct this problem:
-
- 1. Locate the old linker and rename it to something resembling LINK.OLD.
- It is rare that you would need the DOS linker for anything, but this
- method assures that it will still be available.
-
- 2. Change your path so that your PATH environment variable points
- first to the directory containing the correct version of LINK.EXE.
- This solution is less preferable than the one above because it does
- nothing to ensure that the problem will not appear again if you make
- some changes to your system.
-
- It is not uncommon to have a number of linkers in directories that are
- specified in the PATH. Therefore, it is highly recommended that you
- repeat the version number test from within your work directory once
- you have implemented one of these solutions.
-
-
- 608. C1001: Internal Compiler Error: regMD.c, Lines 3047 and 3020
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 31-JAN-1991 ArticleIdent: Q67779
-
- The sample code below produces the following internal compiler errors
- when compiled under different versions of the C compiler. The problem
- occurs when compiled with the /Og and /Oe optimizations under the
- compact and large memory models.
-
- Under C 6.00a
- -------------
-
- file.c(11) : fatal error C1001: Internal Compiler Error
- (compiler file '@(#)regMD.c:1.110', line 3047)
- Contact Microsoft Product Support Services
-
- Under C 6.00
- ------------
-
- file.c(11) : fatal error C1001: Internal Compiler Error
- (compiler file '@(#)regMD.c:1.110', line 3020)
- Contact Microsoft Product Support Services
-
- The following are valid workarounds for the problem:
-
- 1. Compile without the /Oe or /Og optimizations.
-
- 2. Use the #pragma optimize switch in the code to turn off the
- offending optimizations for the particular function.
-
- 3. Compile under the small or medium memory models.
-
- Sample Code
- -----------
-
- #include<string.h>
-
- void foo (void)
- {
- char *o, *wp, *cp;
- int c,t;
-
- for (;;)
- {
- wp++;
- t = wp - cp;
- if (c) t=0;
- if (t) strncpy (&o[c], cp, t );
- c = t;
- cp = wp;
- }
- }
-
-
- 609. /MT Cannot Be Mixed with /FPa As Shown on Page 370 of APT
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | docerr
- Last Modified: 6-FEB-1991 ArticleIdent: Q67782
-
- Page 370 of the "Advanced Programming Techniques" manual shipped with
- Microsoft C version 6.00 incorrectly gives an example of combining the
- command-line switches /MT and /FPa. This procedure does not work and
- will cause the compiler to generate the following error message:
-
- Command Line Error D2016: '-MT' and '-FPa' are incompatible
-
- To use the alternate math libraries, you must either create a single
- threaded .EXE or a multithreaded DLL. The libraries to create a
- multithreaded .EXE are not available.
-
-
- 610. C1001: Internal Compiler Error: regMD.c, Lines 4634 and 4688
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 6-FEB-1991 ArticleIdent: Q67783
-
- When compiled with /Oe and /MD, the sample code generates an internal
- compiler error for Microsoft C Compiler versions 6.00 and C 6.00a. The
- errors are different for each version.
-
- Under C 6.00
- ------------
-
- fatal error c1001: Internal Compiler Error
- (compiler file '@(#)regMD.c:1.110',line 4634)
-
- Under C 6.00a
- -------------
-
- fatal error c1001: Internal Compiler Error
- (compiler file '@(#)regMD.c:1.110',line 4688)
-
- Sample Code
- -----------
-
- char wi_lines(char);
-
- int w_hline(char *pnt)
- {
- int x;
- for (x=0;x<=10;x++)
- pnt[x]=wi_lines(pnt[x]);
- }
-
-
- 611. C 6.00/6.00a May Incorrectly Generate C4009 Warning with /Zg
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 6-FEB-1991 ArticleIdent: Q67784
-
- When compiling with the "/Zg" option in C version 6.00 or 6.00a, a
- C4009 (string too big, trailing characters truncated) warning error
- may be incorrectly flagged. In the sample code below, a local array of
- strings of total size greater than 2K will generate the warning. If
- the array is made global or the total size is less than 2K, the
- warning is not generated.
-
- Sample Code
- -----------
-
- void main(void) { }
-
- int test(void) {
-
- char * test_array[3][35] = {
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
- };
-
- }
-
- Microsoft has confirmed this to be a problem in C versions 6.00 and
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
-
- 612. Bit Operations on Char May Produce Unexpected Results
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00
- Last Modified: 6-FEB-1991 ArticleIdent: Q67785
-
- Bit manipulations on type char may produce different results depending
- on the compiler switches. The /J and /qc switches have different
- effects on the code below when using the Microsoft C versions 6.00 and
- 6.00a compiler.
-
- Sample Code
- -----------
-
- #include <stdio.h>
-
- char unsigned ary[4] = {0xF6, 0xF7, 0xF8, 0xF9};
-
- void main(void)
- {
- unsigned long result1, result2;
- char *p;
- p = ary;
- result1 = *p | ( *(p+2) << 8);
- result1 += ( *(p+1) | ( *(p+3) << 8)) * 0x10000;
- result2 = (unsigned long)(( *(p+2) << 8) | *p) |
- (unsigned long)(( *(p+3) << 8) | *(p+1)) << 16;
- printf("result1 = %lX\n", result1);
- printf("result2 = %lX\n", result2);
- }
-
- When compiled with
-
- cl /qc /J foo.c
-
- the results are:
-
- result1 = F9F7F8F6
- result2 = F9F7F8F6
-
- When compiled with
-
- cl /J foo.c
-
- the results are:
-
- result1 = F9F6F8F6
- result2 = FFFFF8F6
-
- When compiled with
-
- cl /qc foo.c
- or
- cl foo.c
-
- the results are:
-
- result1 = FFF6FFF6
- result2 = FFFFFFF6
-
- The differences occur because of a problem in the Quick Compiler. When
- an integral promotion is required, the Quick Compiler incorrectly
- converts an unsigned char to an unsigned int. According to ANSI, if
- all the values of a char can be represented in an int, it is converted
- to an int; otherwise, it is converted to an unsigned int (see section
- 3.2.1.1). This is also documented in the "Advanced Programming
- Techniques" manual on page 422.
-
- There are a number of ways to work around this problem depending on
- the desired results. If the intent was to generate results equal to
- F9F7F8F6 (as the Quick Compiler with /J did), declare "p" as a pointer
- to an unsigned char and modify the equations for "result1" and
- "result2" to use unsigned int casts where appropriate. For example:
-
- result1 = *p | ((unsigned int)*(p+2) << 8);
- result1 += ( *(p+1) | ( *(p+3) << 8)) * 0x10000;
-
- -or-
-
- result2 = ((unsigned long)(((unsigned int)*(p+2) << 8) | *p)|
- (unsigned long)(( *(p+3) << 8) | *(p+1)) << 16;
-
- If the results from the full optimizing compiler with /J are desired,
- again declare "p" as a pointer to unsigned char and replace the above
- mentioned casts with signed int. Finally, if the results without /J
- are desired, declare "p" as a pointer to a signed char.
-
- Microsoft has confirmed this to be a problem in the Microsoft C
- Compiler versions 6.00 and 6.00a. We are researching this problem and
- will post new information here as it becomes available.
-
-
- 613. Code Generation Error with C 6.00 and Global Variables
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00 buglist6.00a
- Last Modified: 6-FEB-1991 ArticleIdent: Q67786
-
- The sample program below does not compile properly when using any
- optimizations other than /Od under C versions 6.00 and 6.00a. The code
- generated by the compiler incorrectly assumes that foo and bar are
- equal after the call to the function inc_foo. The compiler then
- accesses bar[1] by using the value of foo rather than the value of
- bar. This generates the wrong effect on the array being modified.
-
- There are several workarounds:
-
- 1. Use the /Od option or the /qc option.
-
- 2. Declare foo as a volatile pointer to a char.
-
- 3. Change the code to assign buf to bar first.
-
- Microsoft has confirmed this to be a problem in C versions 6.00 and
- 6.00a. We are researching this problem and will post new information
- here as it becomes available.
-
- Sample Code
- -----------
-
- #include <stdio.h>
- char inc_foo (void);
-
- char * foo;
- char * bar;
- char * buf = "....................";
-
- main ()
- {
- foo= buf;
- bar= buf;
- bar[1]= inc_foo ();
- printf ("buf = %s\n", buf);
- printf ("foo = %d\nbar = %d\n", foo, bar);
- }
-
- char inc_foo ()
- {
- foo += 10;
- return (char) '[';
- }
-
- The correct output is:
-
- buf = .[..................
- foo = 76
- bar = 66
-
- The output generated is:
-
- buf = ...........[........
- foo = 76
- bar = 66
-
-
- 614. %n Format Specifier May Be Ignored in C 6.00 sscanf()
-
- Product Version(s): 6.00 6.00a | 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 6-FEB-1991 ArticleIdent: Q67790
-
- If the "%n" format specifier is used within a sscanf() function and
- the format specifier before it causes the last character to be read
- from the string of data, the %n will be ignored and the sscanf()
- function will return without making the %n assignment. This is correct
- per ANSI specifications, since an input failure before the %n
- parameter is evaluated.
-
- The code below demonstrates the problem. Notice that the last
- parameter passed (d) does not get changed. The sscanf() statement
- finishes making assignments as soon as it reaches the end of the
- string.
-
- Sample Code
- -----------
-
- #include <stdio.h>
-
- void main(void)
- {
- int a,b,c,d;
- char buffer[50];
- a=b=c=d=0;
-
- sscanf("100Dummy2","%n%d%n%s%n",&a,&b,&c,buffer,&d);
-
- printf("%d %d %d\n",a,c,d);
- }
-
- Output
- ------
-
- 0 3 0
-
-
- 615. C and QuickC Compiler Options Should Be Placed Before .C File
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 4-DEC-1990 ArticleIdent: Q23739
-
- The C and QuickC compiler switches must be specified on the command-
- line, before any source files that the option is intended to apply to.
- In most cases, specifying options at the end of the command-line after
- a filename will NOT generate any warnings or errors -- the compiler
- will ignore the options because there are no following source files
- that the options apply to.
-
- In a few cases, a trailing option at the end of the command-line will
- generate an error if the option conflicts with a previously specified
- option.
-
-
- 616. Effects of Min and Max Memory Allocation During C Program Load
-
- Product Version(s): 4.00 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_link s_exemod s_exehdr
- Last Modified: 6-FEB-1991 ArticleIdent: Q24935
-
- Changing the minimum and maximum allocation values in an .EXE file
- will affect the way in which memory is allocated for a program.
-
- Memory is dynamically allocated for a program when it is loaded. DOS
- initially attempts to allocate FFFFH paragraphs memory. This will
- always fail, returning the size of the largest free block. If this
- block is smaller than the minimum allocation and the load size, a
- no-memory error will occur. If this block is larger than the sum of
- the maximum allocation and the load size, DOS will allocate the amount
- specified by the load size and the maximum allocation. Otherwise, the
- largest block of memory available is allocated.
-
- An example of when the maximum allocation should be changed would be a
- program, such as a menu driver, that spawns other programs. Since this
- program would stay resident in memory, the maximum allocation should
- be set to the minimum allocation to keep as much memory available as
- possible for the spawned programs.
-
- In small memory model, the C start-up code will return all memory
- allocated to it back to DOS, except for a 64K block reserved for the
- default data group. If only 4K of this 64K will be used by the menu
- program, the entire 64K should not be kept. There are several ways of
- changing the maximum allocation to 4K -- you can link with the /CP:1
- option or you can modify an existing .EXE file with the EXEHDR or
- EXEMOD utilities.
-
-
- 617. fseek() Function Requires a long for the Offset into a File
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER |
- Last Modified: 6-FEB-1991 ArticleIdent: Q23753
-
- Question:
-
- I am using fseek() to seek in a file, but it fails when I try to seek
- beyond 32K. Is this a limit of fseek()?
-
- Response:
-
- The offset parameter to fseek() takes a value of type long, so this
- problem is not likely to be the result of fseek() limits. On the other
- hand, this situation does occur if you are using variables of type int
- to calculate the offset. Because an int is limited to a maximum value
- of 32,767 (32K), values assigned to ints between 32K and 64K are
- treated as negative.
-
- An int will be automatically typecast to a long when passed to fseek()
- but when this occurs, it is sign-extended. Thus, an int value above
- 32K that is represented as negative will be sign-extended to a
- negative long. This, in turn, specifies a negative offset into the
- file, which fails to produce the expected results.
-
- When using the fseek() routine, just be sure to use a long for
- specifying the offset into the file.
-
-
- 618. Difference Between Minimum Load Size and Minimum Allocation
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc s_link s_exehdr s_exemod
- Last Modified: 6-FEB-1991 ArticleIdent: Q25024
-
- The following is a summation of the differences between the minimum
- load size and the minimum allocation size in a DOS executable (.EXE)
- file header:
-
- The minimum load size is the amount of memory needed for the load
- module, plus the minimum allocation value. This reflects the amount of
- memory necessary to load and run the program, assuming no dynamic
- allocation is necessary.
-
- The minimum allocation is the amount of memory needed above the actual
- load module. These values determine the highest memory location into
- which the program can be loaded. For example, if the minimum load size
- is 0, the program will be loaded at the highest possible location in
- memory.
-
-
- 619. Sending 1Ah to a Printer Requires Setting "Raw" Mode
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER |
- Last Modified: 4-FEB-1991 ArticleIdent: Q23867
-
- Problem:
-
- I am trying to output a graphics file to a printer. I have opened the
- printer as a binary file, but the output stops every time I try to
- output hexadecimal character 1A. I assumed that anything could be
- output to a binary file.
-
- Response:
-
- If you open a device, such as PRN, as a binary file using fopen() or
- open(), the device will not translate carriage return/line feed
- combinations. However, DOS will continue to interpret CTRL+Z (1Ah) as
- an end-of-file character.
-
- You must use interrupt 21h function 44h to set the raw-mode bit for
- the device to disable checking for CTRL+Z characters. This way, all
- characters will be allowed to pass.
-
- The following example was taken from page 351 of "Advanced MS-DOS
- Programming," which gives an assembly language program example for
- setting raw mode.
-
- Sample Code
- -----------
-
- void setrawmode(void)
- {
- union REGS inregs, outregs;
-
- inregs.x.ax = 0x4400;
- inregs.x.bx = 0x04; /* specify the printer */
- int86(0x21, &inregs, &outregs);
-
- outregs.h.dh = 0x00;
- outregs.h.dl = 0x20; /* set raw mode bit */
- outregs.x.ax = 0x4401;
- int86(0x21, &outregs, &inregs);
- }
-
-
- 620. How to Do "Peeks" and "Pokes" in a C Program
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 6-FEB-1991 ArticleIdent: Q23868
-
- The sample code below contains two functions that simulate what are
- commonly known as "peek" and "poke" functions. The peek() function
- allows you to look at the contents of any memory location while the
- poke() function allows you to place a value into any memory location.
-
- Sample Code
- -----------
-
- /* The following function will stuff a value into any location in
- addressable memory. seg:ofs = val.
- */
-
- void poke(unsigned int seg, unsigned int ofs, char val)
- {
- unsigned char far *ptr;
-
- ptr = (unsigned char far *) (((long)seg<<16)|(long)ofs);
- *ptr = val;
- }
-
- /* The following function will return the contents of any location in
- addressable memory. return(seg:ofs).
- */
-
- unsigned char peek(unsigned int seg, unsigned int ofs)
- {
- unsigned char far *ptr;
-
- ptr = (unsigned char far *) (((long)seg<<16)|(long)ofs);
- return(*ptr);
- }
-
-
- 621. malloc() and free() Do Not Return Memory to DOS
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
- Operating System: MS-DOS
- Flags: ENDUSER | s_quickc
- Last Modified: 15-JAN-1991 ArticleIdent: Q23869
-
- Problem:
-
- My large model program calls system() to do a directory, and then I
- malloc() a large amount of space. I can free() it all but I get a "Not
- enough memory" error when I try to call system() again. Apparently
- free() is not returning the memory to DOS.
-
- Response:
-
- When you malloc() a large amount of space (more than is available
- within the current heap), the malloc() function will execute a DOS
- call to get more memory in an attempt to expand the heap. If this is
- successful, DOS will allocate the desired memory to your program and
- malloc() will return successful. If you then free() this memory, it
- will be marked as free within your program's heap and will be
- available for use again by your program.
-
- However, DOS still sees this memory as being used by the program
- because it now resides within the program's heap. If you attempt a
- subsequent system() call, DOS may find it does not have enough free
- memory to load the code required to perform the system() function.
-
- An alternative is to use halloc() and hfree(), which will return the
- memory to DOS, rather than retaining it for use by the currently
- executing program.
-
-
- 622. C 6.00a CD-ROM Setup Does Not Install RAMDRIVE or SMARTDRV
-
- Product Version(s): 6.00a | 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | buglist6.00a
- Last Modified: 31-JAN-1991 ArticleIdent: Q67847
-
- When Setup is run from the CD-ROM version of Microsoft C version
- 6.00a, the following two files are not found along the specified path:
-
- \HD525\DISK7\RAMDRIVE.SYS
- \HD525\DISK7\SMARTDRV.SYS
-
- The two files are included in this path:
-
- \HD525\DISK6\RAMDRIVE.SYS
- \HD525\DISK6\SMARTDRV.SYS
-
- Since the files are not compressed, they can be copied to your hard
- drive.
-
- Microsoft has confirmed this to be a problem in the C version 6.00a
- CD-ROM Setup program. We are researching this problem and will post
- new information here as it becomes available.
-
-
- 623. .EXE Header Must Be Marked for OS/2 Long Filename Support
-
- Product Version(s): 6.00 6.00a
- Operating System: OS/2
- Flags: ENDUSER | s_exehdr
- Last Modified: 1-FEB-1991 ArticleIdent: Q67878
-
- Applications using long filenames and extended file attributes are
- supported under OS/2 versions 1.20 and later running the high
- performance file system (HPFS); however, a bit in the executable file
- must be set to tell OS/2 that the executable file supports long
- filenames.
-
- The following lists two possible methods to specify that the
- application supports long filenames:
-
- 1. Modify the executable file using the EXEHDR utility:
-
- EXEHDR /NEWFILES test.exe
-
- 2. Link with a module definition file containing the following line
- specifying the optional attribute <NEWFILES>:
-
- NAME [appname] [apptype] NEWFILES
-
-
- 624. R6002 "Floating Point Not Loaded" May Result from printf() Use
-
- Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
- Operating System: MS-DOS | OS/2
- Flags: ENDUSER | s_quickc
- Last Modified: 4-DEC-1990 ArticleIdent: Q23873
-
- Question:
-
- I have a simple program that prints out some numbers. Every time I try
- to run the program, I get the error message "R6002: Floating point
- support not loaded." Why do I get this error when I don't have any
- floats in my program?
-
- Response:
-
- You most likely have a printf() statement in your program that
- contains a floating point format specifier, such as %f in the format
- string. At link time, the floating-point library modules will not be
- loaded unless floats are declared.