读朱兆祺攻破C语言之五---关键字、运算符、语句
2013-12-05 16:29
211 查看
下面文章来自朱兆祺编写的《攻破c语言笔试和机试难点》的pdf,为我们详尽讲解了C语言细节和难点问题。在此感谢这位牛人。
1.1
1. 如程序清单4. 1所示,请问输出i、j的结果?
程序清单4.
1 static
很多人傻了,为什么呢?是啊,为什么呢?!
由于被static修饰的变量总存在内存静态区,所以运行这个函数结束,这个静态变量的值也不会被销毁,函数下次使用的时候仍然能使用这个值。
有人就问啊,为什么j一直是1啊。因为每次调用fun2()这个函数,j都被强行置0了。
static的作用:
(1) 函数体内
static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次, 因此其值在下次调用时仍维持上次的值;(所以fun1中static
int i = 0 ;只执行一次。)
(2) 在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3) 在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明 它的模块内;
(4) 在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;(个人未理解)
(5) 在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。(个人未理解)
1.2
1. 如程序清单4.
2所示,输出结果是什么?
程序清单4. 2 for循环
#include <stdio.h>
这个题目主要考察对for循环的理解。我们先来看看运行程序会输出什么?
First = 0 Second = 0 Fourth = 0
Third = 1 Second = 1 Fourth = 1
Third = 2 Second = 2 Fourth = 2
从输出我们就可以知道程序到底是什么运行:
首先i = 0 , 所以输出:First = 0 ; 接着输出:Second = 0 ; i < 10 成立,则输出:Fourth = 0 。就此完成第一个循环。接着 i ++ , 此时i = 1 ,输出:Third = 1 ;接着输出:Second = 1 ;i < 10 成立,则输出:Fourth = 1 ······以此类推。
1.3
1. 如程序清单4. 3所示,sizeof(a),sizeof(b)分别是多少?
程序清单4. 3 sizeof
#include <stdio.h>
int main(int argc, char *argv[])
{
char a[2][3] ;
short b[2][3] ;
printf( "sizeof(a) = %d \n" , sizeof( a ) ) ;
printf( "sizeof(b) = %d \n" , sizeof( b ) ) ;
return 0;
}
这个题目比较简单,由于char 是1个字节、short是2个字节,所以本题答案是:
sizeof(a) = 6
sizeof(b) = 12
好的,再来看看如程序清单4. 4所示,sizeof(a),sizeof(b)分别是多少?
程序清单4.
4 sizeof
#include <stdio.h>
int main(int argc, char *argv[])
{
char *a[2][3] ;
short *b[2][3] ;
printf( "sizeof(a) = %d \n" , sizeof( a ) ) ;
printf( "sizeof(b) = %d \n" , sizeof( b ) ) ;
return 0;
}
是数组指针呢,还是指针数组呢?这里涉及*和[]和优先级的问题。我告诉大家的是这两个数组存放的都是指针变量,至于为什么,在后续章节会详细解释,然而指针变量所占的字节数为4字节,所以答案如下。
[align=left]验证结果如下:(使用TC然间验证输出结果是sizeof(a)=12,sizeof(b)=12)即指针变量在TC占2字节),下面使用ubuntu中GCC验证[/align]
1.4
1. 或许大家都知道,++i是先执行i自加再赋值,但是i++是先赋值再自加,但是还有隐藏在后面的东西呢?
int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (++i) + (++i) ;
C-Free编译输出是:7,有的编译器输出是:9。这两个答案都是对的,编译器不同所不同。7
= 2+2+3;9=3+3+3。区别在于答案是7的先执行(++i)+(++i)再执行+(++i),但是答案是9的是一起执行。
这只是前奏,先看几个让你目瞪口呆的例子。编译环境是VS2010。
int i = 0 ;
int iNumber = 0 ;
iNumber = (i++) + (++i) + (++i) ;
printf( "iNumber = %d \n" , iNumber ) ;
这里输出是:4!!!4 = 1+1+2。
int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (i++) + (++i) ;
printf( "iNumber = %d \n" , iNumber ) ;
这里输出是:4!!!4=1+1+2。
int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (++i) + (i++) ;
printf( "iNumber = %d \n" , iNumber ) ;
这里输出是:6!!!6=2+2+2。
这里至少能说明两个问题,其一,先执行前面两个,再执行第三个;其二,(i++)这个i的自加是最后执行!
1.5
1.
如程序清单4. 6所示,请问输出会是什么?
程序清单4.
6 scanf()函数的返回值
int a , b ;
printf( "%d \n" ,
scanf("%d%d" , &a , &b) ) ;
输出输入这个函数的返回值?!答案是:2。只要你合法输入,不管你输入什么,输出都是2。那么我们就要深入解析scanf这个函数。scanf()的返回值是成功赋值的变量数量。
1.6
1. 阅读如程序清单4.
7所示,想想会输出什么?为什么?
程序清单4.
7 const作用下的变量
在TC和GCC测试的答案一致,都是:50,100 而并不是10,100。即const关键字未起作用。
具体原因待查,分析可能是编译器问题。
这里补充一个知识点:(自己未验证)
const int *p 指针变量p可变,而p指向的数据元素不能变
int* const p 指针变量p不可变,而p指向的数据元素可变
const int* const p 指针变量p不可变,而p指向的数据元素亦不能变
1.7
1. 如程序清单4.
8所示程序,输出什么?
程序清单4. 8 *ptr++
int ia[3]={1,11,22};
int *ptr = ia;
printf("*ptr++=%d\n",*ptr++);
printf("*ptr=%d\n",*ptr);
纠结啊,是先算*ptr还是ptr++;还是纠结啊,ptr是地址加1还是偏移一个数组元素!
这里考查了两个知识点,
其一:*与++的优先级问题;
其二,数组i++和++i的问题。
*和++都是优先级为2,且都是单目运算符,自右向左结合。所以这里的*ptr++和*(ptr++)是等效的。
首先ptr是数组首元素的地址,所以ptr++是偏移一个数组元素的地址。那么ptr++运算完成之后,此时的ptr是指向ia[1],所以第二个输出*ptr = 11 。如图4. 1所示。那么倒回来看第一个输出,ptr++是在执行完成*ptr++之后再执行的,所以,*ptr++
= 1 。
如程序清单4. 9所示程序,输出会是什么?
程序清单4. 9 *++ptr
int ia[3] = { 1 , 11 , 22} ;
int *ptr = ia;
printf( "*++ptr = %d \n" ,
*++ptr ) ;
printf( "*ptr = %d \n" ,
*ptr ) ;
这个解释和上面解释差不多,就是++ptr和ptr++的差别,所以这里的两个输出都是:11。同样的道理,*++ptr和*(++ptr)是等效。
再如程序清单4. 10所示,输出又会是什么?
程序清单4. 10 (*ptr)++
int ia[3] = { 1 , 11 , 22} ;
int *ptr = ia ;
printf( "(*ptr)++ = %d \n" ,
(*ptr)++ ) ;
printf( "*ptr = %d \n" ,
*ptr ) ;
这个的输出是:1,2。
验证结果如下图:
1.1
static
1. 如程序清单4. 1所示,请问输出i、j的结果?程序清单4.
1 static
#include <stdio.h> static int j ; void fun1(void) { static int i = 0 ; i++ ; printf("i = %d " , i ); } void fun2(void) { j = 0 ; j++ ; printf("j = %d \n" , j ); } int main(int argc, char *argv[]) { int k = 0 ; for( k = 0 ; k < 5 ; k++ ){ fun1() ; fun2() ; printf("\n"); } return 0; }
很多人傻了,为什么呢?是啊,为什么呢?!
由于被static修饰的变量总存在内存静态区,所以运行这个函数结束,这个静态变量的值也不会被销毁,函数下次使用的时候仍然能使用这个值。
有人就问啊,为什么j一直是1啊。因为每次调用fun2()这个函数,j都被强行置0了。
static的作用:
(1) 函数体内
static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次, 因此其值在下次调用时仍维持上次的值;(所以fun1中static
int i = 0 ;只执行一次。)
(2) 在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3) 在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明 它的模块内;
(4) 在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;(个人未理解)
(5) 在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。(个人未理解)
1.2
for循环的深究
1. 如程序清单4.2所示,输出结果是什么?
程序清单4. 2 for循环
#include <stdio.h>
int main(int argc, char *argv[]) { int i = 0 ; for( i = 0 ,printf("First = %d " , i ) ; printf("Second = %d " , i ) , i < 10 ; i++ , printf("Third = %d " , i )) { printf("Fourth = %d \n" , i) ; } return 0; }
这个题目主要考察对for循环的理解。我们先来看看运行程序会输出什么?
First = 0 Second = 0 Fourth = 0
Third = 1 Second = 1 Fourth = 1
Third = 2 Second = 2 Fourth = 2
从输出我们就可以知道程序到底是什么运行:
首先i = 0 , 所以输出:First = 0 ; 接着输出:Second = 0 ; i < 10 成立,则输出:Fourth = 0 。就此完成第一个循环。接着 i ++ , 此时i = 1 ,输出:Third = 1 ;接着输出:Second = 1 ;i < 10 成立,则输出:Fourth = 1 ······以此类推。
1.3
尺子——sizeof
1. 如程序清单4. 3所示,sizeof(a),sizeof(b)分别是多少?程序清单4. 3 sizeof
#include <stdio.h>
int main(int argc, char *argv[])
{
char a[2][3] ;
short b[2][3] ;
printf( "sizeof(a) = %d \n" , sizeof( a ) ) ;
printf( "sizeof(b) = %d \n" , sizeof( b ) ) ;
return 0;
}
这个题目比较简单,由于char 是1个字节、short是2个字节,所以本题答案是:
sizeof(a) = 6
sizeof(b) = 12
好的,再来看看如程序清单4. 4所示,sizeof(a),sizeof(b)分别是多少?
程序清单4.
4 sizeof
#include <stdio.h>
int main(int argc, char *argv[])
{
char *a[2][3] ;
short *b[2][3] ;
printf( "sizeof(a) = %d \n" , sizeof( a ) ) ;
printf( "sizeof(b) = %d \n" , sizeof( b ) ) ;
return 0;
}
是数组指针呢,还是指针数组呢?这里涉及*和[]和优先级的问题。我告诉大家的是这两个数组存放的都是指针变量,至于为什么,在后续章节会详细解释,然而指针变量所占的字节数为4字节,所以答案如下。
[align=left]验证结果如下:(使用TC然间验证输出结果是sizeof(a)=12,sizeof(b)=12)即指针变量在TC占2字节),下面使用ubuntu中GCC验证[/align]
1.4
++i和i++
1. 或许大家都知道,++i是先执行i自加再赋值,但是i++是先赋值再自加,但是还有隐藏在后面的东西呢?int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (++i) + (++i) ;
C-Free编译输出是:7,有的编译器输出是:9。这两个答案都是对的,编译器不同所不同。7
= 2+2+3;9=3+3+3。区别在于答案是7的先执行(++i)+(++i)再执行+(++i),但是答案是9的是一起执行。
这只是前奏,先看几个让你目瞪口呆的例子。编译环境是VS2010。
int i = 0 ;
int iNumber = 0 ;
iNumber = (i++) + (++i) + (++i) ;
printf( "iNumber = %d \n" , iNumber ) ;
这里输出是:4!!!4 = 1+1+2。
int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (i++) + (++i) ;
printf( "iNumber = %d \n" , iNumber ) ;
这里输出是:4!!!4=1+1+2。
int i = 0 ;
int iNumber = 0 ;
iNumber = (++i) + (++i) + (i++) ;
printf( "iNumber = %d \n" , iNumber ) ;
这里输出是:6!!!6=2+2+2。
这里至少能说明两个问题,其一,先执行前面两个,再执行第三个;其二,(i++)这个i的自加是最后执行!
1.5
scanf()函数的返回值
1.如程序清单4. 6所示,请问输出会是什么?
程序清单4.
6 scanf()函数的返回值
int a , b ;
printf( "%d \n" ,
scanf("%d%d" , &a , &b) ) ;
输出输入这个函数的返回值?!答案是:2。只要你合法输入,不管你输入什么,输出都是2。那么我们就要深入解析scanf这个函数。scanf()的返回值是成功赋值的变量数量。
1.6
const作用下的变量
1. 阅读如程序清单4.7所示,想想会输出什么?为什么?
程序清单4.
7 const作用下的变量
#include <stdio.h> int main(int argc,char *argv[]) { const int s=10; int a=8; int *ps =(int *)(&s); int *pa=(int *)(&a); *ps=50; *pa=100; printf("s=%d,a=%d\n",s,a); return 0; }
在TC和GCC测试的答案一致,都是:50,100 而并不是10,100。即const关键字未起作用。
具体原因待查,分析可能是编译器问题。
这里补充一个知识点:(自己未验证)
const int *p 指针变量p可变,而p指向的数据元素不能变
int* const p 指针变量p不可变,而p指向的数据元素可变
const int* const p 指针变量p不可变,而p指向的数据元素亦不能变
1.7
*ptr++、*(ptr++),*++ptr、*(++ptr),++(*ptr)、(*ptr)++的纠缠不清
1. 如程序清单4.8所示程序,输出什么?
程序清单4. 8 *ptr++
int ia[3]={1,11,22};
int *ptr = ia;
printf("*ptr++=%d\n",*ptr++);
printf("*ptr=%d\n",*ptr);
纠结啊,是先算*ptr还是ptr++;还是纠结啊,ptr是地址加1还是偏移一个数组元素!
这里考查了两个知识点,
其一:*与++的优先级问题;
其二,数组i++和++i的问题。
*和++都是优先级为2,且都是单目运算符,自右向左结合。所以这里的*ptr++和*(ptr++)是等效的。
首先ptr是数组首元素的地址,所以ptr++是偏移一个数组元素的地址。那么ptr++运算完成之后,此时的ptr是指向ia[1],所以第二个输出*ptr = 11 。如图4. 1所示。那么倒回来看第一个输出,ptr++是在执行完成*ptr++之后再执行的,所以,*ptr++
= 1 。
如程序清单4. 9所示程序,输出会是什么?
程序清单4. 9 *++ptr
int ia[3] = { 1 , 11 , 22} ;
int *ptr = ia;
printf( "*++ptr = %d \n" ,
*++ptr ) ;
printf( "*ptr = %d \n" ,
*ptr ) ;
这个解释和上面解释差不多,就是++ptr和ptr++的差别,所以这里的两个输出都是:11。同样的道理,*++ptr和*(++ptr)是等效。
再如程序清单4. 10所示,输出又会是什么?
程序清单4. 10 (*ptr)++
int ia[3] = { 1 , 11 , 22} ;
int *ptr = ia ;
printf( "(*ptr)++ = %d \n" ,
(*ptr)++ ) ;
printf( "*ptr = %d \n" ,
*ptr ) ;
这个的输出是:1,2。
验证结果如下图:
相关文章推荐
- C语言的32个关键字、9种控制语句、34个运算符
- C语言的32个关键字,9种控制语句,34种运算符
- C语言的32个关键字、9种控制语句、34个运算符
- C语言自学笔记3(运算符、表达式、语句)
- 32个关键字9个控制语句34个运算符(C语言基础)
- 读朱兆祺攻破C语言之一----编程基本概念
- 读朱兆祺攻破C语言之六---数组、指针
- 读朱兆祺攻破C语言之七---结构体、联合体
- C语言学习笔记 运算符,表达式和C语句
- C语言的关键字,运算符,标识符
- C语言学习_005_运算符、表达式和语句
- 朱兆祺教你如何攻破C语言学习、笔试与机试的难点(连载)
- python学习1——标示符、关键字、输出、输入、运算符、赋值、取整取余的作用、判断语句
- C语言中的关键字及常用语句
- 黑马程序员之 ---- 基础语法上(关键字、标识符、进制、变量、数据类型、运算符、语句)
- 【JavaScript】(2)标识符与关键字\基本|引用数据类型 \变量 \运算符与表达式\流程控制语句
- 【02】常用关键字,常量和变量,运算符,判断语句
- CSharp学习笔记之四 关键字、语句、表达式和运算符
- c语言核心整理之数据类型,运算符,表达式和语句
- 第四节:C语言的32个关键字和9种控制语句