|< C Storage Class & Memory Functions | Main | C Run-Time 2 >| Site Index | Download |
MODULE A
IMPLEMENTATION SPECIFIC
MICROSOFT C Run-Time 1
My Training Period: hours
Note:
Program examples compiled using Visual C++ .Net (Visual studio .Net 2003). It is low-level programming and the .Net used is Unmanaged (/clr is not set: Project menu → your_project_name Properties… sub menu → Configuration Properties folder → General subfolder → Used Managed Extension setting set to No). All programs are in debug mode, run on Windows 2000 and Xp Pro.
|
|
Abilities
▪ Able to recognize the standard and implementation specific C. ▪ Able to grasp the fundamental of the Windows file system, file and directory. ▪ Able to find and collect the needed information in order to use functions to accomplish your tasks. ▪ Able to understand and use functions that available in the libraries in your own programs.
- In this Module you will be introduced to the absolute implementation specific of the C/C++, the Microsoft C/C++. However it is still non-GUI type of programs :o). - This brings you to the specific use of the compilers that compile the Windows applications and the programs developed are specific to be run on the Windows platform although in the discussion and program examples of this Module and later on, the standard and non standard (Microsoft extension) libraries will be used together. - Make sure you have already fluent in functions because we will learn how to use them. Remember all the thing about a function such as parameters, return values etc. The final purpose of this Module and that follows actually to show you how to find and collect all the required information from tons of the documentations to suit your needs in developing programs. - Keep in mind that, normally, in libraries we have the following things which defined in and accessed through the header files:
▪ Macro definitions. ▪ Function prototypes. ▪ Structure definitions (struct). ▪ Enumeration definitions (enum). ▪ Data type definitions. ▪ The typedef usage.
- For the data type and structure definitions, you will find that use of struct, typedef and enum is normal here and also for Win32 programming (will be discussed in another Module). - To better understand you must be fluent on those things. If you encounter any problem, you might have to go back to basic :o) by referring to Tutorial #1 tenouk.com. - Other pre requirement topics include array and pointer.
The Background Story: The Microsoft C Run-time Libraries
- The following table lists a various .lib files that comprise the C run-time (CRT) libraries as well as their associated compiler options and preprocessor directives. The libraries contain the C run-time library functions. - For these libraries, the header files used in the programs must have the .h extension. |
|
Pure C run-time library |
Characteristics |
Compiler Option |
Preprocessor directives |
|
LIBC.LIB |
Single-threaded, static link. |
/ML |
|
|
LIBCMT.LIB |
Multithreaded, static link. |
/MT |
_MT |
|
MSVCRT.LIB |
Multithreaded, dynamic link (import library for MSVCR70.DLL). Be aware that if you use the Standard C++ Library, your program will need MSVCP70.DLL to run. |
/MD |
_MT, _DLL |
|
LIBCD.LIB |
Single-threaded, static link (debug). |
/MLd |
_DEBUG |
|
LIBCMTD.LIB |
Multithreaded, static link (debug). |
/MTd |
_DEBUG, _MT |
|
MSVCRTD.LIB |
Multithreaded, dynamic link (import library for MSVCR70D.DLL) (debug) |
/MDd |
_DEBUG, _MT, _DLL |
|
Table 1: C run-time libraries |
|||
- The Compiler Options, Preprocessor Directives and other configuration settings can be accessed from Project menu → your_project_name Properties... sub menu.
- It also can be accessed by selecting your project directory (in the Solution Explorer pane) → Right click → Select the Properties menu as shown below.

Figure 1
- The following Figure is a project Property pages.

Figure 2.
- If you link your program from the command line without a compiler option that specifies a C run-time library, the linker will use LIBC.LIB by default.
- To build a debug version of your application, the _DEBUG flag must be defined and the application must be linked with a debug version of one of these libraries.
- However in this Module and that follows we will compile and link by using the Visual C++ .Net IDEs’ menus instead of command line :o).
- The run-time libraries also include .lib files that contain the iostream library and the Standard C++ Library. You should never have to explicitly link to one of these .lib files; the header files in each library link in the correct .lib file.
- The programs that use this old iostream library will need the .h extension for the header files.
- Before Visual C++ 4.2, the C run-time libraries contained the iostream library functions. In Visual C++ 4.2 and later, the old iostream library functions have been removed from LIBC.LIB, LIBCD.LIB, LIBCMT.LIB, LIBCMTD.LIB, MSVCRT.LIB, and MSVCRTD.LIB.
- This change was made because the Standard C++ Library has been added to Visual C++, and it contains a new set of iostream libraries.
- Thus, two sets of iostream functions are now included in Visual C++. The old iostream functions now exist in their own libraries as shown in the following Table.
|
Old iostream library |
Characteristics |
Compiler Option |
Preprocessor directives |
|
LIBCI.LIB |
Single-threaded, static link. |
/ML |
|
|
LIBCIMT.LIB |
Multithreaded, static link. |
/MT |
_MT |
|
MSVCIRT.LIB |
Multithreaded, dynamic link (import library for MSVCI70.DLL). |
/MD |
_MT, _DLL |
|
LIBCID.LIB |
Single threaded, static link. |
/MLd |
_DEBUG |
|
LIBCIMTD.LIB |
Multithreaded, static link. |
/MTd |
_DEBUG, _MT |
|
MSVCIRTD.LIB |
Multithreaded, dynamic link (import library for MSVCI70D.DLL). |
/MDd |
_DEBUG, _MT, _DLL |
|
Table 2: Old iostream libraries |
|||
- The new iostream functions, as well as many other new functions, that exist in the Standard C++ Library are shown in the following Table.
- The programs that use this new iostream library will need the header files without the .h extension such as <string>.
|
Standard C++ Library |
Characteristics |
Compiler Option |
Preprocessor directives |
|
LIBCP.LIB |
Single-threaded, static link |
/ML |
|
|
LIBCPMT.LIB |
Multithreaded, static link |
/MT |
_MT |
|
MSVCPRT.LIB |
Multithreaded, dynamic link (import library for MSVCP70.dll) |
/MD |
_MT, _DLL |
|
LIBCPD.LIB |
Single-threaded, static link |
/MLd |
_DEBUG |
|
LIBCPMTD.LIB |
Multithreaded, static link |
/MTd |
_DEBUG, _MT |
|
MSVCPRTD.LIB |
Multithreaded, dynamic link (import library for MSVCP70.DLL) |
/MDd |
_DEBUG, _MT, _DLL |
|
Table 3: Standard C++ libraries |
|||
- The Standard C++ Library and the old iostream library are incompatible, that is they cannot be mixed and only one of them can be linked with your project.
- The old iostream library created when the standard is not matured yet.
- When you build a release version of your project, one of the basic C run-time libraries (LIBC.LIB, LIBCMT.LIB, and MSVCRT.LIB) is linked by default, depending on the compiler option you choose (single-threaded, multithreaded, or DLL).
- Depending on the headers you use in your code, a library from the Standard C++ libraries or one from the old iostream libraries may also be linked, for example:
▪ If you include a Standard C++ Library header in your code, a Standard C++ Library will be linked in automatically by Visual C++ at compile time. For example:
#include <ios>
▪ If you include an old iostream library header, an old iostream library will be linked in automatically by Visual C++ at compile time. For example:
#include <ios.h>
- Headers determine whether a Standard C++ library, an old iostream library, or neither will be linked. Compiler options determine which of the libraries to be linked is the default (single-threaded, multithreaded, or DLL).
- When a specific library compiler option is defined, that library is considered to be the default and its preprocessor directives are automatically defined. Also read Module 23 for the big picture.
- As a conclusion, for typical C and C++ programs, by providing the proper header files just let the compiler determine for you which libraries are appropriate to be linked in.
- The following sections will dive more detail some of the functions available in the C run-time library.
- These functions used to create routines that can be used to automate many tasks in Windows that not available in the standard C/C++.
- We will start with category, then the functions available in that category and finally followed by program examples that use some of the functions.
- The functions discussed here mostly deal with directories and files.
- For complete information please refer to Microsoft Visual C++ documentation (online MSDN: Microsoft Visual C++). As a remainder, the following are the things that must be fully understood when you want to use a function, and here, _chsize() is used as an example.
1. What is the use of the function? This will match with "what are you going to do or create?" Keep in mind that to accomplish some of the tasks you might need more (several) than one function. For example:
_chsize() used to change the file size.
2. What is the function prototype, so we know how to write (call) a proper syntax of the function. For example:
int _chsize(int handle, long size);
3. From the function prototype, how many parameters, the order and what are their types, so we can create the needed variables. For example:
|
handle |
Handle referring to open file. |
|
size |
New length of file in bytes. |
4. What header files need to be included? For example the _chsize needs:
<io.h>
5. What is the return type and value? For example:
_chsize returns 0 if the file size is successfully changed. A return value of –1 indicates an error: errno is set to EACCES if the specified file is locked against access, to EBADF if the specified file is read-only or the handle is invalid, or to ENOSPC if no space is left on the device.
- Hence, you are ready to use the function in any of your programs. If you still blur about functions, please read C & C++ Functions tutorial. Not all the needed information is provided here and for complete one, please refers to the Microsoft Visual C++/MSDN/SDK Platform documentations or HERE.
- For C++, together with the classes, it is used when you develop programs using Microsoft Foundation Class (MFC) and Automatic Template Library (ATL).
- The notation convention used for identifiers in MSDN documentation is Hungarian Notation and is discussed C/C++ Notations.
--------------------The Story and Program Examples---------------------
- Functions available in this category used to access, modify, and obtain information about the directory structure and are listed in the following Table.
- Notice that most of the function names are similar to the standard C wherever available, except prefixed with underscore ( _ ) :o). The functions available in this category are listed in the following Table.
Directory Management Functions
- The following Table lists functions used for directory control and management.
|
Function |
Use |
|
_chdir(), _wchdir() |
Change current working directory. |
|
_chdrive() |
Change current drive. |
|
_getcwd(), _wgetcwd() |
Get current working directory for default drive. |
|
_getdcwd(), _wgetdcwd() |
Get current working directory for specified drive. |
|
_getdiskfree() |
Populates a _diskfree_t structure with information about a disk drive. |
|
_getdrive() |
Get current (default) drive. |
|
_getdrives() |
Returns a bitmask representing the currently available disk drives. |
|
_mkdir(), _wmkdir() |
Make new directory. |
|
_rmdir(), _wrmdir() |
Remove directory. |
|
_searchenv(), _wsearchenv() |
Search for given file on specified paths. |
|
Table 4: Directory control functions |
|
- The following is an example of the needed information in order to use the _getdrives() function.
|
Information |
Description |
|
The function |
_getdrives(). |
|
The use |
Returns a bitmask representing the currently available disk drives. |
|
The prototype |
int _getdrives(void); |
|
Example |
ULONG DriveMask = _getdrives();
while (DriveMask) { //List all the drives... if(DriveMask & 1) printf(mydrives); ++mydrives[1]; //Shift the bit masks binary //to the right and repeat DriveMask >>= 1; } |
|
The parameters |
void |
|
The return value |
If the function succeeds, the return value is a bitmask representing the currently available disk drives. Bit position 0 (the least-significant bit) is drive A, bit position 1 is drive B, bit position 2 is drive C, and so on. If the function fails, the return value is zero. To get extended error information, call GetLastError(). |
|
The header file |
<direct.h> |
|
Table 5: _getdrives() information |
|
- The following program example uses the _getdrives() function to list the available logical drives in the current machine.
#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>
//Buffer, be careful with terminated NULL
//Must match with ++mydrives[1]...that is one space
//Example if no one space: "A:"--> ++mydrives[0];
TCHAR mydrives[] = " A: ";
//Or char mydrives[] = {" A: "};
//Or char mydrives[] = " A: ";
int main()
{
//Get the drives bit masks...1 is available, 0 is not available
//A = least significant bit...
ULONG DriveMask = _getdrives();
//If something wrong
if(DriveMask == 0)
printf("_getdrives() failed with failure code: %d\n", GetLastError());
else
{
printf("This machine has the following logical drives:\n");
while (DriveMask)
{ //List all the drives...
if(DriveMask & 1)
printf(mydrives);
//Go to the next drive strings with one space
++mydrives[1];
//Shift the bit masks binary
//to the right and repeat
DriveMask >>= 1;
}
printf("\n");
}
return 0;
}
The output:
This machine has the following logical drives:
A: C: D: E: F: G: H: I: J: K: L:
Press any key to continue
- The following is an example of the needed information in order to use the _getdiskfree() function.
|
Information |
Description |
|
The function |
_getdiskfree(). |
|
The use |
Populates a _diskfree_t structure with information about a disk drive. |
|
The prototype |
unsigned _getdiskfree(
unsigned drive, struct _diskfree_t * driveinfo); |
|
Example |
struct _diskfree_t df = {0}; unsigned uDrive; _getdiskfree(uDrive, &df); |
|
The parameters |
drive - The disk drive for which you want information. driveinfo - A _diskfree_t structure that will be populated with information about the drive. _diskfree_t is defined in direct.h. |
|
The return value |
If the function succeeds, the return value is zero. If the function fails, the return value is the error code. To get extended error information, call GetLastError(). |
|
The header file |
<direct.h> |
|
Table 6: _getdiskfree() information |
|
- The following program example uses the _getdiskfree() function to list logical drives information in the current machine.
#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>
TCHAR g_szText[] = _T("Drive Total_clus Available_clus Sec/Cluster Bytes/Sec\n");
TCHAR g_szText1[] = _T("----- ---------- -------------- ----------- ---------\n");
TCHAR g_szInfo[] = _T("-> \n");
//For data display format...
//Right justified, thousand comma separated and other format
//for displayed data
void utoiRightJustified(TCHAR* szLeft, TCHAR* szRight, unsigned uValue)
{
TCHAR* szCur = szRight;
int nComma = 0;
if(uValue)
{
while(uValue && (szCur >= szLeft))
{
if(nComma == 3)
{
*szCur = ',';
nComma = 0;
}
else
{
*szCur = (uValue % 10) | 0x30;
uValue /= 10;
++nComma;
}
--szCur;
}
}
else
{
*szCur = '0';
--szCur;
}
if(uValue)
{
szCur = szLeft;
while(szCur <= szRight)
{//If not enough field to display the data...
*szCur = '*';
++szCur;
}
}
}
int main()
{
TCHAR szMsg[4200];
struct _diskfree_t df = {0};
//Search drives and assigns the bit masks to
//uDriveMask variable...
ULONG uDriveMask = _getdrives();
unsigned uErr, uLen, uDrive;
printf("clus - cluster, sec - sector\n");
printf(g_szText);
printf(g_szText1);
for(uDrive = 1; uDrive <= 26; ++uDrive)
{
//If the drive is available...
if(uDriveMask & 1)
{ //Call _getdiskfree()...
uErr = _getdiskfree(uDrive, &df);
//Provide some storage
memcpy(szMsg, g_szInfo, sizeof(g_szInfo));
szMsg[3] = uDrive + 'A' - 1;
//If _getdiskfree() is no error, display the data
if(uErr == 0)
{
utoiRightJustified(szMsg+4, szMsg+15, df.total_clusters);
utoiRightJustified(szMsg+18, szMsg+29, df.avail_clusters);
utoiRightJustified(szMsg+27, szMsg+37, df.sectors_per_cluster);
utoiRightJustified(szMsg+40, szMsg+50, df.bytes_per_sector);
}
else
{//Print system message and left other fields empty
uLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, uErr, 0, szMsg+8, 4100, NULL);
szMsg[uLen+6] = ' ';
szMsg[uLen+7] = ' ';
szMsg[uLen+8] = ' ';
}
printf(szMsg);
}
//shift right the found drive bit masks and
//repeat the process
uDriveMask >>= 1;
}
return 0;
}
The output:
clus - cluster, sec - sector
Drive Total_clus Available_clus Sec/Cluster Bytes/Sec
----- ---------- -------------- ----------- ---------
-> A 2,847 834 1 512
-> C 2,560,351 62,315 8 512
-> D 2,560,351 1,615,299 8 512
-> E 2,560,351 2,310,975 8 512
-> F 2,560,351 2,054,239 8 512
-> G 2,353,514 2,039,396 8 512
-> H 2,560,351 2,394,177 8 512
-> I 2,381,628 1,618,063 8 512
-> J 321,935 0 1 2,048
-> L 63,419 20,706 16 512
Press any key to continue
- Note that J: is CD-RW, L: is thumb drive and A: is a floppy. For floppy and CD-ROM, you have to insert the media.
- The following is an example of the needed information in order to use the _getdrive() function.
|
Information |
Description |
|
The function |
_getdrive(). |
|
The use |
Gets the current disk drive. |
|
The prototype |
int _getdrive(void); |
|
Example |
int curdrive; curdrive = _getdrive(); |
|
The parameters |
void |
|
The return value |
Returns the current (default) drive (1=A, 2=B, and so on). There is no error return. |
|
The header file |
<direct.h> |
|
Table 7: _getdrive() information |
|
- The following Table lists the needed information in order to use the _chdir(), _wchdir() functions.
|
Information |
Description |
|
The function |
_chdir(), _wchdir(). |
|
The use |
Change the current working directory. |
|
The prototype |
int _chdir(const char *dirname); /*For wide character*/ int _wchdir(const wchar_t *dirname); |
|
Example |
char path1[50] = "C:\\WINNT\\System32\\config"; _chdir(path1); |
|
The parameters |
dirname - Path of new working directory. |
|
The return value |
These functions return a value of 0 if successful. A return value of –1 indicates that the specified path could not be found, in which case errno is set to ENOENT. |
|
The header file |
<direct.h> or <wchar.h> for _wchdir(). |
|
Table 8: _chdir(), _wchdir() functions information |
|
- The _chdir() function changes the current working directory to the directory specified by dirname. The dirname parameter must refer to an existing directory.
- This function can change the current working directory on any drive. If a new drive letter is specified in dirname, the default drive letter will be changed as well.
- For example, if A is the default drive letter and \BIN is the current working directory, the following call changes the current working directory for drive C and establishes C as the new default drive:
_chdir("c:\\te