1 printf 和cout都是将输入按照从右到左压栈,然后输出依次出栈
例子
int arr[] = {6,7,8,9,10};
int* ptr = arr;
*(ptr++) += 123;
cout<<*ptr<<" "<<*(++ptr)<<endl
=================================
8,8
=================================
在计算时,遇到x++会记录此时的x的值作为最后的输出结果。遇到x和++x的时候则不会将此时的计算结果作为最终的输出,只会修改x的值,在最终输出的时候都输出x的值(所以++x和x的结果总是一样的)。
为什么会是这个样子呢?参见某高手解释吧:
对于a++的结果,是有ebp寻址函数栈空间来记录中间结果的,在最后给printf压栈的时候,再从栈中把中间结果取出来;而对于++a的结果,则直接压寄存器变量,寄存器经过了所有的自增操作。
分析上面的,依次压入,但是,根据前面的定义,两者实际相等
int x=1; printf("%d %d %d %d %d
",x,x++,++x,x++,x);
===============================
4 3 4 1 4
===============================
2 两个数的较大值
int max = (a+b+abs(a-b))/2
3 宏定义最大值
#deine MAX(A,B) ((A)>(B)?(A):(B))
4 const 用途
(1) 修饰常量
(2) 修饰函数参数
(3) 修饰函数返回值
(4) 修饰函数定义
5 sizeof
char s[] = "abc";
cout<<strlen(s)<<endl;
cout<<sizeof(s);
=================
3
4
=================
6 指针数组 数组指针
指针数组:指一个数组里面装着指针 int *ptr[]
数组指针:指向数组的指针 int (*ptr)[]
7 int a[] = {1,2,3,4,5};
int* ptr = (int*)(&a+1);
printf("%d %d",*(a+1),*(ptr-1));
a是数组名,是a[0]的一个别名,这样,&a相当于是一个指向a[0]的一个数组指针,数组指针+1相当于对整个数组的增加,所以,ptr现在是指向第6个(不存在),这样*(ptr-1)指向第5个元素,即5
===============================
2,5
===============================
8 c++有了malloc/free 为什么还用new/delete
(1) malloc是c标准库,new是运算符
(2)对于非内部类型的对象,例如class等,malloc无法完成
9 char *a[] = {"abc","the","apple"};
char**p = a;
p++;
cout<<*p<<endl;
====================
the
====================
10. TCP与UDP之间的区别
(1)TCP是传输控制协议,提供的是面向连接、可靠的字节流服务,拥塞控制协议。
TCP套接字由一个四元组(源IP,源端口号,目的IP,目的端口号)
UDP(目的IP,目的端口号)
1.基于连接与无连接;
2.对系统资源的要求(TCP较多,UDP少);
3.UDP程序结构较简单;
4.流模式与数据报模式 ;
5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。
11
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
cout << boolalpha << ( str1==str2 ) << endl; // 输ê?出3?什ê2么′?£?
cout << boolalpha << ( str3==str4 ) << endl; // 输ê?出3?什ê2么′?£?
cout << boolalpha << ( str5==str6 ) << endl; // 输ê?出3?什ê2么′?£?
==============================
分别输出false,false,true。str1和str2都是字符数组,每个都有其自己的存储区,它们的值则是各存储区首地址,不等;str3和str4同上,只是按const语义,它们所指向的数据区不能修改。str5和str6并非数组而是字符指针,并不分配存储区,其后的“abc”以常量形式存于静态数据区,而它们自己仅是指向该区首地址的指针,相等。
==============================
12 说一说C与C++的内存分配方式?
1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,如全局变量,static变量。
2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
3)从堆上分配(动态内存分配)程序在运行的时候用malloc或new申请任意多少的内存,程序员负责在何时用free或delete释放内存。动态内存的生存期自己决定,使用非常灵活。
13 析构函数为什么一般情况下要声明为虚函数?
A2:虚函数是实现多态的基础,当我们通过基类的指针是析构子类对象时候,如果不定义成虚函数,那只调用基类的析构函数,子类的析构函数将不会被调用。如果定义为虚函数,则子类父类的析构函数都会被调用。
14 c++中static用法
(1)全局变量
(2)变量作用域只限于此文件
15
union
{
int i;
char x[2];
}a;
int main()
{
a.x[0] =10;
a.x[1] =1;
printf("%d",a.i);
}
=================================
266
=================================
低位低地址,高位高地址
在内存中的情况应该是这样的:
00000001 00001010(二进制)
你要打印的i和x共享一片内存,输出来就是十进制266了。
15
char const str1[] = "abc";
char const str2[] = "abc";
const char* str3 = "abc";
const char* str4 = "abc";
cout<<boolalpha<<(str1==str2)<<endl;
cout<<boolalpha<<(str3==str4)<<endl;
===================
false
true
===================
解答:str1和str2两个字符数组存储在栈上,因此地址不相等,但是str3和str4以常量形式存储与常量区。
16:
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
============
2,5
============
17:
struct A{
int a;
short b;
char c;
}*p;
求p+0x10,(Ulong)p+0x10,(short*)p+0x10
sizeof(A)为8,指针加减其实是指针所指向的元素的前后移动,因此加减的是指针的sizeof.因此第一个为p+(sizeof A)*0x10.
第二个则直接转换为整数,所以直接加减
第三个则为p + (sizeof short)*0x10
18:
char a[] = "abc" #栈上分配
char*a = "abc" #常量
所以可以strcpy(a,"h")第一个可以,第二个不可以,因为常量不可修改