4 常量和C预处理器

2 Character Strings: An Introduction

2.3 The strlen() function

The previous chapter unleashed the sizeof operator, which gives the size of things in bytes. The strlen() function gives the length of a string in characters. Because it takes one byte to hold one character, you might suppose that both would give the same result when applied to a string, but they don't. Add a few lines to the example, as shown in Listing 4.3 , and see why.

Listing 4.3 The praise2.c Program

c 复制代码
/* praise2.c */
// try the %u or %lu specifiers if your implementation
// does not recognize the %zd specifier
#include <stdio.h>
#include <string.h> /* provides strlen() prototype */
#define PRAISE "You are an extraordinary being."

int main(void){
    char name[40];
    printf("What's your name? ");
    scanf("%s", name);
    printf("Hello, %s. %s\n", name, PRAISE);
    printf("Your name of %zd letters occupies %zd memory cells.\n",
 strlen(name), sizeof name);
    printf("The phrase of praise has %zd letters ",
    strlen(PRAISE));
    printf("and occupies %zd memory cells.\n", sizeof PRAISE);
    return 0;
} 

If you are using a pre-ANSI C compiler, you might have to remove the following line:

c 复制代码
#include <string.h>

The string.h file contains function prototypes for several string-related functions, including strlen(). Chapter 11 , "Character Strings and String Functions," discusses this header file more

fully. (By the way, some pre-ANSI Unix systems use strings.h instead of string.h to contain declarations for string functions.)

More generally, C divides the C function library into families of related functions and provides a header file for each family. For example, printf() and scanf() belong to a family of standard input and output functions and use the stdio.h header file. The strlen() function joins several other string-related functions, such as functions to copy strings and to search through strings, in a family served by the string.h header.

Notice that Listing 4.3 uses two methods to handle long printf() statements. The first method spreads one printf() statement over two lines. (You can break a line between arguments to printf() but not in the middle of a string---that is, not between the quotation marks.) The second method uses two printf() statements to print just one line. The newline

character ( \n) appears only in the second statement. Running the program could produce the

following interchange:

c 复制代码
What's your name? Serendipity Chance
 Hello, Serendipity. You are an extraordinary being.
Your name of 11 letters occupies 40 memory cells.
 The phrase of praise has 31 letters and occupies 32 memory cells. 

See what happens. The array name has 40 memory cells, and that is what the sizeof operator reports. Only the first 11 cells are needed to hold Serendipity, however, and that is what

strlen() reports. The twelfth cell in the array name contains the null character, and its presence tells strlen() when to stop counting. Figure 4.4illustrates this concept with a shorter

string.

When you get to PRAISE, you find that strlen() again gives you the exact number of characters (including spaces and punctuation) in the string. The sizeof operator gives you a

number one larger because it also counts the invisible null character used to end the string. The

program didn't tell the computer how much memory to set aside to store the phrase. It had to

count the number of characters between the double quotes itself.

As mentioned in Chapter 3 , "Data and C," the C99 and C11 standards use a %zd specifier for

the type used by the sizeof operator. This also applies for type returned by strlen(). For

earlier versions of C you need to know the actual type returned by sizeof and strlen(); typically that would be unsigned or unsigned long .

One other point: The preceding chapter used sizeof with parentheses, but this example

doesn't. Whether you use parentheses depends on whether you want the size of a type or the

size of a particular quantity. Parentheses are required for types but are optional for particular

quantities. That is, you would use sizeof(char) or sizeof(float) but can use sizeof name

or sizeof 6.28. However, it is all right to use parentheses in these cases, too, as in sizeof

(6.28) .

The last example used strlen() and sizeof for the rather trivial purpose of satisfying a user's

potential curiosity. Actually, however, strlen() and sizeof are important programming

tools. For example, strlen() is useful in all sorts of character-string programs, as you'll see in

Chapter 11

3 常量和C预处理器

Sometimes you need to use a constant in a program. For example, you could give the circumference of a circle as follows:

c 复制代码
circumference = 3.14159 * diameter; 

Here, the constant 3.14159 represents the world-famous constant pi (π). To use a constant,

just type in the actual value, as in the example. However, there are good reasons to use a

symbolic constant instead. That is, you could use a statement such as the following and have the

computer substitute in the actual value later:

c 复制代码
circumference = pi * diameter;

Why is it better to use a symbolic constant? First, a name tells you more than a number does.

Compare the following two statements:

c 复制代码
owed = 0.015 * housevalue;
owed = taxrate * housevalue;

If you read through a long program, the meaning of the second version is plainer.

Also, suppose you have used a constant in several places, and it becomes necessary to change its value. After all, tax rates do change. Then you only need to alter the definition of the

symbolic constant, rather than find and change every occurrence of the constant in the

program.

Okay, how do you set up a symbolic constant? One way is to declare a variable and set it equal

to the desired constant. You could write this:

c 复制代码
float taxrate;
taxrate = 0.015; 

This provides a symbolic name, but taxrate is a variable, so your program might change its value accidentally. Fortunately, C has a couple better ideas.

The original better idea is the C preprocessor. todo:替换为链接 In Chapter 2 , "Introducing C," you saw how the preprocessor uses #include to incorporate information from another file. The preprocessor also lets you define constants. Just add a line like the following at the top of the file containing your program:

c 复制代码
#define TAXRATE 0.015

When your program is compiled, the value 0.015 will be substituted everywhere you have used TAXRATE. This is called a compile-time substitution . By the time you run the program, all the substitutions have already been made. Such defined constants are often termed manifest constants .

Note the format. First comes #define. Next comes the symbolic name ( TAXRATE) for the constant and then the value ( 0.015) for the constant. (Note that this construction does not use the = sign.) So the general form is as follows:

c 复制代码
#define NAME value

You would substitute the symbolic name of your choice for NAME and the appropriate value for value. No semicolon is used because this is a substitution mechanism handled by the preprocessor, not a C statement. Why is TAXRATE capitalized? It is a sensible C tradition to type constants in uppercase. Then, when you encounter one in the depths of a program, you know immediately that it is a constant, not a variable. Capitalizing constants is just another technique to make programs more readable. Your programs will still work if you don't capitalize the constants, but capitalizing them is a reasonable habit to cultivate.

The names you use for symbolic constants must satisfy the same rules that the names of variables do. You can use uppercase and lowercase letters, digits, and the underscore character. The first character cannot be a digit.

The #define statement can be used for character and string constants, too. Just use single quotes for the former and double quotes for the latter. The following examples are valid:

c 复制代码
#define BEEP '\a'
#define TEE 'T'
#define ESC '\033'
#define OOPS "Now you have done it!" 

Remember that everything following the symbolic name is substituted for it. Don't make this common error:

c 复制代码
/* the following is wrong */
#define TOES = 20

If you do this, TOES is replaced by = 20, not just 20. In that case, a statement such as

c 复制代码
digits = fingers + TOES;

is converted to the following misrepresentation:

c 复制代码
 digits = fingers + = 20;
3.1 The const Modifier

C90 added a second way to create symbolic constants---using the const keyword to convert a declaration for a variable into a declaration for a constant:

c 复制代码
const int MONTHS = 12; // MONTHS a symbolic constant for 12 

This makes MONTHS into a read-only value. That is, you can display MONTHS and use it in calculations, but you cannot alter the value of MONTHS. This newer approach is more flexible than using #define; it lets you declare a type, and it allows better control over which parts of a program can use the constant. Chapter 12 , "Storage Classes, Linkage, and Memory Management" discusses this and other uses of const .

Actually, C has yet a third way to create symbolic constants, and that is the enum facility discussed in Chapter 14 , "Structures and Other Data Forms."

3.2 Manifest Constants on the Job
相关推荐
Eiceblue几秒前
在.NET用C#将Word文档转换为HTML格式
开发语言·vscode·c#·html·word·.net
步、步、为营2 分钟前
C#局部函数 VS Lambda表达式
开发语言·windows·c#
Kevinyu_4 分钟前
Java ArrayList
java·开发语言·windows
忆源4 分钟前
Linux高级--3.3.1 C++ spdlog 开源异步日志方案
java·c++·开源
stormjun19 分钟前
基于 Python 的深度学习的车俩特征分析系统,附源码
开发语言·python·深度学习·车辆特征分析·python 车辆特征分析
BinaryBardC20 分钟前
Dart语言的字符串处理
开发语言·后端·golang
数据的世界0123 分钟前
C#表达式和运算符
开发语言·c#
一只小菜鸡29 分钟前
python+django+Nacos实现配置动态更新-集中管理配置(实现mysql配置动态读取及动态更新)
开发语言·python·django
有梦想的咕噜32 分钟前
Qt Quick 和 Qt Designer
开发语言·qt
0xCC说逆向36 分钟前
Windows图形界面(GUI)-QT-C/C++ - Qt List Widget详解与应用
c语言·开发语言·c++·windows·qt·win32·1024程序员节