在C语言(以及大多数编程语言)中,并不是所有的表达式都有结果或返回值,但它们在语法和逻辑上通常都设计为能够产生某种效果或值。然而,要准确回答这个问题,我们需要区分不同类型的表达式。
有结果的表达式
-
算术表达式(如
1 + 2
)、关系表达式(如a > b
)、逻辑表达式(如x && y
)、赋值表达式(如a = b
)等通常都有明确的结果或返回值。这些结果可以是数值(对于算术和赋值表达式)、布尔值(对于关系和逻辑表达式)等。 -
函数调用(如果函数被设计为返回某个值)也是一个有结果的表达式。
没有直接结果的表达式
-
语句(如
if
语句、for
循环等)本身不是表达式,它们不产生返回值。但是,它们可以包含表达式作为其子部分。 -
某些函数调用(如果函数被设计为不返回任何值,即返回类型为
void
)也不产生直接的结果或返回值。 -
表达式语句(如
a++;
)虽然包含表达式(在这个例子中是后缀递增表达式),但整个语句本身并不产生可用于其他表达式的结果。然而,表达式本身(在这个例子中是a++
)确实有一个结果,即递增前的a
的值,但这个值通常不会被直接使用(除非在更复杂的表达式中,如(a++) + 1
)。 -
逗号运算符(
,
)是一个特殊的运算符,它用于分隔两个表达式,并返回第二个表达式的值。虽然这看起来像是两个表达式都有“结果”,但逗号运算符表达式的结果实际上是第二个表达式的值。
总结
在C语言中,大多数表达式都有结果或返回值,但这些结果或返回值的用途和类型可能因表达式的类型而异。然而,并不是所有的语法结构都是表达式,也不是所有的表达式都被设计为产生可用于其他表达式的直接结果。
*dest++=*src++,表达式的结果就是字符,而字符又通过ascll码表转化为对应的数字,'\0'对应的值是0,所以循环结束。
a=b+3,这个表达式的结果就是8,8再赋值给c.
int main()
{
int a = 10;
int b = 30;
int const* p = &a;
p = &b;
//*p = 20;//即使是换了地址也不行,只要是const* p,*p就不能用
return 0;
}
*arr++=0中,是先解引用,还是先++?
在C或C++等语言中,表达式 *arr++ = 0;
涉及解引用(dereference)和自增(increment)两个操作,但这些操作的顺序是由语言的定义和上下文决定的,特别是在表达式评估时。
对于这个特定的表达式 *arr++ = 0;
,它首先是一个后缀自增表达式(postfix increment expression),这意味着自增操作(++
)会在整个表达式的其余部分(这里是解引用赋值)被评估之后才执行。然而,重要的是要理解这个表达式的行为如何分解为两个主要步骤,尽管这些步骤在逻辑上分开,但在实际执行时,编译器和处理器会尽量优化以提高效率。
-
解引用赋值:首先,
*arr
是对指针arr
所指向位置的解引用,即获取该位置的值。然后,这个值被赋值为0
。但是,重要的是要注意,这里的arr
在赋值时还没有因为自增而改变,所以赋值是针对arr
当前指向的位置进行的。 -
自增:在解引用赋值完成后,
arr
指针自身会增加其类型的大小(对于大多数指针来说,这是机器字长,如 4 字节或 8 字节,取决于平台)。这个自增操作是在整个表达式*arr++ = 0;
评估完成后才发生的,并且这个自增只影响arr
的值,不影响已经完成的赋值操作。
因此,虽然这两个操作在逻辑上看起来像是同时发生的,但实际上它们是有序的:先解引用赋值,后自增。
这种顺序在处理指针和数组时尤其重要,因为它决定了哪个内存位置被修改以及指针本身在表达式评估后指向哪里。在编写涉及指针和自增的复杂表达式时,了解这些操作的顺序和它们对程序状态的影响是非常重要的。
综上所述,*arr++是arr增加,而不是*arr增加
---------------------------------------------------------------------------------------------------------------------------------
int main()
{
int a = 10;
int* p = &a;
*p++;//a并没有变为11,这说明了,当*这个操作符使用完后,才到++,而不是解引用的同时,进行++操作,这也证明了,操作符是有顺序的
printf("%d\n", a);
return 0;
}
如果想看strlen的源码,直接在文件夹里搜strlen.c