分配运算符

将右侧操作数的值分配给左侧操作数指定的存储位置,并返回该值。

int x = 5;      /* Variable x holds the value 5. Returns 5. */ 
char y = 'c';   /* Variable y holds the value 99. Returns 99 
                 * (as the character 'c' is represented in the ASCII table with 99).
                 */
float z = 1.5;  /* variable z holds the value 1.5. Returns 1.5. */
char const* s = "foo"; /* Variable s holds the address of the first character of the string 'foo'. */

一些算术运算具有复合赋值运算符。

a += b  /* equal to: a = a + b */
a -= b  /* equal to: a = a - b */
a *= b  /* equal to: a = a * b */
a /= b  /* equal to: a = a / b */
a %= b  /* equal to: a = a % b */
a &= b  /* equal to: a = a & b */
a |= b  /* equal to: a = a | b */
a ^= b  /* equal to: a = a ^ b */
a <<= b /* equal to: a = a << b */
a >>= b /* equal to: a = a >> b */

这些复合赋值的一个重要特征是左侧的表达式(a)仅评估一次。例如,如果 p 是一个指针

*p += 27;

仅引用一次 p,而以下两次。

*p = *p + 27;

还应注意,诸如 a = b 之类的赋值的结果是所谓的右值。因此,赋值实际上具有一个值,然后可以将该值赋给另一个变量。这允许分配链接在单个语句中设置多个变量。

这个右值可以用在 if 语句(或循环或 switch 语句)的控制表达式中,这些语句保护一些代码对另一个表达式或函数调用的结果。例如:

char *buffer;
if ((buffer = malloc(1024)) != NULL)
{
    /* do something with buffer */
    free(buffer);
}
else
{
    /* report allocation failure */
}

因此,必须注意避免可能导致神秘错误的常见错字。

int a = 2;
/* ... */
if (a = 1)
    /* Delete all files on my hard drive */

这将带来灾难性的结果,因为 a = 1 将始终评估为 1,因此 if 语句的控制表达式将始终为真(请阅读更多有关此常见陷阱的信息 )。作者几乎肯定打算使用等于运算符(==),如下所示:

int a = 2;
/* ... */
if (a == 1)
    /* Delete all files on my hard drive */

运算符相关性

int a, b = 1, c = 2;
a = b = c;

这将 c 分配给 bb 将返回 b,而 b 将分配给 a。发生这种情况是因为所有赋值运算符都具有正确的关联性,这意味着首先计算表达式中最右边的操作,然后从右向左进行。