I don't understand what a pointer does in the for
loop. What does the *p
do in the following loop?
我不明白指针在for循环中做什么。在下面的循环中*p做了什么?
char str[128] = "Some Text";
char *p;
for (p = str; *p /*what does this mean?*/; p++)
{
// Code
}
I do understand the rest, but why isn't *p
like p > 3
or something like that?
Why is it alone?
Why is it written that way?
我知道其他的,但是为什么不像p > 3之类的?为什么孤独?为什么这样写?
14 个解决方案
#1
52
In a Boolean context such as the condition of a for
loop, each expression in C evaluates to true (non-zero) or false (zero).
在布尔上下文中,例如for循环的条件中,C中的每个表达式计算为true(非零)或false(零)。
You want the for
loop to terminate, when it reaches the end of the string.
当for循环到达字符串的末尾时,您希望它终止。
In C, each string is terminated with the character '\0'
, which is practically 0
. So, when the for
loop reaches the end of string, *p
evaluates to '\0'
, which is 0
, which evaluates to false, which terminates the for
loop.
在C语言中,每个字符串都以字符'\0'结束,这实际上是0。因此,当for循环到达字符串的末尾时,*p计算为'\0',即为0,计算结果为false,从而终止for循环。
#2
29
The for loop will terminate if whatever lies between the two ;
in the statement is zero (false). *p
dereferences p and returns the char
, p
points to. According to Dennis Ritchie "C treats strings as arrays of characters conventionally terminated by a marker". That marker is the null character with (ASCII) value of zero. So, this for loop :
如果在两者之间存在任何东西,则for循环将终止;在语句中为0 (false)。*p去引用p并返回char, p指向。根据Dennis Ritchie的说法,“C”将字符串作为一组字符的数组,这些字符通常会被标记终止。该标记是空字符,(ASCII)值为0。这个for循环
for (p = str; *p; p++)
is equivalent to these
相当于这些
for (p = str; *p != '\0'; p++)
for (p = str; *p != 0; p++)
for (p = str; p[0] != '\0'; p++)
Another name for the null terminating character is sentinel or according to Donald Knuth "dummy value" (Art of Computer Programming, Volume 1). Here is a diagram of the str
string, the indexes (offsets from the start) of each character and the values at each index :
空终止字符的另一个名称是sentinel或根据Donald Knuth“哑值”(计算机编程艺术,第1卷)。
For completeness and after a request at the comments here is what the debugger sees in the memory block that str
occupies :
为了完整性,在注释中的请求之后,调试器会看到str占用的内存块:
0x00007fffffffe6a0:
0x53 0x6f 0x6d 0x65 0x20 0x54 0x65 0x78 0x74 0x00 0x00 0x00 0x00 0x00 0x00 0x00
S o m e T e x t
- The hex value at the first line is the address (64bit) of this memory block. That's where
p
points to at the start of the for loop. - 第一行的十六进制值是这个内存块的地址(64位)。这就是p在for循环开始时的位置。
- On the 2nd line you see the hex values of the letters in your string. You can see an ASCII table here. The last char in your string is
t
with hex value of0x74
. After that you have the string's null character0x00
. Then you see a few more null characters because I built in debug mode and the compiler zero-initialized. Normally you would see garbage (seemingly random values) - 在第二行,你可以看到字符串中字母的十六进制值。您可以在这里看到一个ASCII表。字符串中的最后一个字符是t,十六进制值为0x74。在此之后,您将得到字符串的空字符0x00。然后您会看到更多的空字符,因为我在调试模式中构建,编译器为零初始化。通常你会看到垃圾(看似随机的值)
- On the 3rd line I added the chars of your string for reference
- 在第三行,我添加了字符串的字符作为参考
I understand you are on precipitous learning curve at the moment with pointers in C, but eventually you'll be able to say "I C the point"
我知道你现在正处在一个陡峭的学习曲线上用C表示指针,但最终你会说"I C the point"
#3
19
This could be rewritten like this
可以这样重写
for (p = str; *p != '\0'; p++)
{
// Code
}
In C, a string must always be terminated by a null character, which is the same as '\0' or 0
.
在C中,字符串必须总是以null字符结束,这与“\0”或0相同。
#4
13
Lets analyze it the dry but depth way!
Or as D. Ritchie would say: Let's do it with the power of assembly language and the convenience of … assembly language.
或者像D. Ritchie所说的:让我们用汇编语言的力量和汇编语言的便利来做这件事。
I'll try to explain all necessary aspects by referencing the ISO/IEC:9899 (emphasis mine)- C99 standard. (The post style is motivated by Donald Knuth's phrase "Science is what we understand well enough to explain to a computer. Art is everything else we do. ")
我将引用ISO/IEC:9899(强调我的)- C99标准来解释所有必要的方面。(这篇文章的风格是由Donald Knuth所说的“科学是我们理解的足以向计算机解释的东西”所激发的。艺术就是我们所做的一切。”)
First of all, lets inspect what exactly is the for
-loop supposed to do!
Referring to ISO/IEC:9899 6.8.5 "Iteration statements"
参照ISO/IEC: 98996.8.5“迭代语句”
Semantics
语义
4 An iteration statement causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0.
迭代语句导致一个名为循环体的语句被重复执行,直到控制表达式比较等于0。
So far nothing new I guess, so lets get it on:
到目前为止,我想没什么新鲜的,所以我们开始吧:
6.8.5.3 The for statement
6.8.5.3 for语句
1 The statement
for ( clause-1 ; expression-2 ; expression-3 ) statement
1 .声明(第1条);expression-2;expression-3)语句
behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. ...
表达式表达式表达式表达式-2是在每次执行循环体之前计算的控制表达式。
So we now know the body (in your case // Code
) will be executed as long the beforehand evaluated value of your *p
is not zero.
因此我们现在知道主体(在您的情况下//代码)将被执行,只要您的*p的预先评估值不是0。
... The expression expression-3 is evaluated as a void expression after each execution of the loop body.[...]
…表达式expression-3在每次执行循环体之后被评估为一个空表达式。
So now we know, (I assume digging up p++
's definition is not necessary?!) that for each iteration p
increments, so there may be a change in *p
.
现在我们知道,(我假设挖掘出p+的定义是不必要的?!)对于每个迭代p增量,所以*p中可能会有变化。
The following point is not related, but I'm adding it since this makes the Semantic part of for
complete and its well to know since its the reason, why for(;;)
is a inf-loop.
下面这一点没有关系,但我添加了它,因为这使for complete的语义部分很清楚,因为它是原因,为什么for(;;)是一个inf循环。
2 (---) Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.
2(--)第1条和第3条都可以省略。省略的表达式-2被一个非零常数所取代。
Ok, that's the dry but information-enriched part of what the for
loop does in your case.
好了,这就是for循环在你的例子中干的但是信息丰富的部分。
Now lets get over to pointer arithmetic:
6.5.6 Additive operators
6.5.6加法操作符
Constraints
约束
2 For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)
2对于加法,两个操作数都应该具有算术类型,或者一个操作数应该是指向对象类型的指针,另一个操作数应该具有整数类型。(递增相当于加1。)
So in your case you are adding 1 (integer) to the "pointer to an object"-type.
因此,在你的例子中,你要向“指向一个对象的指针”-type添加1(整型)。
What is equivalent to increasing the Address by the sizeof its pointed to type like shown in this picture of tomislav kostic:
就像托米斯拉夫·科斯蒂克(tomislav kostic)的这幅图中所示,通过其指向的类型的大小来增加地址,等于什么?
Now lets see what *p
actually does.
现在我们来看看*p是怎么做的。
6.5.3.2 Address and indirection operators
6.5.3.2地址和间接操作符
Constraints
约束
[...]
[…]
2 The operand of the unary * operator shall have pointer type.
一元*运算符的操作数应具有指针类型。
Semantics
语义
[...]
[…]
4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.
一元*运算符表示间接。如果操作数指向一个函数,则结果是一个函数指示器;如果它指向一个对象,则结果是一个lvalue指定对象。如果操作数类型为“指针类型”,则结果具有类型“类型”。如果一个无效的值被分配给指针,那么一元*操作符的行为是未定义的。
This is a bit dry again1 but for better understanding this can be reverse engineered by:
这又有点干涩了1,但为了更好地理解这一点,我们可以通过以下方法进行反向设计:
6.5.2.1 Array subscripting
6.5.2.1数组下标
[...]
[…]
Semantics
语义
2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).
后缀表达式后跟方括号[]中的表达式是数组对象元素的下标指定。下标运算符[]的定义是E1[E2]与(*((E1)+(E2))相同。
So *((p)+(0))
what is(since p+0
is same as p
... obvious) is equal to p[0]
, is doing nothing else as evaluating p
's object.
那么*(p)+(0)是什么(因为p+0等于p…显然的)等于p[0],它没有做任何其他的事情来计算p的对象。
And since we know, expression-2
of a for loop is interrupting the iteration if it is evaluating 0
, we can say it is the same as p[0] != 0
.
由于我们知道,for循环的表达式-2在取值为0时中断迭代,我们可以说它与p[0] != 0相同。
Now the final step
Lets just look onto the C-Coder's Friend; JSSCA... No, wait...our friend was called... ASCII Now as that's clarified, we can figure out what the 0
is representing.
让我们看看C-Coder的朋友;JSSCA……不,等等…我们的朋友叫…ASCII现在已经澄清了,我们可以算出0表示什么。
It is the NULL-token that in C is designating the end of a string.
在C中,空令牌表示字符串的结束。
So conclusive:
All, this is doing is:
所做的是:
Iterating the body of that for
-loop, until p
is actually pointing to the address, where the object evaluates to the "end of string"-token.
迭代该for循环的主体,直到p实际指向该地址,在该地址中,对象计算为“字符串的结束”—令牌。
Or:
或者:
Let p
go through the string until the end is reached.
让p穿过绳子直到到达终点。
And now just to cite my self; Something you never should forget:
(emphasis mine.....)
现在引用我的自我;你永远不应该忘记的事情:
变量是通过声明符(类型说明符)声明的,该声明符在标识符前面,标识符命名一个lvalue对象,可以对其值进行计算
It is neither more nor less!
它既不多也不少!
1That is, what I promised! ;)
那就是我答应过的!,)
#5
12
Before diving in, I would like to state a simple rule in C regarding an expression
在开始之前,我想在C中声明一个关于表达式的简单规则
When C requires the Boolean value of an expression, a
false
value is inferred when the expression compares equal to zero, and atrue
value otherwise. That is, whenever one writes当C需要一个表达式的布尔值时,当表达式比较为零时,就推断出一个假值,反之则推断出一个真值。也就是说,无论何时写作
if(expr)
where
expr
is any expression at all, the compiler essentially acts as if it had been written as当expr是任何表达式时,编译器的行为本质上就好像它是被写成的一样
if((expr) != 0)
Now coming to your question:
现在来回答你的问题:
What does the
*p
do in the following loop?在下面的循环中*p做了什么?
In C, strings are terminated by a null character '\0'
.
在C语言中,字符串以空字符'\0'结束。
Every character has a decimal equivalent. This '\0'
is an ASCII escape character. The decimal equivalent of '\0'
is 0
.
每个字符都有一个十进制的等价物。这个“\0”是一个ASCII转义字符。十进制的“\0”等于0。
So, the expression *p
in loop just check that the decimal equivalent of character at the memory address pointed by p
is either a zero or non-zero. When p
reaches the end of the string and finds the first '\0'
character, the expression *p
returns1 a zero value. A zero means false
in C. This is equivalent to testing *p != '\0'
or *p != 0
as stated above.
因此,循环中的表达式*p仅仅检查在p点的内存地址上的十进制字符是0或非0。当p到达字符串的末尾并找到第一个'\0'字符时,表达式*p returns1为零。0在c中表示为false。这相当于测试*p != '\0'或*p != 0,如上所述。
This is how it works:
这就是它的工作原理:
1 When *p
evaluates then the value of *p
is fetched from memory. This value is the value of expression *p
.
当*p求值时,从内存中获取*p的值。这个值是表达式*p的值。
#6
9
The *p Haiku
Poetically, I tried to represent the struggling of *p in the loop:
诗意地,我试图在循环中表现*p的挣扎:
Brave C *p(rogrammers)
勇敢的C * p(rogrammers)
In the loop of whilederness
在长细的循环中。
The NUL will stop them
核会阻止他们
This is an haiku poem, it consists of three lines, with the first and last line having 5 syllable, and the middle line having 7. Another example by @Samidamaru (a Master Haiku Poet, see comment below): First p equals str, Then p is incremented, Until *p is NUL.
这是一首俳句诗,由三行组成,第一行和最后一行有5个音节,中间一行有7个音节。@Samidamaru的另一个例子(一位著名的俳句诗人,见注释):首先p等于str,然后p增加,直到*p变成NUL。
A little bit of pop
Hour of Code ambassador, Jessica Alba
一小时的代码大使,杰西卡·阿尔芭
What does the *p do in the loop?
Following the imaginary advice of Jessica (who is citing D. Knuth (1)), we will try to see the meaning of *p in the for loop:
根据Jessica(引用D. Knuth(1)的假想建议,我们将在for循环中尝试理解*p的意义:
for (p = str; *p; p++)
To this goal we first examine how the unary operator "*" works in C: “The unary operator * is the indirection or deferencing operator; when applied to a pointer, it access the object the pointer points to.” (B. Kernighan and D. Ritchie (2))
为了达到这个目的,我们首先检查一元运算符“*”在C中的工作方式:“一元运算符*是间接运算符或延迟运算符;当应用到指针时,它访问指针指向的对象。(B. Kernighan和D. Ritchie (2))
So *p is simply the value pointed by p:
所以*p就是p点的值:
1.1 A closer look to the for loop
The for loop is composed of three instructions:
for循环由三条指令组成:
- p = str
- p = str
- *p
- * p
- p++
- p + +
In 1. we assign the pointer to the array str to p. In C the following assignments have the same effect:
在1。我们将指向数组str的指针赋给p。在C中,以下的赋值具有相同的效果:
p = &str[0];
p = str;
“By definition, the value of a variable or expression of type array is the address of element zero of the array” (K & R (2)). Moreover we have that “In evaluating a[i], C converts it to *(a+i) immediately. …. it follows that &a[i] and a+i are identical” (K & R (2)). If we put i = 0, we obtain the above assignments.
“根据定义,变量或类型数组表达式的值是数组的元素0的地址”(K & R(2))。此外,我们还有“在计算a[i]时,C会立即将它转换成*(a+i)。”....它遵循的是[i]和a+i是相同的”(K & R(2))。如果我们把i = 0,就得到了上面的赋值。
We can now state that, at the beginning of the for loop, p points to the first element of str.
现在我们可以声明,在for循环的开始,p指向str的第一个元素。
1.2 The core of the question
Let's move to the point 2., the core of your question. The second expression of the loop controls the exit condition: the instruction "*p" is evaluated and if is false the loop exit. This means that "*p" is equivalent to "*p != 0" or in words: when the value pointed by p is zero, exit.
我们再看点2。你的问题的核心。循环的第二个表达式控制退出条件:对指令“*p”进行计算,如果为false,则循环退出。这意味着“*p”等价于“*p != 0”,也就是说:当p的值为0时,退出。
Now, to understand when *p is zero we recall that the array str has been initialised as follows:
现在,为了理解当*p为0时,我们回想一下数组str已被初始化如下:
char str[128] = "Some Text";
and: “all string constants contain a null termination character (\0) as their last character” (gnu-manual). So the string actually stored in memory has a \0 at the end: "Some Text\0".
并且:“所有字符串常量都包含一个空终止字符(\0)作为它们的最后一个字符”(gnu-manual)。因此,实际上存储在内存中的字符串在末尾有一个\0:“Some Text\0”。
In the third instruction, p++, the pointer p is advanced to the next element of the str array, thus, at the 9-th iteration *p became 0 (or \0, NULL, NUL, see the answer from @Joe) and the loop exits.
在第三条指令中,p++,指针p被推进到str数组的下一个元素,因此,在第9次迭代*p变成0(或\0,NULL, NUL,从@Joe看到答案)和循环退出。
1.3 See to believe
A picture is worth a thousand words, here is a graphical representation of the loop:
一幅画胜过千言万语,这是循环的图形表示:
1.4 A further example: the same usage of *p in a different example
In the following snippet *p is used the same way but in a while loop:
在下面的代码片段*p中使用相同的方法,但在while循环中:
#include <stdio.h>
int main() {
char str[128] = "We all scream for ice cream!";
char *p = str;
// here we see again the loop exit condition *p == '\0'
while(*p) {
printf("%c", *p);
p++;
}
printf("\n");
}
May the for(;*C;)e be with you!
References
引用
(1) Vol. I, Fundamental Algorithms, Section 1.1 (1968)
(1)Vol. I,基本算法,Section 1.1 (1968)
(2) The C Programming Language Pg 94-99
(2)C编程语言Pg 94-99。
#7
4
A long time ago, in a PDP far, far away, resources were scarce, names got short: i
for index, p
for pointer would please early Jedi programmers.
很久以前,在一个遥远的PDP中,资源是稀缺的,名字是短的:i代表索引,p代表指针,这将取悦早期的绝地程序员。
Implicit tests told the truth in for
condition space. A single *
was all they typed, trusting p
and pushing it to the end of strings.
隐式测试在条件空间中告诉了真相。他们输入的只有一个*,信任p并把它推到字符串的末尾。
To this day, they use the for(e = s;*e;e++)
most familiar and elegant loop to defy the C++ empire and its cohorts of ctors, dtors and vile iterators. Bare bits and bytes against templates, exceptions and obscure types, only the brave still dare for C to fight, and uncast the void *
.
直到今天,他们仍在使用最为熟悉和优雅的for循环来对抗c++帝国以及它的ctors、dtors和卑鄙的迭代者。对模板、异常和模糊类型进行裸比特和字节,只有勇敢的C才敢战斗,并释放出空虚*。
#8
4
It takes advantage of the fact that the terminator to the string (eventually found by that for loop) will be an ASCII NUL
, which is a zero, which also happens to evaluate to false, thus terminating the for loop.
它利用了这样一个事实:字符串的终止符(最终由for循环找到)将是一个ASCII NUL,它是一个0,它也恰好计算为false,从而终止for循环。
It's worth noting the difference and similarity between 0, false, NULL and ASCII NUL. See this question: What is the difference between NULL, '\0' and 0
值得注意的是0、false、NULL和ASCII NUL之间的差异和相似之处。看看这个问题:NULL, '\0'和0之间的区别是什么
#9
4
I have tried to satisfy the bounty awarder's desires which were mentioned at various times. To keep it simple I have restricted my answer to three sections of three lines each, and because (as The Bellman said in his Rule Of Three) "What I tell you three times is true" (the theme of this answer).
我试着去满足那些在不同时期被提及的赏金者的欲望。为了简单起见,我把答案限制在每行三段,因为(正如行李员在他的三行规则中所说的)“我告诉你的三次都是真的”(这个答案的主题)。
Technical
技术
The truth of your for
loop terminates it when the expression *p
evaluates to 0
and this evaluation is performed before every iteration of the loop, note that in C 0
is false and anything else is true - that's a very expansive definition in other worlds!
当表达式*p的值为0,并且在循环的每次迭代之前执行这个评估时,你的for循环的真相就会终止,请注意,在c0中是错误的,其他的都是正确的——在其他的世界中这是一个非常广泛的定义!
The pointer variable p
is initialised once, to point to the start of the array with p = str
, and p
is incremented at the end of every iteration, so *p
is accessing successive elements of the array in each iteration.
指针变量p被初始化一次,指向带有p = str的数组的开始,并且p在每次迭代结束时都是递增的,所以*p在每次迭代中访问数组的连续元素。
The expression *p
will thus evaluate to 0
(false) when the array element read by *p
is the 0
or '\0'
terminator that signals the end of a C "string", but you can't see this zero in the initialisation of str
because it is supplied by the compiler automatically.
因此,当*p读取的数组元素是表示C“字符串”结束的0或'\0'终止符时,表达式*p将计算为0 (false),但在str的初始化中看不到这个0,因为编译器自动提供它。
Lyrical
抒情
Expressions of truth
真理的表达式
Are not understood by youth
青春不懂吗?
Read Ritchie and Knuth
阅读里奇和Knuth
Whimsical
反复无常的
Jessica Alba is a fine actress who is very knowledgeable, having taken on board truths from observing the development of computer technology, as these quotes reveal:
杰西卡·阿尔芭(Jessica Alba)是一位非常博学的女演员,她从观察计算机技术的发展中获得了一些真理,正如这些名言所揭示的:
"Every five years I feel like I'm a completely different person."
“每隔五年,我就会觉得自己完全变了一个人。”
"It's all about your product and how it performs. Either it works, or it doesn't."
这都是关于你的产品和它的表现。要么成功,要么失败。
#10
3
A haiku:
俳句:
WHY for (p=str; *p; p++)
IS for (p=str; p[0] != 0; p++)
THINK for (i=0; str[i]; ++i)
EDITED
编辑
Here is some additional detail:
以下是一些额外的细节:
The second line of code of the "haiku" is equivalent to the first line. The original post asks "what does this mean" in a code-comment. The second line demonstrates the answer by equivalence. *p means p[0]. The second clause in the for loop cares about whether or not p[0] is equivalent to zero.
“俳句”的第二行代码相当于第一行代码。最初的帖子在代码注释中问道“这是什么意思”。第二行用等价性证明了答案。* p p[0]。for循环中的第二个子句关心的是p[0]是否等于零。
The third line of code of the "haiku" is a line of code which can be used conceptually: You can think of the operation of the original line as behaving much like the third line ought to.
“俳句”的第三行代码是可以概念性地使用的代码:您可以认为原始行的操作与第三行应该具有的行为非常相似。
#11
2
As you can see from the picture, for
loop starts with *p
where p
points the str
. At this point *p
has S
.
如图所示,for循环从*p开始,p指向str,此时*p有S。
When continuously looping the for
, it finally reaches to str[9]
which has '\0'
which means NULL
.
当连续循环for时,它最终到达str[9],它有'\0'意思是NULL。
At this point the condition statement *p
in for (p = str; *p; p++)
is equal to NULL
so the code will break from the for
loop.
此时,条件语句*p in for (p = str;* p;p++)等于NULL,因此代码将从for循环中中断。
#12
2
That is the condition part of the loop.
If that condition is not met then the loop is not executed anymore.*p
dereferences the pointer p
and returns the character pointed at in the string str
.
The C-style string str
is terminated by the value \0
.
The loop iterates over each character (using p
) until the condition is not met.
这是循环的条件部分。如果不满足该条件,则不再执行循环。*p撤销指针p并返回字符串str中指向的字符。c风格的字符串str以值\0结束。循环遍历每个字符(使用p),直到满足条件为止。
In C a value of 0
or \0
is like the meaning offalse
, i.e. condition is not met.
Any other value is like the meaning of true
, i.e. condition is met.
在C中,0或\0的值类似于offalse的意思,即不满足条件。任何其他值都类似于true的意义,即满足条件。
In short, p
iterates over each character in str
and stops as soon as it hits the string termination character \0
.
简而言之,p遍历str中的每个字符,当它到达字符串终止字符\0时立即停止。
Why not using p
instead of *p
?
Because p
is a pointer and contains an address. It's sometimes hard or even not possible to use address arithmetic only. It's not good practice and makes code hard to read.*p
is the dereferenced pointer and contains the value that p
points to. In this case it is easy to use the values that p
points to, because you know the string is terminated by a \0
. As a condition (if
, while
, etc.) *p
is equivalent to *p != '\0'
.
为什么不用p代替*p呢?因为p是一个指针,包含一个地址。有时仅仅使用地址运算是很难的,甚至是不可能的。这并不是一个好的实践,并且使代码难以阅读。*p是dereferenced指针,包含p指向的值。在这种情况下,很容易使用p指向的值,因为您知道字符串被一个\0终止。作为条件(if, while, etc.) *p等于*p != '\0'。
#13
1
Firstly you need to grasp a concept of pointer, like name says they point to something. Pointer contains adress of variable.
首先你需要掌握指针的概念,就像名字说的指针指向某物一样。指针包含变量的附加。
int var=0;
int *p;
int p=&var;
in this code p
is a pointer and printf("%d",p);
prints adress of variable var
and printf("%d",*p);
prints value of variable var
which in this example is 0.
在这个代码中,p是一个指针和printf(“%d”,p);打印变量var和printf的adress ("%d",*p);输出变量var的值,在本例中为0。
Secondly, you must understand how arrays works.Arrays are kind of data structure that can store a fixed-size SEQUENTIAL collection of elements of the same type.
其次,您必须了解数组是如何工作的。数组是一种数据结构,可以存储相同类型的元素的固定大小的顺序集合。
int array[3]={9,8,7};
printf("%d",array[0]); //prints what is on 1st position,9
printf("%d",array[1]); //prints what is on 2nd position,8
printf("%d",array[2]); //prints what is on 3rd position,7
operator []
are just user-friendly work with arrays. Last three lines of code can be replaced with following lines(and they will do just the same):
操作符[]只是使用数组进行用户友好的工作。最后三行代码可以替换为以下几行代码(它们也会这样做):
printf("%d",*(array+0)); //prints what is on 1st position,9
printf("%d",*(array+1)); //prints what is on 2nd position,8
printf("%d",*(array+2)); //prints what is on 3rd position,7
array
is pointer to first element of array(contains adress of first element in array), so dereferencing it we get value of first element e.g. *array
. We know that arrays are seqential which means that array+1
points to second element of array,so dereferencing this you get value of second element e.g. *(array+1)
, and so on.
数组是数组中第一个元素的指针(包含数组中第一个元素的地址),因此将其取消引用,我们得到第一个元素的值,例如*数组。我们知道数组是seqential是指数组+1指向数组的第二个元素,因此取消引用就会得到第二个元素的值,例如*(数组+1)等等。
Same also aplies for strings because they are array of char, except string has '\0' (null character) at the end of strings.
字符串也是如此,因为它们是char数组,除了字符串末尾有'\0' (null字符)。
char str[128] = "Some Text";
char *p;
for (p = str; *p; p++)
{
printf("%c",*p);
}
This program prints string str
.
这个程序打印字符串str。
p = str
//assign address of first character of string str
to p
,we don't won't to lose a track of first char in string so we use p
not str
to iterate
p = str //分配字符串str的第一个字符的地址到p,我们不会丢失字符串中第一个字符的踪迹所以我们使用p not str来迭代
*p
//this expresion means *p!=0
so this is true until you arrive at the end of string,remember that '0' in ascii has integer value 48
p // /这句话的意思是*p!=0所以这是对的,直到字符串结束,记住ascii中的'0'的整数值是48
p++
//at the end of for block you add +1 to p
to obtain adress of next char
p++ //在块的末尾,您添加+1到p以获得下一个字符的地址
#14
0
It can be explained as follows :
可以这样解释:
for( initialization ; Conditional Expression ; expression3)
{
Code here will execute while 2nd Expression(Conditional Expression) is true
true means non-zero value
'\0' is equivelant to 0,so when *p equal '\0' : loop will terminate
}
#1
52
In a Boolean context such as the condition of a for
loop, each expression in C evaluates to true (non-zero) or false (zero).
在布尔上下文中,例如for循环的条件中,C中的每个表达式计算为true(非零)或false(零)。
You want the for
loop to terminate, when it reaches the end of the string.
当for循环到达字符串的末尾时,您希望它终止。
In C, each string is terminated with the character '\0'
, which is practically 0
. So, when the for
loop reaches the end of string, *p
evaluates to '\0'
, which is 0
, which evaluates to false, which terminates the for
loop.
在C语言中,每个字符串都以字符'\0'结束,这实际上是0。因此,当for循环到达字符串的末尾时,*p计算为'\0',即为0,计算结果为false,从而终止for循环。
#2
29
The for loop will terminate if whatever lies between the two ;
in the statement is zero (false). *p
dereferences p and returns the char
, p
points to. According to Dennis Ritchie "C treats strings as arrays of characters conventionally terminated by a marker". That marker is the null character with (ASCII) value of zero. So, this for loop :
如果在两者之间存在任何东西,则for循环将终止;在语句中为0 (false)。*p去引用p并返回char, p指向。根据Dennis Ritchie的说法,“C”将字符串作为一组字符的数组,这些字符通常会被标记终止。该标记是空字符,(ASCII)值为0。这个for循环
for (p = str; *p; p++)
is equivalent to these
相当于这些
for (p = str; *p != '\0'; p++)
for (p = str; *p != 0; p++)
for (p = str; p[0] != '\0'; p++)
Another name for the null terminating character is sentinel or according to Donald Knuth "dummy value" (Art of Computer Programming, Volume 1). Here is a diagram of the str
string, the indexes (offsets from the start) of each character and the values at each index :
空终止字符的另一个名称是sentinel或根据Donald Knuth“哑值”(计算机编程艺术,第1卷)。
For completeness and after a request at the comments here is what the debugger sees in the memory block that str
occupies :
为了完整性,在注释中的请求之后,调试器会看到str占用的内存块:
0x00007fffffffe6a0:
0x53 0x6f 0x6d 0x65 0x20 0x54 0x65 0x78 0x74 0x00 0x00 0x00 0x00 0x00 0x00 0x00
S o m e T e x t
- The hex value at the first line is the address (64bit) of this memory block. That's where
p
points to at the start of the for loop. - 第一行的十六进制值是这个内存块的地址(64位)。这就是p在for循环开始时的位置。
- On the 2nd line you see the hex values of the letters in your string. You can see an ASCII table here. The last char in your string is
t
with hex value of0x74
. After that you have the string's null character0x00
. Then you see a few more null characters because I built in debug mode and the compiler zero-initialized. Normally you would see garbage (seemingly random values) - 在第二行,你可以看到字符串中字母的十六进制值。您可以在这里看到一个ASCII表。字符串中的最后一个字符是t,十六进制值为0x74。在此之后,您将得到字符串的空字符0x00。然后您会看到更多的空字符,因为我在调试模式中构建,编译器为零初始化。通常你会看到垃圾(看似随机的值)
- On the 3rd line I added the chars of your string for reference
- 在第三行,我添加了字符串的字符作为参考
I understand you are on precipitous learning curve at the moment with pointers in C, but eventually you'll be able to say "I C the point"
我知道你现在正处在一个陡峭的学习曲线上用C表示指针,但最终你会说"I C the point"
#3
19
This could be rewritten like this
可以这样重写
for (p = str; *p != '\0'; p++)
{
// Code
}
In C, a string must always be terminated by a null character, which is the same as '\0' or 0
.
在C中,字符串必须总是以null字符结束,这与“\0”或0相同。
#4
13
Lets analyze it the dry but depth way!
Or as D. Ritchie would say: Let's do it with the power of assembly language and the convenience of … assembly language.
或者像D. Ritchie所说的:让我们用汇编语言的力量和汇编语言的便利来做这件事。
I'll try to explain all necessary aspects by referencing the ISO/IEC:9899 (emphasis mine)- C99 standard. (The post style is motivated by Donald Knuth's phrase "Science is what we understand well enough to explain to a computer. Art is everything else we do. ")
我将引用ISO/IEC:9899(强调我的)- C99标准来解释所有必要的方面。(这篇文章的风格是由Donald Knuth所说的“科学是我们理解的足以向计算机解释的东西”所激发的。艺术就是我们所做的一切。”)
First of all, lets inspect what exactly is the for
-loop supposed to do!
Referring to ISO/IEC:9899 6.8.5 "Iteration statements"
参照ISO/IEC: 98996.8.5“迭代语句”
Semantics
语义
4 An iteration statement causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0.
迭代语句导致一个名为循环体的语句被重复执行,直到控制表达式比较等于0。
So far nothing new I guess, so lets get it on:
到目前为止,我想没什么新鲜的,所以我们开始吧:
6.8.5.3 The for statement
6.8.5.3 for语句
1 The statement
for ( clause-1 ; expression-2 ; expression-3 ) statement
1 .声明(第1条);expression-2;expression-3)语句
behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. ...
表达式表达式表达式表达式-2是在每次执行循环体之前计算的控制表达式。
So we now know the body (in your case // Code
) will be executed as long the beforehand evaluated value of your *p
is not zero.
因此我们现在知道主体(在您的情况下//代码)将被执行,只要您的*p的预先评估值不是0。
... The expression expression-3 is evaluated as a void expression after each execution of the loop body.[...]
…表达式expression-3在每次执行循环体之后被评估为一个空表达式。
So now we know, (I assume digging up p++
's definition is not necessary?!) that for each iteration p
increments, so there may be a change in *p
.
现在我们知道,(我假设挖掘出p+的定义是不必要的?!)对于每个迭代p增量,所以*p中可能会有变化。
The following point is not related, but I'm adding it since this makes the Semantic part of for
complete and its well to know since its the reason, why for(;;)
is a inf-loop.
下面这一点没有关系,但我添加了它,因为这使for complete的语义部分很清楚,因为它是原因,为什么for(;;)是一个inf循环。
2 (---) Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.
2(--)第1条和第3条都可以省略。省略的表达式-2被一个非零常数所取代。
Ok, that's the dry but information-enriched part of what the for
loop does in your case.
好了,这就是for循环在你的例子中干的但是信息丰富的部分。
Now lets get over to pointer arithmetic:
6.5.6 Additive operators
6.5.6加法操作符
Constraints
约束
2 For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)
2对于加法,两个操作数都应该具有算术类型,或者一个操作数应该是指向对象类型的指针,另一个操作数应该具有整数类型。(递增相当于加1。)
So in your case you are adding 1 (integer) to the "pointer to an object"-type.
因此,在你的例子中,你要向“指向一个对象的指针”-type添加1(整型)。
What is equivalent to increasing the Address by the sizeof its pointed to type like shown in this picture of tomislav kostic:
就像托米斯拉夫·科斯蒂克(tomislav kostic)的这幅图中所示,通过其指向的类型的大小来增加地址,等于什么?
Now lets see what *p
actually does.
现在我们来看看*p是怎么做的。
6.5.3.2 Address and indirection operators
6.5.3.2地址和间接操作符
Constraints
约束
[...]
[…]
2 The operand of the unary * operator shall have pointer type.
一元*运算符的操作数应具有指针类型。
Semantics
语义
[...]
[…]
4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.
一元*运算符表示间接。如果操作数指向一个函数,则结果是一个函数指示器;如果它指向一个对象,则结果是一个lvalue指定对象。如果操作数类型为“指针类型”,则结果具有类型“类型”。如果一个无效的值被分配给指针,那么一元*操作符的行为是未定义的。
This is a bit dry again1 but for better understanding this can be reverse engineered by:
这又有点干涩了1,但为了更好地理解这一点,我们可以通过以下方法进行反向设计:
6.5.2.1 Array subscripting
6.5.2.1数组下标
[...]
[…]
Semantics
语义
2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).
后缀表达式后跟方括号[]中的表达式是数组对象元素的下标指定。下标运算符[]的定义是E1[E2]与(*((E1)+(E2))相同。
So *((p)+(0))
what is(since p+0
is same as p
... obvious) is equal to p[0]
, is doing nothing else as evaluating p
's object.
那么*(p)+(0)是什么(因为p+0等于p…显然的)等于p[0],它没有做任何其他的事情来计算p的对象。
And since we know, expression-2
of a for loop is interrupting the iteration if it is evaluating 0
, we can say it is the same as p[0] != 0
.
由于我们知道,for循环的表达式-2在取值为0时中断迭代,我们可以说它与p[0] != 0相同。
Now the final step
Lets just look onto the C-Coder's Friend; JSSCA... No, wait...our friend was called... ASCII Now as that's clarified, we can figure out what the 0
is representing.
让我们看看C-Coder的朋友;JSSCA……不,等等…我们的朋友叫…ASCII现在已经澄清了,我们可以算出0表示什么。
It is the NULL-token that in C is designating the end of a string.
在C中,空令牌表示字符串的结束。
So conclusive:
All, this is doing is:
所做的是:
Iterating the body of that for
-loop, until p
is actually pointing to the address, where the object evaluates to the "end of string"-token.
迭代该for循环的主体,直到p实际指向该地址,在该地址中,对象计算为“字符串的结束”—令牌。
Or:
或者:
Let p
go through the string until the end is reached.
让p穿过绳子直到到达终点。
And now just to cite my self; Something you never should forget:
(emphasis mine.....)
现在引用我的自我;你永远不应该忘记的事情:
变量是通过声明符(类型说明符)声明的,该声明符在标识符前面,标识符命名一个lvalue对象,可以对其值进行计算
It is neither more nor less!
它既不多也不少!
1That is, what I promised! ;)
那就是我答应过的!,)
#5
12
Before diving in, I would like to state a simple rule in C regarding an expression
在开始之前,我想在C中声明一个关于表达式的简单规则
When C requires the Boolean value of an expression, a
false
value is inferred when the expression compares equal to zero, and atrue
value otherwise. That is, whenever one writes当C需要一个表达式的布尔值时,当表达式比较为零时,就推断出一个假值,反之则推断出一个真值。也就是说,无论何时写作
if(expr)
where
expr
is any expression at all, the compiler essentially acts as if it had been written as当expr是任何表达式时,编译器的行为本质上就好像它是被写成的一样
if((expr) != 0)
Now coming to your question:
现在来回答你的问题:
What does the
*p
do in the following loop?在下面的循环中*p做了什么?
In C, strings are terminated by a null character '\0'
.
在C语言中,字符串以空字符'\0'结束。
Every character has a decimal equivalent. This '\0'
is an ASCII escape character. The decimal equivalent of '\0'
is 0
.
每个字符都有一个十进制的等价物。这个“\0”是一个ASCII转义字符。十进制的“\0”等于0。
So, the expression *p
in loop just check that the decimal equivalent of character at the memory address pointed by p
is either a zero or non-zero. When p
reaches the end of the string and finds the first '\0'
character, the expression *p
returns1 a zero value. A zero means false
in C. This is equivalent to testing *p != '\0'
or *p != 0
as stated above.
因此,循环中的表达式*p仅仅检查在p点的内存地址上的十进制字符是0或非0。当p到达字符串的末尾并找到第一个'\0'字符时,表达式*p returns1为零。0在c中表示为false。这相当于测试*p != '\0'或*p != 0,如上所述。
This is how it works:
这就是它的工作原理:
1 When *p
evaluates then the value of *p
is fetched from memory. This value is the value of expression *p
.
当*p求值时,从内存中获取*p的值。这个值是表达式*p的值。
#6
9
The *p Haiku
Poetically, I tried to represent the struggling of *p in the loop:
诗意地,我试图在循环中表现*p的挣扎:
Brave C *p(rogrammers)
勇敢的C * p(rogrammers)
In the loop of whilederness
在长细的循环中。
The NUL will stop them
核会阻止他们
This is an haiku poem, it consists of three lines, with the first and last line having 5 syllable, and the middle line having 7. Another example by @Samidamaru (a Master Haiku Poet, see comment below): First p equals str, Then p is incremented, Until *p is NUL.
这是一首俳句诗,由三行组成,第一行和最后一行有5个音节,中间一行有7个音节。@Samidamaru的另一个例子(一位著名的俳句诗人,见注释):首先p等于str,然后p增加,直到*p变成NUL。
A little bit of pop
Hour of Code ambassador, Jessica Alba
一小时的代码大使,杰西卡·阿尔芭
What does the *p do in the loop?
Following the imaginary advice of Jessica (who is citing D. Knuth (1)), we will try to see the meaning of *p in the for loop:
根据Jessica(引用D. Knuth(1)的假想建议,我们将在for循环中尝试理解*p的意义:
for (p = str; *p; p++)
To this goal we first examine how the unary operator "*" works in C: “The unary operator * is the indirection or deferencing operator; when applied to a pointer, it access the object the pointer points to.” (B. Kernighan and D. Ritchie (2))
为了达到这个目的,我们首先检查一元运算符“*”在C中的工作方式:“一元运算符*是间接运算符或延迟运算符;当应用到指针时,它访问指针指向的对象。(B. Kernighan和D. Ritchie (2))
So *p is simply the value pointed by p:
所以*p就是p点的值:
1.1 A closer look to the for loop
The for loop is composed of three instructions:
for循环由三条指令组成:
- p = str
- p = str
- *p
- * p
- p++
- p + +
In 1. we assign the pointer to the array str to p. In C the following assignments have the same effect:
在1。我们将指向数组str的指针赋给p。在C中,以下的赋值具有相同的效果:
p = &str[0];
p = str;
“By definition, the value of a variable or expression of type array is the address of element zero of the array” (K & R (2)). Moreover we have that “In evaluating a[i], C converts it to *(a+i) immediately. …. it follows that &a[i] and a+i are identical” (K & R (2)). If we put i = 0, we obtain the above assignments.
“根据定义,变量或类型数组表达式的值是数组的元素0的地址”(K & R(2))。此外,我们还有“在计算a[i]时,C会立即将它转换成*(a+i)。”....它遵循的是[i]和a+i是相同的”(K & R(2))。如果我们把i = 0,就得到了上面的赋值。
We can now state that, at the beginning of the for loop, p points to the first element of str.
现在我们可以声明,在for循环的开始,p指向str的第一个元素。
1.2 The core of the question
Let's move to the point 2., the core of your question. The second expression of the loop controls the exit condition: the instruction "*p" is evaluated and if is false the loop exit. This means that "*p" is equivalent to "*p != 0" or in words: when the value pointed by p is zero, exit.
我们再看点2。你的问题的核心。循环的第二个表达式控制退出条件:对指令“*p”进行计算,如果为false,则循环退出。这意味着“*p”等价于“*p != 0”,也就是说:当p的值为0时,退出。
Now, to understand when *p is zero we recall that the array str has been initialised as follows:
现在,为了理解当*p为0时,我们回想一下数组str已被初始化如下:
char str[128] = "Some Text";
and: “all string constants contain a null termination character (\0) as their last character” (gnu-manual). So the string actually stored in memory has a \0 at the end: "Some Text\0".
并且:“所有字符串常量都包含一个空终止字符(\0)作为它们的最后一个字符”(gnu-manual)。因此,实际上存储在内存中的字符串在末尾有一个\0:“Some Text\0”。
In the third instruction, p++, the pointer p is advanced to the next element of the str array, thus, at the 9-th iteration *p became 0 (or \0, NULL, NUL, see the answer from @Joe) and the loop exits.
在第三条指令中,p++,指针p被推进到str数组的下一个元素,因此,在第9次迭代*p变成0(或\0,NULL, NUL,从@Joe看到答案)和循环退出。
1.3 See to believe
A picture is worth a thousand words, here is a graphical representation of the loop:
一幅画胜过千言万语,这是循环的图形表示:
1.4 A further example: the same usage of *p in a different example
In the following snippet *p is used the same way but in a while loop:
在下面的代码片段*p中使用相同的方法,但在while循环中:
#include <stdio.h>
int main() {
char str[128] = "We all scream for ice cream!";
char *p = str;
// here we see again the loop exit condition *p == '\0'
while(*p) {
printf("%c", *p);
p++;
}
printf("\n");
}
May the for(;*C;)e be with you!
References
引用
(1) Vol. I, Fundamental Algorithms, Section 1.1 (1968)
(1)Vol. I,基本算法,Section 1.1 (1968)
(2) The C Programming Language Pg 94-99
(2)C编程语言Pg 94-99。
#7
4
A long time ago, in a PDP far, far away, resources were scarce, names got short: i
for index, p
for pointer would please early Jedi programmers.
很久以前,在一个遥远的PDP中,资源是稀缺的,名字是短的:i代表索引,p代表指针,这将取悦早期的绝地程序员。
Implicit tests told the truth in for
condition space. A single *
was all they typed, trusting p
and pushing it to the end of strings.
隐式测试在条件空间中告诉了真相。他们输入的只有一个*,信任p并把它推到字符串的末尾。
To this day, they use the for(e = s;*e;e++)
most familiar and elegant loop to defy the C++ empire and its cohorts of ctors, dtors and vile iterators. Bare bits and bytes against templates, exceptions and obscure types, only the brave still dare for C to fight, and uncast the void *
.
直到今天,他们仍在使用最为熟悉和优雅的for循环来对抗c++帝国以及它的ctors、dtors和卑鄙的迭代者。对模板、异常和模糊类型进行裸比特和字节,只有勇敢的C才敢战斗,并释放出空虚*。
#8
4
It takes advantage of the fact that the terminator to the string (eventually found by that for loop) will be an ASCII NUL
, which is a zero, which also happens to evaluate to false, thus terminating the for loop.
它利用了这样一个事实:字符串的终止符(最终由for循环找到)将是一个ASCII NUL,它是一个0,它也恰好计算为false,从而终止for循环。
It's worth noting the difference and similarity between 0, false, NULL and ASCII NUL. See this question: What is the difference between NULL, '\0' and 0
值得注意的是0、false、NULL和ASCII NUL之间的差异和相似之处。看看这个问题:NULL, '\0'和0之间的区别是什么
#9
4
I have tried to satisfy the bounty awarder's desires which were mentioned at various times. To keep it simple I have restricted my answer to three sections of three lines each, and because (as The Bellman said in his Rule Of Three) "What I tell you three times is true" (the theme of this answer).
我试着去满足那些在不同时期被提及的赏金者的欲望。为了简单起见,我把答案限制在每行三段,因为(正如行李员在他的三行规则中所说的)“我告诉你的三次都是真的”(这个答案的主题)。
Technical
技术
The truth of your for
loop terminates it when the expression *p
evaluates to 0
and this evaluation is performed before every iteration of the loop, note that in C 0
is false and anything else is true - that's a very expansive definition in other worlds!
当表达式*p的值为0,并且在循环的每次迭代之前执行这个评估时,你的for循环的真相就会终止,请注意,在c0中是错误的,其他的都是正确的——在其他的世界中这是一个非常广泛的定义!
The pointer variable p
is initialised once, to point to the start of the array with p = str
, and p
is incremented at the end of every iteration, so *p
is accessing successive elements of the array in each iteration.
指针变量p被初始化一次,指向带有p = str的数组的开始,并且p在每次迭代结束时都是递增的,所以*p在每次迭代中访问数组的连续元素。
The expression *p
will thus evaluate to 0
(false) when the array element read by *p
is the 0
or '\0'
terminator that signals the end of a C "string", but you can't see this zero in the initialisation of str
because it is supplied by the compiler automatically.
因此,当*p读取的数组元素是表示C“字符串”结束的0或'\0'终止符时,表达式*p将计算为0 (false),但在str的初始化中看不到这个0,因为编译器自动提供它。
Lyrical
抒情
Expressions of truth
真理的表达式
Are not understood by youth
青春不懂吗?
Read Ritchie and Knuth
阅读里奇和Knuth
Whimsical
反复无常的
Jessica Alba is a fine actress who is very knowledgeable, having taken on board truths from observing the development of computer technology, as these quotes reveal:
杰西卡·阿尔芭(Jessica Alba)是一位非常博学的女演员,她从观察计算机技术的发展中获得了一些真理,正如这些名言所揭示的:
"Every five years I feel like I'm a completely different person."
“每隔五年,我就会觉得自己完全变了一个人。”
"It's all about your product and how it performs. Either it works, or it doesn't."
这都是关于你的产品和它的表现。要么成功,要么失败。
#10
3
A haiku:
俳句:
WHY for (p=str; *p; p++)
IS for (p=str; p[0] != 0; p++)
THINK for (i=0; str[i]; ++i)
EDITED
编辑
Here is some additional detail:
以下是一些额外的细节:
The second line of code of the "haiku" is equivalent to the first line. The original post asks "what does this mean" in a code-comment. The second line demonstrates the answer by equivalence. *p means p[0]. The second clause in the for loop cares about whether or not p[0] is equivalent to zero.
“俳句”的第二行代码相当于第一行代码。最初的帖子在代码注释中问道“这是什么意思”。第二行用等价性证明了答案。* p p[0]。for循环中的第二个子句关心的是p[0]是否等于零。
The third line of code of the "haiku" is a line of code which can be used conceptually: You can think of the operation of the original line as behaving much like the third line ought to.
“俳句”的第三行代码是可以概念性地使用的代码:您可以认为原始行的操作与第三行应该具有的行为非常相似。
#11
2
As you can see from the picture, for
loop starts with *p
where p
points the str
. At this point *p
has S
.
如图所示,for循环从*p开始,p指向str,此时*p有S。
When continuously looping the for
, it finally reaches to str[9]
which has '\0'
which means NULL
.
当连续循环for时,它最终到达str[9],它有'\0'意思是NULL。
At this point the condition statement *p
in for (p = str; *p; p++)
is equal to NULL
so the code will break from the for
loop.
此时,条件语句*p in for (p = str;* p;p++)等于NULL,因此代码将从for循环中中断。
#12
2
That is the condition part of the loop.
If that condition is not met then the loop is not executed anymore.*p
dereferences the pointer p
and returns the character pointed at in the string str
.
The C-style string str
is terminated by the value \0
.
The loop iterates over each character (using p
) until the condition is not met.
这是循环的条件部分。如果不满足该条件,则不再执行循环。*p撤销指针p并返回字符串str中指向的字符。c风格的字符串str以值\0结束。循环遍历每个字符(使用p),直到满足条件为止。
In C a value of 0
or \0
is like the meaning offalse
, i.e. condition is not met.
Any other value is like the meaning of true
, i.e. condition is met.
在C中,0或\0的值类似于offalse的意思,即不满足条件。任何其他值都类似于true的意义,即满足条件。
In short, p
iterates over each character in str
and stops as soon as it hits the string termination character \0
.
简而言之,p遍历str中的每个字符,当它到达字符串终止字符\0时立即停止。
Why not using p
instead of *p
?
Because p
is a pointer and contains an address. It's sometimes hard or even not possible to use address arithmetic only. It's not good practice and makes code hard to read.*p
is the dereferenced pointer and contains the value that p
points to. In this case it is easy to use the values that p
points to, because you know the string is terminated by a \0
. As a condition (if
, while
, etc.) *p
is equivalent to *p != '\0'
.
为什么不用p代替*p呢?因为p是一个指针,包含一个地址。有时仅仅使用地址运算是很难的,甚至是不可能的。这并不是一个好的实践,并且使代码难以阅读。*p是dereferenced指针,包含p指向的值。在这种情况下,很容易使用p指向的值,因为您知道字符串被一个\0终止。作为条件(if, while, etc.) *p等于*p != '\0'。
#13
1
Firstly you need to grasp a concept of pointer, like name says they point to something. Pointer contains adress of variable.
首先你需要掌握指针的概念,就像名字说的指针指向某物一样。指针包含变量的附加。
int var=0;
int *p;
int p=&var;
in this code p
is a pointer and printf("%d",p);
prints adress of variable var
and printf("%d",*p);
prints value of variable var
which in this example is 0.
在这个代码中,p是一个指针和printf(“%d”,p);打印变量var和printf的adress ("%d",*p);输出变量var的值,在本例中为0。
Secondly, you must understand how arrays works.Arrays are kind of data structure that can store a fixed-size SEQUENTIAL collection of elements of the same type.
其次,您必须了解数组是如何工作的。数组是一种数据结构,可以存储相同类型的元素的固定大小的顺序集合。
int array[3]={9,8,7};
printf("%d",array[0]); //prints what is on 1st position,9
printf("%d",array[1]); //prints what is on 2nd position,8
printf("%d",array[2]); //prints what is on 3rd position,7
operator []
are just user-friendly work with arrays. Last three lines of code can be replaced with following lines(and they will do just the same):
操作符[]只是使用数组进行用户友好的工作。最后三行代码可以替换为以下几行代码(它们也会这样做):
printf("%d",*(array+0)); //prints what is on 1st position,9
printf("%d",*(array+1)); //prints what is on 2nd position,8
printf("%d",*(array+2)); //prints what is on 3rd position,7
array
is pointer to first element of array(contains adress of first element in array), so dereferencing it we get value of first element e.g. *array
. We know that arrays are seqential which means that array+1
points to second element of array,so dereferencing this you get value of second element e.g. *(array+1)
, and so on.
数组是数组中第一个元素的指针(包含数组中第一个元素的地址),因此将其取消引用,我们得到第一个元素的值,例如*数组。我们知道数组是seqential是指数组+1指向数组的第二个元素,因此取消引用就会得到第二个元素的值,例如*(数组+1)等等。
Same also aplies for strings because they are array of char, except string has '\0' (null character) at the end of strings.
字符串也是如此,因为它们是char数组,除了字符串末尾有'\0' (null字符)。
char str[128] = "Some Text";
char *p;
for (p = str; *p; p++)
{
printf("%c",*p);
}
This program prints string str
.
这个程序打印字符串str。
p = str
//assign address of first character of string str
to p
,we don't won't to lose a track of first char in string so we use p
not str
to iterate
p = str //分配字符串str的第一个字符的地址到p,我们不会丢失字符串中第一个字符的踪迹所以我们使用p not str来迭代
*p
//this expresion means *p!=0
so this is true until you arrive at the end of string,remember that '0' in ascii has integer value 48
p // /这句话的意思是*p!=0所以这是对的,直到字符串结束,记住ascii中的'0'的整数值是48
p++
//at the end of for block you add +1 to p
to obtain adress of next char
p++ //在块的末尾,您添加+1到p以获得下一个字符的地址
#14
0
It can be explained as follows :
可以这样解释:
for( initialization ; Conditional Expression ; expression3)
{
Code here will execute while 2nd Expression(Conditional Expression) is true
true means non-zero value
'\0' is equivelant to 0,so when *p equal '\0' : loop will terminate
}