简体   繁体   English

澄清C中的char指针

[英]Clarification of char pointers in C

I'm working through K&R second edition, chapter 5. 我正在研究K&R第二版,第5章。

On page 87, pointers to character arrays are introduced as: 在页87,引入字符数组的指针如下:

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

How does one know that pmessage is a pointer to a character array, and not a pointer to a single character? 如何知道pmessage是指向字符数组的指针,而不是指向单个字符的指针?

To expand, on page 94, the following function is defined: 要扩展,请在第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];
}

If one were simply provided with the function declaration for the above, how could one know whether a single character or a character array is returned? 如果只提供了上面的函数声明,那么如何知道是返回单个字符还是字符数组?

If one were to assume the return from month_name() is a character array and iterate over it until a NULL is encountered, but the return was in fact a single character then is there not the potential for a segmentation fault? 如果假设从month_name()返回是一个字符数组并迭代它直到遇到NULL ,但返回实际上是单个字符,那么是否有可能出现分段错误?

Could somebody please demonstrate the declaration and assignment of a pointer to a single character vs a character array, their usage with functions and identification of which has been returned? 有人可以演示一个指向单个字符与字符数组的指针的声明和赋值,它们对函数的使用以及已经返回的标识?

So what you have is a string literal which is an array of char with static storage duration: 所以你拥有的是一个字符串文字,它是一个具有静态存储持续时间的char数组:

"Now is the time"

in most contexts an array will decay into a pointer to the first element which is what happens here: 在大多数情况下,数组会衰减成指向第一个元素的指针,这是在这里发生的事情:

pmessage = "Now is the time";

You need to design and document your interface in such a way that you know what to expect for the input and output. 您需要以这样一种方式设计和记录您的界面,使您知道输入和输出的期望。 There is no run-time information to tell the nature of what is being pointed to. 没有运行时信息来说明所指出的内容的性质。

For example if we look at the man page of strtok it tells us: 例如,如果我们查看strtok手册页,它会告诉我们:

Each call to strtok() returns a pointer to a null-terminated string containing the next token. 每次调用strtok()都会返回一个指向包含下一个标记的以null结尾的字符串的指针。

and so the programmer knows exactly what to expect and deals with the result accordingly. 因此程序员确切地知道预期的结果并相应地处理结果。

In the case where you have a pointer to a single char and instead it like a C style string then you will have undefined behavior because you will be accessing memory out of bounds. 如果你有一个指向单个字符的指针而不是像C样式字符串,那么你将有未定义的行为,因为你将访问超出范围的内存。 A segmentation fault is one possibility but being undefined just means the result is unpredictable. 分段错误是一种可能,但未定义仅意味着结果是不可预测的。

What does 是什么

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

mean? 意思?
char *pmessage; means that you declared pmessage as a pointer to char 表示您将pmessage声明为char的指针
pmessage = "Now is the time"; means that pmessage now points to the first character of the string literal Now is the time . 意味着pmessage现在指向字符串文字的第一个字符 Now is the time

When you return pmessage from a function then a pointer to string literal is returned. 从函数返回pmessage时,将返回指向字符串文字的指针。
If you will print pmessage with %c specifier then it will print N and if you will print it with %s then it will print the entire string literal. 如果您将使用%c说明符打印pmessage ,那么它将打印N ,如果您将使用%s打印它,那么它将打印整个字符串文字。

printf("%c\n", *N);     // 'N' will be printed
printf("%s\n", N);      //  "Now is the time" will be printed 

Strange as it seems, C trusts the intelligence of the programmer. 看起来很奇怪,C信任程序员的智慧。 If I see a function such as: 如果我看到如下功能:

/* 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];
}

I look at the documentation and read that it returns a NUL-terminated string that is a pointer to statically allocated memory. 我查看文档并读取它返回一个NUL终止的字符串,该字符串是指向静态分配的内存的指针。 That is enough for me to treat the return value as I should. 这足以让我按照自己的意愿对待回报值。

If the creator of the function changes the return value in a future release to a different kind of string, they better shout it out loud, change the function name, or make it very clear otherwise it's very bad behavior from their side. 如果函数的创建者将未来版本中的返回值更改为不同类型的字符串,则他们最好大声喊出它,更改函数名称,或者使其非常清楚,否则它们的行为非常糟糕。

If I on the other hand fail to treat the return value correctly even though it's documented properly, well I wouldn't be so intelligent then and perhaps cut out to be a Java developer. 另一方面,如果我没有正确处理返回值,即使它被正确记录,那么我也不会那么聪明,也许可能会成为一名Java开发人员。

Lastly, if the function is not documented, find its owner and burn his house. 最后,如果没有记录该功能,找到它的主人并烧毁他的房子。 1 1

1 if it's in a library this is released ! 1 如果它在库中,则会被释放 Don't burn people's house as soon as they start coding a library! 一旦他们开始编写图书馆,就不要烧人的房子! ^_^ ^ _ ^

How does one know that pmessage is a pointer to a character array, and not a pointer to a single character? 如何知道pmessage是指向字符数组的指针,而不是指向单个字符的指针?

You don't. 你没有。 At least, there's no way to tell from the pointer value itself whether it points to a single char or the first element of an array of char . 至少,没有办法从指针值本身告诉它是指向单个char还是char数组的第一个元素。 It can be used either way. 它可以任何一种方式使用。

You have to rely on context or specify explicitly how the pointer is to be used. 您必须依赖上下文或明确指定如何使用指针。 For example, scanf uses different conversion specifiers in order to determine whether a pointer is pointing to a single char : 例如, scanf使用不同的转换说明符来确定指针是否指向单个char

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

or an array of char : char数组:

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

Remember that when it isn't the operand of the sizeof or unary & operators or a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T " will be converted ("decay") to an expression of "pointer to T ", and the value of the expression will be the address of the first element of the array, so that last line could also be written 请记住,当它不是sizeof或一元&运算符的操作数或用于在声明中初始化另一个数组的字符串文字时,将转换“N元素数组T ”的表达式(“衰减”)表达式为“指向T指针”,表达式的值将是数组第一个元素的地址,因此最后一行也可以写入

scanf( "%s", array_of_char );

Because of that conversion rule, anytime you pass an array expression to a function, what the function actually receives is a pointer value. 由于该转换规则,无论何时将数组表达式传递给函数,函数实际接收的是指针值。 In fact, the function declarations 实际上,函数声明

void foo( char str[N] );

and

void foo( char str[] );

are equivalent to 相当于

void foo( char *str );

All three treat str as a pointer to char . 这三个都将str视为指向char的指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM