6

我正在阅读 K&R 第二版第 5 章。

在第 87 页,指向字符数组的指针被介绍为:

char *pmessage;
pmessage = "Now is the time";

怎么知道这pmessage是一个指向字符数组的指针,而不是指向单个字符的指针?

为了扩展,在第 94 页,定义了以下函数:

/* month_name: return the name of the n-th month */
char *month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        ...
    };

    return (n < 1 || n > 12) ? name[0] : name[n];
}

如果只是为上面提供了函数声明,那么如何知道返回的是单个字符还是字符数组?

如果假设返回 frommonth_name()是一个字符数组并迭代它直到NULL遇到 a ,但返回实际上是单个字符,那么是否没有分段错误的可能性?

有人可以演示指向单个字符与字符数组的指针的声明和分配,它们与函数的用法以及已返回的标识吗?

4

4 回答 4

4

所以你所拥有的是一个字符串文字,它是一个具有静态存储持续时间的 char 数组:

"Now is the time"

在大多数情况下,数组将衰减为指向第一个元素的指针,这就是这里发生的情况:

pmessage = "Now is the time";

您需要以您知道输入和输出的期望的方式设计和记录您的界面。没有运行时信息来说明所指向内容的性质。

例如,如果我们查看strtok 的手册页,它会告诉我们:

每次调用 strtok() 都会返回一个指向包含下一个标记的以空字符结尾的字符串的指针。

所以程序员确切地知道会发生什么并相应地处理结果。

如果您有一个指向单个字符的指针,而不是像C 风格的字符串,那么您将有未定义的行为,因为您将越界访问内存。分段错误是一种可能性,但未定义仅意味着结果不可预测。

于 2014-03-14T12:06:33.937 回答
2

做什么

char *pmessage;
pmessage = "Now is the time";  

意思是?
char *pmessage;表示您声明pmessage为指针,char
pmessage = "Now is the time";表示pmessage现在指向字符串字面量 的第一个字符Now is the time

当您pmessage从函数返回时,将返回指向字符串文字的指针。
如果您将pmessage使用%c说明符打印,那么它将打印N,如果您将使用它打印,%s那么它将打印整个字符串文字。

printf("%c\n", *N);     // 'N' will be printed
printf("%s\n", N);      //  "Now is the time" will be printed 
于 2014-03-14T12:06:19.727 回答
2

看起来很奇怪,C 信任程序员的智慧。如果我看到一个函数,例如:

/* month_name: return the name of the n-th month */
char *month_name(int n)
{
    static char *name[] = {
        "Illegal month",
        "January", "February", "March",
        ...
    };

    return (n < 1 || n > 12) ? name[0] : name[n];
}

我查看文档并读到它返回一个以 NUL 结尾的字符串,该字符串是指向静态分配内存的指针。这足以让我按我应该的方式对待返回值。

如果函数的创建者在将来的版本中将返回值更改为不同类型的字符串,他们最好大声喊出来,更改函数名称,或者说得很清楚,否则从他们的角度来看这是非常糟糕的行为。

另一方面,如果我未能正确处理返回值,即使它已正确记录,那么我就不会那么聪明,并且可能会成为一名 Java 开发人员。

最后,如果功能没有记录,找到它的主人并烧毁他的房子。1

1 如果它在库中,则已发布!不要在人们开始编写库时就烧毁他们的房子!^_^

于 2014-03-14T12:08:56.237 回答
1

怎么知道 pmessage 是指向字符数组的指针,而不是指向单个字符的指针?

你没有。至少,没有办法从指针值本身判断它是指向单个char元素还是指向char. 它可以使用任何一种方式。

您必须依赖上下文或明确指定指针的使用方式。例如,scanf使用不同的转换说明符来确定指针是否指向单个char:

char single_char;
scanf( " %c", &single_char );

或数组char

char array_of_char[N];
scanf( "%s", &array_of_char[0] );

请记住,当它不是sizeof或一元运算符的操作数&或用于在声明中初始化另一个数组的字符串文字时,类型为“N-element array of T”的表达式将被转换(“decay”)为表达式的“指针T”,表达式的值将是数组的第一个元素的地址,所以最后一行也可以写

scanf( "%s", array_of_char );

由于该转换规则,每当您将数组表达式传递给函数时,函数实际接收的是指针值。事实上,函数声明

void foo( char str[N] );

void foo( char str[] );

相当于

void foo( char *str );

这三个都被str视为指向char.

于 2014-03-14T15:22:53.493 回答