Home > Articles

A Word on C

Built-In Functions

You will not have to author all the functions that your application employs because the C programming language provides many functions for you. When you become aware of functions inherent to a language, you increase your proficiency in it.

The availability of functions provided by an environment such as X Window or a third-party package adds to this challenge.

Third-party packages are ones that you add to your system and are generally not part of the standard installation process. These packages are usually purchased separately and selected for the functionality they add to your development or runtime environment. The OSF/Motif Widget Set is an example of this; it compliments the X Window System because it provides elegant three-dimensional features to X Window-based application development.

Focusing on some of the functions provided by the C programming language, look again at the code sample from the Hello World example that started the chapter:

3:    printf("Hello World");

The printf Command

The printf command is a function the C language provides for printing formatted output to the terminal. The use of printf is extremely flexible because it supports every data type recognized by the C language.

EXCURSION

Terminals Aren't Just Where Planes Depart

A terminal may be your screen or a terminal emulator (window) such as the xterm depending on whether your system is running in graphics or text mode.

Generally, printf places its output on the command line following where the program was executed. This destination is known as standard out and represented in C as stdout. In addition to standard out, the C language also provides the destination standard error (stderr) for output.

Standard out and standard error start as the same destination; however, they can be altered through the use of redirection as discussed in the section "grep, Pipes, Redirection, and more" in Chapter 1, page 44.

Chapter 4 covers windowing concepts and terminal emulators in detail.

As with the function add2Nums defined earlier, there must be a forward declaration (prototype) for the function printf. Because the C language provides the function, it also provides the prototype.

The printf function's declaration (and many other functions performing input and output) is found in the file stdio.h, which is part of the standard C header files.

EXCURSION

Another Look at the Use of Header Files

Header files, as discussed in the Note found in the section "Definition" in Chapter 2, page 68, are source files often containing prototypes and other declarations shared by multiple files within a project.

You include a header file by using the include compiler directive. As the name implies, a compiler directive directs the compiler to perform a task or make a decision.

In C, all compiler directives are prefaced with the pound sign (#).

#include <stdio.h>
Used in the same manner as the include statement from Makefile syntax as discussed in Chapter 1, section "Include" on page 37, the compiler directive to include a header file performs the inclusion at the point of the directive. The effect is that the compiler sees the contents of the file as if replicated by the directive.

The syntax when employing the include compiler directive offers a hint to where the file can reside. Specifically, when the header is part of the standard C library the < and > are used to enclose the filename. However, when the header file is part of a third-party package or one that you have authored as part of the project, the filename is enclosed by double quotes.

#include "gxgraphics.h".
The C compiler first looks in a standard directory such as /usr/include for files enclosed with the < > symbols and then it considers the paths specified by the -I flag passed when the compiler was invoked.

To review the gcc command and use of the -I flag, refer to Chapter 1, section "gcc -I", page 28.

To properly declare the printf function prior to its invocation, add the following line to the "Hello World" code sample:

0a: #include <stdio.h>

The syntax of the printf function follows the form

printf( "format string" [, arg][, arg][, ...] );

To accomplish the formatting recognized by the printf function, the format string ranges from a constant such as "Hello World" to accepting a variety of formatting tokens.

Note

Notice in the syntax of the printf that the args are enclosed in square braces ([]), indicating that they are optional. An argument (arg) is only required if a format token is nested in the format string.

Table 3.1 shows some common formatting tokens recognized by printf that can be embedded in the format string.

Table 3.1 Printf Formatting Tokens

Token

Type

Sample

Output

%s

char *

printf("String: %s", "Hello" );

String: Hello

%c

char, char

printf( "Character: %c", 'A' );

Character: A

%d

int, long, short, unsigned int, unsigned long, unsigned short

printf( "Number: %d", 198 );

Number: 198

%f

float, double

printf( "Real Number: %f", 3.14

Real Number: 3.14 );


All formatting tokens are prefaced with the percent sign (%), indicating to printf that what follows is for argument substitution. Further, for each token in the format string there must be a corresponding argument to satisfy the substitution.

Multiple arguments are comma separated and substituted in the order they are placed.

printf( "String %s and Char: %c", "Hello", 'A' );

Note

As demonstrated in the previous example, C uses double quotes ("") to reresent multiple characters (strings) and single quotes to represent a single character ('').

Note

printf's capability to perform type checking is limited. A token nested in the format string expects a complimenting argument of a specific type. If an argument of a differing type is placed in the argument list, the results cannot be predicted. The printf statement will attempt to cast the argument, but because this is done at run-time (while the program executes) there is no recovery if the types are not compatible.

EXCURSION

Promoting Variable Data Types to Satisfy Type Checking

Casting from one data type to another is a way to promote variables to satisfy type requirements and avoid compiler warnings. For instance, a character (char) is easily promoted to an integer (int), which has a larger storage capacity.

The code fragment

char chr = 'A';
int num = (int)chr;

assigns the letter A to the variable chr. Because the letter A has a decimal equivalence of 65, casting chr to an int would assign the value 65 to the variable num.

Caution must be used when casting from a larger data size to a smaller, however, because data could be lost. Consider the fragment

int bigNum = 999;
char chr = (char)bigNum;

Because the maximum value of a character is 256, the assignment of bigNum to chr, although made legal by the cast, results in the new value of chr being –25. Clearly, this is not the expected result.

See the section "Data Types" in Chapter 2, page 70 for a review of valid value ranges and the implicit size of recognized data types.

Looking again at the format string accepted by the printf function, it should be clear why printf is said to perform formatted output. Additional formatting tokens and token modifiers are available to printf for outputting data types in varying forms as well as controlling field widths, alignment, and more.

Review the printf man page for a full description of its capabilities.

The printf is one of several functions that C provides for performing formatted output. Similar to printf are the functions fprintf and sprintf.

Both fprintf and sprintf enable the output to be directed some place other than standard out. For instance, fprintf may be used to send the formatted output to standard error.

fprintf( stderr, "%s %s", "hello", "world" );

Differing from the syntax of printf, fprintf requires as its first parameter the destination designator for the output. This destination can be one that C provides, such as stderr used in the example, or it can be one created by using the fopen (file open) function.

Before looking at the use of fopen, consider sprintf as it relates to the printf and fprintf functions. Use of sprintf enables a programmer to format output for placement in a buffer.

A buffer is a character array used for intermediate storage during input or output operations. For instance, in

char message[25];

message is declared as an array of 25 characters and could be used to satisfy the first parameter required by sprintf.

sprintf( message, "Error occurred at line %d", lineno );

EXCURSION

Apply Great Caution when Determining the Correct Size of an Array

In the sprintf example, message was declared with a length of 25. Count the characters in the format string passed to the function:

"Error occurred at line %d"

Including spaces, there are 23 characters in the format string, excluding the value of the formatting token %d.

The C function sprintf null terminates the output that it formats: It inserts a null character (\0) at the end of the string. This termination is important for other C functions that can act on the string and it consumes one place in the buffer.

With the 23 characters in the format string and one character for null termination, a total of 24 characters are placed in the buffer message before the argument substitution for the token %d. If the value of lineno substituted in the message is only one digit (0–9), you have exactly filled the 25 character spaces available to message. However, if the value of lineno is greater than 9 (two or more digits), you will exceed the length of message because the null termination will be placed outside the valid memory associated with the buffer.

Figure 3.2 illustrates the effect on memory when the boundary of an array is exceeded, a condition known as a segmentation violation.

The value 69 placed in the buffer exceeds the allowed space for message. The owner of the memory that the \0 (null) overwrites is unknown. The memory can be unused or it can be a critical part of the program. Depending on the importance of the unknown space, the program might crash instantly, or it might only corrupt the value of the neighboring space, leading to a crash much later in program execution.

Note

Improper use of arrays is one of the most common causes of program bugs.

A program bug is anything that causes a program to behave unexpectedly, often resulting in a crash.

Now that we've reviewed the built-in functions of printf, fprintf, and sprintf for formatting and outputting data, we can return to the use of the fopen function for creating destination designators to be passed to fprintf.

The fopen Function

The fopen function opens a file named in the parameter list returning a handle to the file known as a file pointer.

Incorporating everything discussed thus far, consider the following code sample illustrating the use of the fopen function:

1: #include <stdio.h> // for printf and fopen function prototypes
1a:          // and FILE structure definition
2: FILE *openFile( char * filename )
3: {
4:    FILE *fp;
5:
6:    fp = fopen( filename, "w+" );
7:
8:    if( fp == NULL ) {
9:      fprintf( stderr, "Unable to open file %s", filename);
10:
11:   }
12:   return( fp );
13: }

The code sample defines a function named openFile that accepts a single parameter filename and a character pointer, and returns a pointer to FILE.

Figure 3.2 An illustration of the error that results in a segmentation violation.

Note

The FILE data type is a structure that C provides for referencing files opened with the fopen function. The structure is considered opaque, meaning that the fields defined within the structure are not to be accessed. The structure exists only to serve as a handle for manipulating files.

The standard out (stdout) and standard error (stderr) references provided by C are pointers to the FILE structure (FILE *).

In the code sample demonstrating use of the fopen function, notice the test on the value returned by the fopen.

8:   if( fp == NULL ) {

If fopen is unable to open the file specified, it returns NULL.

C provides NULL as a means of representing nothing. Literally defined as 0 (zero) and cast to a void pointer ((void *)0), it is returned in cases of failure to create a valid reference to a return value by functions such as fopen.

The fopen command expects two parameters. The first, evident by the example, is the name of the file to open:

6:   fp = fopen( filename, "w+" );

The second parameter is the mode in which fopen should open the file.

Table 3.2 shows the valid modes that can be passed to the fopen function and describes their effect.

Table 3.2 File Modes Understood by fopen

Mode

Description

r

Open the file for reading

r+

Open the file for reading or writing

w, w+

Truncate to zero length or create; file is opened for writing

a, a+

Append, open, or create file for update, writing at the end of the file


Upon successfully opening a file, fopen returns a file pointer (FILE *) reference which can be passed to functions requiring a destination designator such as fprintf:

fprintf( fp, "Line entered into file referenced by fp" );

Now that you're comfortable with the code sample illustrating the fprintf command, the use of NULL, function bodies, rules of scope, and variable and function declarations, we will consider another family of functions provided by C.

The C String Library

The lexical analysis of strings as discussed in Chapter 2, the section "Types of Conditions," page 52, was said to require a different method from integers and characters for forming test conditions. Because string manipulation is language specific, the C string library satisfies this requirement.

C provides many built-in functions for comparing, copying, and creating strings. The first to consider is the function for comparing two strings called strcmp (string compare). Passing the two strings for comparison satisfies the parameters required by the strcmp function:

1: #include <strings.h>
2: 
3:   char *str1 = "tag",
4:      *str2 = "day";
5:
6:   if( strcmp( str1, str2 ) == 0 ) {
7:     // the strings match
8:   } else if( strcmp( str1, str2 ) < 0 ) {
9:     // str1 appears before str2 in a dictionary
10:   } else if( strcmp( str1, str2 ) > 0 ) {
11:     // str1 comes after str2 in a dictionary
12:   }
13: }

Notice that this code sample uses the include compiler directive to include the file strings.h:

1: #include <strings.h>

This is the header file that C provides to satisfy the built-in string functions' forward declarations.

EXCURSION

Combining Declarations and Assignments Using C Syntax

A variation on variable declaration appears in this code sample as the declaration of str1 and str2 are combined sharing the data type char.

3:    char *str1 = "tag",
4:      *str2 = "day";

Syntactically correct, multiple variables of the same type can be comma separated at their declaration.

Seen previously but not explicitly noted is the combination of a variable's declaration and its initialization as shown in the previous example.

A sound programming habit is to initialize a variable prior to the variable's use. It saves you from having to scour code later looking for the obscure bug that lack of initialization might cause if the variable is employed in an expression before being assigned an initial value.

As implied by using strcmp in the previous code sample, the comparison of the two strings returns 0 if the strings are equal. The strcmp function returns a value greater than (or less than) 0, depending on the lexical analysis of the two strings.

EXCURSION

The Lexical Analysis of Two Strings of Varying Length

If the two strings being compared by strcmp are not the same length, as in

char *s1 = "act", *s2 = "abra";
if( strcmp( s1, s2 ) == 0 ) {
then the function compares the strings up to the point of finding the NULL termination or end-of-string marker. (See the Excursion in the section about sprintf for a description of string termination performed by C).

It is possible to inform C how many characters of the two strings to compare by use of the strncmp function.

The strncmp function accepts one more parameter than its sister function strcmp. Specifically, the third parameter informs strncmp of the number of characters to consider in the comparison.

char *s1 = "act", *s2 = "abra";
if( strncmp( s1, s2, 3 ) == 0 ) {

In this example, you've explicitly said to stop comparing after three characters.

How To Pronounce It

The function strncmp is read like it is written stir-n-compare.

Table 3.3 shows several string functions that C provides; they are common in programs employing the language.

Table 3.3 C String Functions

Function

Example

Description

strcmp, strncmp

if(strcmp(str1, str2) == 0) { or if(strncmp(str1, str2, 4) == 0){

Compare two strings (optionally specifying number of characters to compare)

strcpy, strncpy

char str1[10]; strcpy( str1 "Initialize"); strncpy(str1, "Initialize", 10);

Copy one string into another, (optionally specifying number copy); Caution: the destination string, str1, must have space available for the number of characters being copied to avoid a segmentation violation

strcat, strncat

char str1[10]; strcat( str1, "Warn" ); strcat( str1, "ing " ); strncat( str1, "at line", 2 );

Concatenate two strings; the second string specified is added to the end of str1 (optionally specify number of characters to add to the end of str1); Caution: the destination string, str1, must have space available to hold the contents of the second string or a segmentation violation will occur

strchr

char *token, *buf = token = strchr

Find the first occurrence of a character within a string; function returns either a pointer to the position of the character within the first parameter, or NULL if no match was found

strstr

char *token, *buf = "No error"; token = strstr( buf, "err");

Find the first occurrence of a sub-string within a string; function returns a pointer to the start of the sub-string within the first parameter or NULL if no match was found

strdup

char *newStr = strdup( "error_log");

Duplicate a string, returns a new copy of the string specified to the function

strlen

int len = strlen ( newStr );

Return the length (number of characters) comprising the string


Table 3.3 shows that dangers are associated with string manipulation because the space available when copying strings must be sufficient to hold the new contents. The idea of space in a computer program always translates to memory.

The caution extended in the introduction to pointer manipulation, variables by reference, (see the section "Data Types" in Chapter 2, page 70) must be applied to strings as well. In fact, it is the same warning described in the Excursion in the section "sprintf" earlier in this chapter. The common thread is a necessity for proper memory management.

 

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020