C语言复习

之前复习C时候整理的一些word笔记,刚清理磁盘发现的,感觉扔了又可惜,以后还可以看看就整理成博客

1. 二维数组维数声明错误

	int a[]; //错误不知长度
	int a[] = { 14};  //正确,元素个数为1
	int b[][3] ={0,0} ; //正确,元素个数为1,每个元素长为3
	int c[][] = {{1},{2,1}};  //错误

总结:定义数组时,数组个数可以省,数组长度不能
(只能省最高维)

2. 显示出 ”My salary was increased by 15%!” (有引号) printf(“\”My salary was increased by 15%%!\”\n”);

理由:因为%是代表输出的格式,所以要输出百分号必须用%%
		“”输出要转
		\”  为 “
		%% 为 %
		! 为 !(不需要转)
		\”  为 “

总结:要输出时用转义序列,反斜杠”\”后面的一个字符原样输出

> 	例:输出  ‘hello;  (注意有个单引号)
> 			cout<<"\'hello";
> 			printf("\'hello"); 		输出’hello’
> 			cout<<”\’hello\’”<<endl;

3. 3||5 结果问题

	int a(3);
	int b(5);
	a || b 结果为1   ()
	cout << (3 || 5) << endl;  //结果为1
	cout << sizeof((3 || 5)) << endl;   //结果为1
	cout << ((5 || 1) == 1 ? "equal 1" : "not equal 1") << 	endl;  //结果为equal 1

4. C语言的基本功能模块为函数,c语言一切皆函数

5. 有以下定义:char x[ ]=“abcdefg”; char y[ ]={‘a’,‘b’,‘c’,‘d’,‘e’,‘f’,‘g’};则数组x的长度大于数组y的长度。

(这题为计算字符长度,但第二个数组里面并不是字符串,而strlen为求字符串的长度,这里不能用strlen,要用sizeof比较)
Strlen大小不算\0
char x[5] = "abcd";  //定义char x[4] = “abcd”会报错,因为末尾要\0;
strlen(x)  // 结果为4
sizeof(x);  //结果为5
char y[4] = { 'a','b','c','d' };char a[100] = "abcd";
	cout << sizeof(a) << endl;  //结果为100
	cout << strlen(a) << endl;   //结果为4

6. 标准规定其他函数不能调用main()函数

7. ++p比p++更好(通过反汇编可以知道++p两步p++三步)

8. 下列不属于未定义的行为是©
A. int i=0;i=(i++);
B. char *p=”hello”;p[1]=’E’
C. char *p=”hello”;char ch=*p++
D. int i=0;printf(“%d%d\n”,i++,i–)

未定义行为(Undefined
Behavior)是指C语言标准未做规定的行为。同时,标准也从没要求编译器判断未定义行为,所以这些行为有编译器自行处理,在不同的编译器可能会产生不同的结果,又或者如果程序调用未定义的行为,可能会成功编译,甚至一开始运行时没有错误,只会在另一个系统上,甚至是在另一个日期运行失败。当一个未定义行为的实例发生时,正如语言标准所说,“什么事情都可能发生”,也许什么都没有发生。一句话,未定义行为就是运行结果不确定

1.变量即是左边结果,又是右边的操作数,如a+=a++,a %= b ^= a ^= b ^= a
2.使用越界数组也是C的一个“未定义行为”
3.允许一个随便指的指针的读写。
4.使用未初始化的变量 A选项,不知道编译器会怎么选择自增和赋值的顺序,所以这是由编译器决定的,属于未定义行为。 首先,未定义是说最后i到底等于多少? i=i++;
我们知道,i++是先返回i的值,然后再+1。未定义就出现在i返回以后(此时返回0),=和++到底编译器先执行哪个。
如果先执行=,那么执行完=后i为0,再执行++,i为1。
如果先执行++,那么执行完++后i为1,再执行=,注意这里上面返回的是0,因此i赋值为0。=运算符只可能把0赋给i,不可能把1赋给i,这是重点,i=++i才是把1赋给i B选项,”hello“这个字符串属于一个字符串常量了,指针p指向了这个字符串常量,通过这个指针来直接修改常量第二个字符,这也属于未定义行为。
C选项,只是通过指针找到第二个字符并将它赋值给一个字符变量,并没有改变这个字符串常量,所以不属于未定义行为。
D选项,在printf语句中,i++和i–谁先执行由编译器决定,这是未定义行为。 int i = 0; i = (i++); cout
<< i << endl; //在dev运行结果为0在vs2015为1 int j = 0; printf("%d%d",
j++,j–); //在vs和dev是-10

9. 后置++的本质:

两条理论

 (b = a++)
  int a = 0; 			
  int b = a++;    //b的结果为0,a的结果为1 

(1): c = a ; a += 1; b = c; (gcc)
(严格按照优先级顺序先++再赋值(赋a++之前的值), 然后把a++之前的值给b)
(2): b = a ;a += 1;(国内教程说法) (vs)
违背优先级顺序先赋值再++,

例子 int a = 2; int c = a++ + a++; //改为int c = (a++) + (a++)效果一样
(1)对于vs,先赋值再自增,结果为c = 2 + 2 等赋值结束a再自增变为4 (++对于表达式计算不产生影响)
(2)对于gcc, 先自增,再把之前的结果给c,因此c = 2 + 3 a还是4 造成啦二义性 例子 int a = 1; a =(a++); 对于gcc: 最终a为1; //先自增,再把之前的值给a 对于vs 结果为2
//先赋值,然后再自增让a变为2

例:int a = 2; int b = a++ + a++ + 3*4 //vs结果为16 gcc为17

10. 若变量已经正确赋值,下列表达式不符合c语言的语法的是(CD)
A. a = a + 2;
B. a = 7 + b + c,a++;
C. int(12.3%4);
D. a =a + 7 = c + b;

解析:对于C来说,取余只能在整数上面来操作 也就是说下面代码是行不通的
int a = 12.3%2; 对于D来说赋值运算是典型的右结合,但是在辅助操作运算符左边,要求必须是变量,在本题中7为常量 也就是说下面这个代码是行不通的 int a = 1; int b = 0; b + 1 = a + 2;

11. 指针变量可以由整形变量直接赋值,不能用浮点变量直接赋值。

int* p = (int*)1235445; //直接用整数,因为地址本来就是十六进制整数, 所
以用前面加(int*)会把它转化为十六进制的整数并加上0x 而float要转为int int* q =
(int*)(int)123456.6; 例: int* p = (int*)1235445;
printf("%x\n",1235445); //结果为12d9f5 cout<<p<<endl; //结果为0x12d9f5

12. 以下字符中不是转义字符的是(C)
A. ‘\a’;
B. ‘\b’
C. ‘\c’
D. ‘\’
解析:常见转义字符表

13. 逗号表达式(优先级最低,左结合)
逗号表达式,又称为“顺序求值运算符”。逗号表达式的一般形式为
表达式1,表达式2

3+56+8
逗号表达式的求解过程是:先求解表达式1,再求解表达式2。整个逗号表达式的值是表达式2的值。例如,上面的逗号表达式“3+56+8”的值为14。又如,逗号表达式
  a=  3*5,a*4      (假设a初始值为3)
易错想法:先计算逗号表达式(3*5,a*4)  结果为12再赋值给a(错误,,没有想优先级)
易错想法:先计算a = 3*5 = 15;再计算a = a *460
正确做法:先计算 a = 3*515,此时a已经是15啦,原来的逗号表达式变为15,a*4
             整个表达式结果为60但a还是15
a = (3 * 5, a * 4)  //a的值等于逗号表达式值12

例:(x=4*5, x*5), x+25 
最后表达式结果为45

14. 输出的结果为:
#define MIN (x,y) (x)<(y) ? (x):(y)
void main()
{
int i=10,j=15,k;
k=10*MIN(i,j);
printf ("%d\n",k);
}

宏替代完全替代: k = 10 * (10) < (15) ? (10):(15);
结果为15

15. malloc函数进行内存分配是在什么阶段(D)
A. 编译阶段
B. 链接阶段
C. 装载阶段
D. 执行阶段

解析:程序占用三种类型的内存:静态内存、栈内存、堆内存; 

静态内存: 用来保存局部static对象、类static数据成员以及定义在任何函数之外的变量(全局变量) 第一次调用时分配内存并作初始化

栈内存:用来保存定义在函数内的非static对象。
分配在静态内存或栈内存中的对象由编译器自动创建和销毁。对于栈对象,仅在其定义的程序块运行时才存在;static对象在使用之前分配,在程序结束时销毁。

堆内存:在程序运行时分配。动态对象的生存周期由程序(用户)来控制。

各个内存最大?

16. 宏替代不占用程序运行时间

17. 关于c++/java类中static成员和对象说法正确的是(C)
A. static 成员变量在对象构造时生成
B. static 成员函数在对象成员函数中无法调用
C. 虚成员函数不可能是static 成员函数
D. static 成员函数不能访问static 成员变量

解析:static成员变量是在类加载时候生成的,static成员函数既可以通过类名直接调用,也可以通过对象名进行调用,虚函数是c++中的,虚函数不可能是static的,static成员函数可以访问static变量,类的static成员属于类不属于对象,静态与非静态唯一区别就是有无this指针

static的学习
1、静态全局变量:全局变量加上static关键字

特点:
 1、在全局数据区分配内存
 2、未出初始化的会被自动初始化为0
 3、整个文件可见,不会被其它文件所访问

、静态局部变量:全局变量加上static关键字

特点:
 1、在全局数据区分配内存
 2、在程序执行到该对象的声明处被首次初始化,
    之后的函数调用也不会再进行初始化
 3、始终驻留在全局数据区,直到程序运行结束
    但其作用域为局部作用域,当定义它的函数或语句块结束时,
    其作用域随之结束。

3、面向对象(类中的static关键字)

3.1 静态数据成员:数据成员加上static

特点:
1、静态数据成员只分配一次,供所有对象共用
2、static数据成员在全局数据区分配内存,
所以没有产生类对象时其作用域就可见,
即不产生类的实例时可以操作
3、static成员变量是在类加载的时候生成的

3.2 静态成员函数:static + 成员函数
    
    特点:
     1、无法访问类对象的非静态数据成员和非静态成员函数
     2、可以访问静态的成员和函数
     3、非静态的成员函数可以访问static的
    4、static成员函数不可以声明为const和virtua

18. 有如下程序,输入数据:12345M678<cR>后(表示回车),x的值是() 。
#include<stdio.h>
main()
{
int x;
float y;
scanf("%3d%f",&x,&y);
}

解析:scanf("%3d%f",&x,&y); int
x,说明x是整形数据!%3d意思就是取3个整形数据,y是浮点数!输入的M后面的识别不了自动忽略!只有12345能被识别!&x就是%3d对应的数据,对应123这三个整数!所以x是123。
%f对应y,故y应该是45。

19. 下列属于合法的字符常量是(B)
A. ’\087’
B. ‘\x43’
C. ‘abc’
D. 68

解析A:表示八进制,八进制每个数取值0 – 7 B.表示十六进制67,对应字符C C.只能一个字符 D.只能引号

`

20. 静态局部生命期全局,作用域受限于本函数

#include<iostream>
using namespace std;
void fun();
int main()
{
	for(int i = 1;i<=4;i++)
		fun();   //结果依次为2 3 4 5, 全局变量的初始化代码,只执行1次
作用域受限于函数内部,但可以拐弯用指针来访问。(类中私有成员也是可通过指针)

	return 0;
}
void fun()
{
	static int m = 1;
	m++;
	cout<<m<<endl;  
	
}



#include<iostream>
using namespace std;
int *fun();
int main()
{
	int *p = fun();
	(*p)++;    //m也发生了改变
	fun();
	return 0;
}
int *fun()
{
	static int m = 1;
	cout<<m<<endl;
	return &m;
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值