C语言中的Operator
问题:
#include <stdio.h>
int main()
{
int i = 3;
printf("%d", (++i)++);
return 0;
}
答案:Compile-time error
解释:
在c语言中,前缀和后缀操作符需要对左值进行操作,并返回右值,表达式(++i)++ 在执行过程中,首先增加 i 的值(i是左值),然后返回右值(++i),然后编译器产生错误,因为后缀表达式需要对一个左值进行操作。
问题:
#include "stdio.h"
int main()
{
int x, y = 5, z = 5;
x = y == z;
printf("%d", x);
getchar();
return 0;
}
答案:1
解释:
== 的优先级高于 =,故先执行 y==z,然后将结果赋值给 x
问题:
#include <stdio.h>
int main()
{
int i = 1, 2, 3;
printf("%d", i);
return 0;
}
答案:Compile time error
解释:
逗号在这里用作分隔符,编译器首先创建了一个变量并初始化为1,然后编译器在创建第二个变量时会报错,因为2并不是有效的标识符。
另一个类似问题:
#include <stdio.h>
int main()
{
int i;
i = 1, 2, 3;
printf("%d", i);
return 0;
}
答案:1
解释:
在这里逗号作为操作符,由于复制操作符有更高的优先级,所以表达式可以看做 (i = 1), 2, 3,编译器将1赋值给变量 i。
问题:
#include <stdio.h>
int main()
{
int i = (1, 2, 3);
printf("%d", i);
return 0;
}
答案:3
解释:
括号的优先级比赋值操作符的优先级高,所以括号内的表达式依次从左至右执行,结果是最后的一次赋值。
问题:
#include <stdio.h>
int main()
{
/*Assume size of an integer as 4 bytes.*/
int i = 5, j = 10, k = 15;
printf("%d ", sizeof(k /= i + j));
printf("%d", k);
return 0;
}
答案:4 15
解释:
这个程序的关键在于 sizeof(k /= i + j). 在 sizeof() 操作符内的表达式不会被求值,故 k 的值保持不变。且 sizeof 返回整型。
问题:
#include <stdio.h>
int main()
{
//Assume sizeof character is 1 byte and sizeof integer is 4 bytes
printf("%d", sizeof(printf("GeeksQuiz")));
return 0;
}
答案:4
解释:
首先 sizeof 内部的表达式不会被执行,故不会打印 GeeksQuiz,printf 返回成功打印的字符数 9,9 是整型,故 sizeof 操作符返回 sizeof(int)。
问题:
#include <stdio.h>
int f1() { printf ("Geeks"); return 1;}
int f2() { printf ("Quiz"); return 1;}
int main()
{
int p = f1() + f2();
return 0;
}
答案:Compiler Dependent
解释:
操作符’+’并没有标准的执行顺序,f1() 或 f2() 都有可能先执行,所以编译器可能会输出 “GeeksQuiz”或“QuizGeeks”.
问题:
#include<stdio.h>
int main()
{
char *s[] = { "knowledge","is","power"};
char **p;
p = s;
printf("%s ", ++*p);
printf("%s ", *p++);
printf("%s ", ++*p);
return 0;
}
答案:nowledge nowledge s
解释:
p 是指向指针的指针,s 是元素为 char 型指针的数组,* p 获得指向knowledge 的指针,给
p 加 1,指针指向 knowledge 的第二个字符,即 n,因此,第一个 printf 打印 nowledge。第二个printf 中,因为 ++ 的优先级高于
,所以 p++ 先求值,p 指向数组的第二个元素,但 p++ 仍然是旧的值,故仍然打印 nowledge,在第三个 printf 中,p的新值(被第二个 printf 更新的)被使用,故打印 s。
一些复杂的指针声明总结:
char *ptr[3]; //An array of three pointers to chars char (*ptr)[3]; //A pointer to an array of three chars int (*pf)(); //pf is a pointer to a function which return int float *(*ptr)(int*) //A pointer to a function which receives an int pointer and returns float pointer void *cmp(); //cmp is a function that return a void pointer. void (*ptr)() //A pointer to a function which receives nothing and returns nothing int *f(); //f is a function returning pointer to an int.
问题:
#include<stdio.h>
int main(void)
{
int a = 1;
int b = 0;
b = a++ + a++;
printf("%d %d",a,b);
return 0;
}
答案:Compiler Dependent
解释:
程序的输出是未定义的,取决于具体的编译器。字表达式 i++会产生副作用,它修改 i 的值,由于 i 在其他地方被引用,导致未定义的行为。
Unlike above cases, at certain specified points in the execution sequence called sequence points, all side effects of previous evaluations are guaranteed to be complete. A sequence point defines any point in a computer program’s execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed. Following are the sequence points listed in the C standard:
— The end of the first operand of the following operators:
a) logical AND &&
b) logical OR ||
c) conditional ?
d) comma ,
详见:
Sequence point
问题:
#include <stdio.h>
#define VAL 32
int main()
{
char arr[] = "geeksquiz";
*(arr + 0) &= ~VAL;
*(arr + 5) &= ~VAL;
printf("%s", arr);
return 0;
}
答案:GeeksQuiz
解释:
(arr + 5) &= ~VAL 表示从 第五个字符的 ascii 码减去 32,即将相应字符转换为大写。
(arr + 0) &= ~VAL 同理。
问题:
#include <stdio.h>
int main()
{
printf("%d", 1 << 2 + 3 << 4);
return 0;
}
答案:512
解释:
+的优先级高于 <<,即 1 << (2 + 3) << 4
问题:
#include <stdio.h>
int main()
{
int i = 0;
do
{
printf("GeeqsQuiz ");
i = i++;
}
while (i < 5);
return 0;
}
答案:Undefined Behavior
解释:
i=i++ 会造成未定义的行为。详见:
Sequence point
问题:
#include<stdio.h>
int main()
{
int a = 2,b = 5;
a = a^b;
b = b^a;
printf("%d %d",a,b);
return 0;
}
答案:7 2
解释:
关于位操作中的按位异或操作符:直接相加,并且将进位丢弃。
The bitwise XOR (exclusive or) performs a logical XOR function, which is equivalent to adding two bits and discarding the carry.
bit a | bit b | a ^ b (a XOR b) |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
问题:
#include <stdio.h>
int main()
{
int x = 10;
int y = (x++, x++, x++);
printf("%d %d\n", x, y);
return 0;
}
答案:13 12
解释:
逗号在这里定义了一个 sequence point,所有的表达式按照从左到右的顺序依次执行。
问题:
#include <stdio.h>
int main()
{
int y = 0;
int x = (~y == 1);
printf("%d", x);
return 0;
}
答案:0
解释:
~ 是按位“取非”运算符,~ 运算符查看表达式的二进制表示形式的值,并执行按位求非运算。
表达式中的任何一位为 1,则结果中的该位变为 0。 表达式中的任何一位为 0,则结果中的该位变为 1。
当 ~ 运算符充当整型数据类型的操作数时,它不进行强制并返回与操作数具有相同数据类型的值。 当操作数是非整型数据类型时,该值在运算执行之前被强制为 int 类型,该运算符的返回值为 int 类型。
下面的示例阐释了按位 NOT (~) 运算符的用法。
var temp = ~5;
表达式 | 二进制 | 十进制 |
---|---|---|
5 | 00000000 00000000 00000000 00000101 | -5 |
~5 | 11111111 11111111 11111111 11111010 | -6 |
问题:
#include <stdio.h>
#include <stdlib.h>
int top=0;
int fun1()
{
char a[]= {'a','b','c','(','d'};
return a[top++];
}
int main()
{
char b[10];
char ch2;
int i = 0;
while (ch2 = fun1() != '(')
{
b[i++] = ch2;
}
printf("%s",b);
return 0;
}
答案:3 special characters with ASCII value 1
解释:
!= 的优先级高于 =,所以表达式 “ch2 = fun1() != ‘(‘” 等价于 “ch2 = (fun1() != ‘(’ )”.
问题:
以下代码是否正确
a>b ? : ;
a>b ? c=10 : d=10;
答案:错误
解释:
三元操作符第二第三个参数不能为空,1错,且三元操作符的优先级高于赋值操作符,2错
其他:
操作符优先级表:
优先级排序:函数操作符>一元操作符>二元操作符(算数运算>关系运算>位运算>逻辑运算)>三元操作符>赋值操作符