The main purpose of white space characters is to format source files so that they are more readable. The compiler ignores white space characters, except when they are used to separate tokens or when they appear within string literals.
The newline character is not treated as white space in preprocessor directives. A newline character is used to terminate preprocessor directives. See Overview of the Preprocessor for more information.
The line continuation character in C is the backslash (\). Use the continuation
character at the end of the line when splitting a quoted string or preprocessor
directive across one or more lines of source code.
HP C allows comments to appear anywhere in the source file except within identifiers or string literals. The C language does not support nested comments.
In the following example, a comment follows an assignment statement:
average = total / number_of_components; /* Find mean value. */Comments may also span multiple lines, as in:
/* This is a multi-line comment. */
| NOTE | HP C allows the dollar sign ($) in identifiers, including using the $ in the first character, as an extension to the language. |
Identifiers cannot conflict with reserved Keywords
.
The ANSI/ISO standard requires compilers to support names of up to 32 characters for local variables and 6 characters for global variables.
To improve portability, it is a good idea to make your local variable
names unique within the first 32 characters, and global variable names
unique within the first 6 characters.
kilograms KILOGRAMS KilogramsSome HP-UX programming languages (such as Pascal and FORTRAN) are case-insensitive. When writing an HP C program that calls routines from these other languages, you must be aware of this difference in sensitivity.
Strings are also case-sensitive. The system recognizes the following two strings as distinct:
"THE RAIN IN SPAIN" "the rain in spain"
| NOTE | The const, signed, and volatile keywords are part of the ANSI/ISO standard, but not part of the K&R language definition. |
switch (getchar())
{
case "r":
case "R":
moveright();
break;
...
}
A char type has a minimum value of -128 and a maximum value of 127.
The numeric range for unsigned char is 1 byte, with a minimum
value of 0 and a maximum value of 255.
/* declare factor as a constant float */ const float factor = 2.54;The value of factor cannot change after the initialization.
switch (grade){
case "A":
printf("Excellent\n");
break;
default:
printf("Invalid grade\n");
break;
}
The lower normalized bound is 2.225E-308. The lower denormalized bound is 4.941E-324. The upper bound is 1.798E+308.
Other floating-point types are float and long double.
The range for float is:
The range for int is -2,147,483,648 through 2,147,483,647.
The range for unsigned int is 0 through 4,294,967,295.
The long long 64-bit data type is supported as an extension to the language when you use the -Ae compile-line option.
The range for long long is -9,223,372,036,854,775,808 through
+9,223,372,036,854,775,807.
NOTE: __restrict__ qualifier can only be used with pointers.
Example usages:
int a = 10;
<
int *__restrict__ b = &a;
The range for short is -32,768 through 32,767.
The range for unsigned short is 0 through 65,535.
This keyword is implemented as an HP-specific type qualifier, with the same syntax as const and volatile, but not the same semantics. Syntax examples:
__thread int var; int __thread var;Semantics for the __thread keyword: Only variables of static duration can be thread specific. Thread specific data objects can not be initialized. Pointers of static duration that are not thread specific may not be initialized with the address of a thread specific object - assignment is okay. All global variables, thread specific or not, are initialized to zero by the linker implicitly.
Only one declaration, for example,
__thread int x;is allowed in one compilation unit that contributes to the program (including libraries linked into the executable). All other declarations must be strictly references:
extern __thread int x;Even though __thread has the same syntax as a type qualifier, it does not qualify the type, but is a storage class specification for the data object. As such, it is type compatible with non-thread-specific data objects of the same type. That is, a thread specific data int is type compatible with an ordinary int, (unlike const and volatile qualified int).
Note that use of the __thread keyword in a shared library will
prevent that shared library from being dynamically loaded (that is, loaded
via an explicit call to
shl_load()).
void func(int a, int b)
{
. . .
}
This indicates that the function func() does not return a value.
Likewise, on the calling side, you declare
func() as:
extern void func(int, int);
[storage_class_specifier] [data_type] variable_name [=initial_value];where:
int age; /* integer variable "age" */
int length, width; /* abbreviated declaration of two
variables*/
float ph; /* floating-point variable "ph" */
char a_letter; /* character variable "a_letter" */
int values[10]; /* array of 10 integers named values */
enum days {mon, wed, fri}; /* enumerated variable "days" */
A typedef declaration may appear anywhere a variable declaration may appear and obeys the same scoping rules as a normal declaration. Once declared, a typedef name may be used anywhere that the type is allowed (such as in a declaration, cast operation, or sizeof operation). You can write typedef names in all uppercase so that they are not confused with variable names.
You may not include an initializer with a typedef.
The statement:
typedef long int FOUR_BYTE_INT;makes the name FOUR_BYTE_INT synonymous with long int. The following two declarations are now identical:
long int j; FOUR_BYTE_INT j;
typedef struct {
char month[4];
int day;
int year;
} BIRTHDAY;
typedef char A_LINE[80]; /* A_LINE is an array of
* 80 characters */
#if SMALL_COMPUTER typedef int SHORTINT; typedef long LONGINT; #elif BIG_COMPUTER typedef short SHORTINT; typedef int LONGINT; #endifThis is useful when writing code to run on two computers, a small computer where an int is two bytes, and a large computer where an int is four bytes. Instead of using short, long, and int, you can use SHORTINT and LONGINT and be assured that SHORTINT is two bytes and LONGINT is four bytes regardless of the machine.
typedef float *PTRF, ARRAYF[], FUNCF();This declares three new types called PTRF (a pointer to a float), ARRAYF (an array of floats), and FUNCF (a function returning a float). These typedefs could then be used in declarations such as the following:
PTRF x[5]; /* a 5-element array of pointers to floats */ FUNCF z; /* A function returning a float */
| wrong | right |
|---|---|
typedef char STR[80];
STR string, *ptr;
main()
{
ptr = string;
printf("ptr = %d\n", ptr);
ptr++;
printf("ptr = %d\n", ptr);
}
*** Run-Time Results ***
ptr = 3997696
ptr = 3997776
|
typedef char STR[80];
STR string;
char *ptr;
main()
{
ptr = string;
printf("ptr = %d\n", ptr);
ptr++;
printf("ptr = %d\n", ptr);
}
*** Run-Time Results ***
ptr = 3997696
ptr = 3997697
|
| NOTE | The separate name spaces for goto labels and for each struct, union, or enum definition are part of the ANSI/ISO standard, but not part of the K&R language definition. |
The following example uses the same name, overuse, in four different ways:
int main(void)
{
int overuse; /* normal identifier */
struct overuse { /* tag name */
float overuse; /* member name */
char *p;
} x;
goto overuse;
overuse: overuse = 3; /* label name */
}
struct A {
int x;
float y;
};
struct B {
int x;
float y;
};
The members in struct A are distinct from the members in structB.
#define square(arg) arg * arg
int main(void)
{
...
square:
...
}
Every constant has two properties: value and type.
For example, the constant 15 has value 15 and type int.
The data type assigned to an integer constant is the first in which it will fit from the list on the right for the constant declaration on the left:
| Constant | Assigned Data Type |
|---|---|
| decimal (no suffix) | int, long int, unsigned long int |
| octal or hex (no suffix) | int, unsigned int, long, unsigned long |
| letter u or U suffix | unsigned int, unsigned long int |
| letter l or L suffix | long, unsigned long |
| both letters u or U and | unsigned long l or L suffix: |
| letters ll or LL suffix: | long long, unsigned long long |
| both letters u or U and ll or LL suffix: | unsigned long long |
| Decimal | Octal | Hexadecimal |
|---|---|---|
| 3 | 003 | 0x3 |
| 8 | 010 | 0x8 |
| 15 | 017 | 0xF |
| 16 | 020 | 0x10 |
| 21 | 025 | 0x15 |
| -87 | -0127 | -0x57 |
| 187 | 0273 | 0xBB |
| 255 | 0377 | 0xff |
The number may be followed by an f or F, to signify that it is of type float, or by an l or L, to signify that it is of type long double. If the number does not have a suffix, it is of type double even if it can be accurately represented in four bytes.
If the magnitude of a floating-point constant is too great or too small to be represented in a double, the C compiler will substitute a value that can be represented. This substitute value is not always predictable.
You may precede a floating-point constant with the unary plus or minus
operator to make its value positive or negative.
The letter e or E, standing for exponent, is used to separate the two parts.
The floating-point constant 3e2, for instance, is interpreted as 3*(102),
or 300. Likewise, the value -2.5e-4 is interpreted as -2.5/(104),
or -0.00025.
| Constant | Legal or Illegal |
|---|---|
| 3. | legal |
| 35 | legal - interpreted as an integer. |
| 3.141 | legal |
| 3,500.45 | illegal - commas are illegal. |
| .3333333333 | legal |
| 4E | illegal - the exponent must be followed by a number |
| 0.3 | legal |
| -3e2 | legal |
| 4e3.6 | illegal - the exponent must be an integer |
| 3.0E5 | legal |
| +3.6 | legal |
| 0.4E-5 | legal |
The value of a character constant is the integer ISO Latin-1 value of
the character. For example, the value of the constant x is 120.
| Escape Code | Character | What it Does |
|---|---|---|
| \a | Audible alert | Rings the terminal's bell. |
| \b | Backspace | Moves the cursor back one space. |
| \f | Formfeed | Moves the cursor to the next logical page. |
| \n | Newline | Prints a newline. |
| \r | Carriage return | Prints a carriage return. |
| \t | Horizontal tab | Prints a horizontal tab. |
| \v | Vertical tab | Prints a vertical tab. |
| \\ | Backslash | Prints a backslash. |
| \? | Question mark | Prints a question mark. |
| \' | Single quote | Prints a single quote. |
| \" | Double quote | Prints a double quote. |
The escape sequences for octal and hexadecimal numbers are commonly
used to represent characters. For example, if ISO Latin-1 representations
are being used, the letter a may be written as \141 or
\x61
and Z as \132 or \x5A. This syntax is most frequently
used to represent the null character as \0. This is exactly equivalent
to the numeric constant zero (0). When you use the octal format, you do
not need to include the zero prefix as you would for a normal octal constant.
For example, the following assignments are legal:
{
char x; /* 1-byte integer */
unsigned short int si; /* 2-byte integer */
unsigned long int li; /* 4-byte integer */
/* the following two assignments are portable: */
x = "j"; /* 1-byte character constant */
li = L"j"; /* 4-byte wide char constant */
/* the following two assignments are not portable,
and are not recommended: */
si = "ef"; /* 2-character constant */
li = "abcd"; /* 4-character constant */
}
The variable si is assigned the value of e and f,
where each character takes up 8 bits of the 16-bit value. The HP C compiler
places the last character in the rightmost (least significant) byte. Therefore,
the constant ef will have a hexadecimal value of 6566. Since the
order in which bytes are assigned is machine dependent, other machines
may reverse the order, assigning f to the most significant byte.
In that case, the resulting value would be 6665. For maximum portability,
do not use multi-character constants. Use character arrays instead.
"A short string"becomes an array with 15 elements.
Like a character constant, a string constant can begin with the letter L to indicate that it is a string constant in an extended character set.
To span a string constant over more than one line, use the backslash character (\), also called the continuation character. The following, for instance, is legal:
strcpy(string,"This is a very long string that requires more \ than one line");Note that if you indent the second line, the spaces will be part of the string.
The compiler concatenates adjacent string constants. Therefore, you can also span a string constant over one line as shown:
strcpy(string, "This is a very long string that requires more " "than one line");When you indent the second line with this method, the spaces are not part of the string.
The type of a string is array of char, and strings obey the same conversion rules as other arrays. Except when a string appears as the operand of sizeof or as an initializer, it is converted to a pointer to the first element of the string. Note also that the null string,
""is legal, and contains a single trailing null character.
The following shows how a program can be organized:
/* preprocessor directives */
#include <stdio.h>
#define WEIGHTING_FACTOR 0.6
/* global typedef declaration */
typedef float THIRTY_TWO_BIT_REAL;
/* global variable declaration */
THIRTY_TWO_BIT_REAL correction_factor = 1.15;
/* prototype */
float average (float arg1, THIRTY_TWO_BIT_REAL arg2)
/* start of function body */
{
/* local variable declaration */
float mean;
/* assignment statement */
mean = (arg1 * WEIGHTING_FACTOR) +
(arg2 * (1.0 - WEIGHTING_FACTOR));
/* return statement */
return (mean * correction_factor);
/* end of function body */
}
int main(void)
/* start of function body */
{
/* local variable declarations */
float value1, value2, result;
/* statements */
printf("Enter two values -- ");
scanf("%f%f", &value1, &value2);
result = average(value1, value2);
/* continuation line */
printf("The weighted average using a correction \
factor of %4.2f is %5.2f\n", correction_factor, result);
/* end of function body */
}