所有问题--有空解决

九 x=x+1,x+=1和x++哪个效率高

x=x+1最低,因为它的执行过程如下:
1. 读取右x的地址;
2. x+1;
3. 读取左x的地址;
4. 将右值传给左边的x(编译器并不认为左右x的地址相同).

x+=1其次,它的执行过程如下:
1. 读取右x的地址;
2. x=1;
3. 将得到的值传给x(因为x的地址已经读出).
x++最高,它的执行如下:
1. 读取右x的地址;
2. x自增1.


自己的理解:
x=x+1;和y=x+1;的执行过程本质相同,都是两次寻址 plus 一次加法运算。编译器在做x+1运算时和之后都不知道结果传向哪里,即x=和y=效果是一样的

而+=复合运算符,本身就被编译器支持,即编译器识别了+=之后,就已经知道源操作数和目的操作数均是一个地址。故x+=1;只有一次寻址和一次加法运算

最后x++为什么比x+=1效率高???

关于红字部分,从CPU和汇编层次去考虑,x自增1还是要将数取到加法器中,才能加1,然后再放回去,但是这样的话就和x+=1执行过程一样了?



八 C中的指针常量和常量指针





七 “a=a++;”在Java和C/C++中不同结果

Java中:

int a=1;
a=a++;
System.out.println("a值为:"+a);   // 结果为1


解释:

    a++和++a都相当于a=a+1; 不同的是, a++的返回值(或者说此表达式的值)为计算“a=a+1;”之前a的值,即1;++a的

返回值(此表达式的值)为计算“a=a+1;”之后的值,为2。

    所以,a=a++; 确定a++的返回值为1,然后计算 a=a+1; a等于2,再进行赋值,a=表达式返回值=1;

另注:http://blog.sina.com.cn/s/blog_605f5b4f0100khy0.html

C/C++中:

int a=1;

a=a++;

printf("a值为:%d\n",a);   // 结果为2,C++中也是2


https://www.zhihu.com/question/23180989/answer/23874381


一般自增自减运算符单独使用,不推荐符合使用。(这其实又和其本身产生的原因相悖。。。)



六. Java中关于int i=VALUE;  integer i=VALUE;  Integer i=new Integer(VALUE); 的区别,i存放在栈,堆,及常量池中?


五. 为什么Java中byte为8 bit,表示范围却为-128-127,多出来的那个0的补码到底怎么回事。类似地,4B的int取值范围为-(Max+1)-Max


四. Java为什么全局变量无须初始化,局部变量必须初始化

    先说结论:修饰变量时的区别(全部和局部)结论:Java中,全局变量(成员变量)如果没有初始化,JVM会自动初始化为

零;局部变量(方法中自己定义的变量)必须初始化。

public class Demo {
    int m;
    public static void main(String[] args) {
        Demo demo = new Demo();
        System.out.println(demo.m); //输出0
    }
}

public class Demo {
    public static void main(String[] args) {
        int m;
        System.out.println(m); //报未初始化错误
    }
}

https://www.zhihu.com/question/30516949

理解:

    全局变量成员变量)数目是确定的(有限的“”),新建一个对象时,JVM在Heap区申请内存,用以存放内存区域用以存放类的数据。此时若有未初始化的成员变量,可以初始化为0/null。

    而局部变量数目不确定,但是作用域可能又很小(如循环体),在块末尾可能就销毁回收了,若盲目将所有局部变量初始化(必然要为每个局部变量分配空间,并进行赋初值操作),浪费了空间和时间,还不如强制要求程序员自己必须初始化局部变量,不然报错。

    类比C/C++:“如果定义全局变量而没有初始化,系统会自动初始化为0,局部变量为随机值。”全局变量在整个程序运行期间一直占用着存储空间,局部变量只在函数被调用分配内存,调用结束回收。







三 编译器优化?

#include<stdio.h>
#include<time.h>

void Interval(int number);

void main()
{
	register int i;
	Interval(i);            //register int i 作为实参计时

	auto int j;             //auto int i 作为实参计时
	Interval(j);
}


void Interval(int number)
{
    clock_t start,finish;
    double  duration;

    start=clock();
    for(number=0;number<100000000;number++);
    finish=clock();
    duration=(double)(finish-start)/CLOCKS_PER_SEC;
    printf("用时: %f seconds\n", duration);
}

结果:

用时: 0.209000 seconds        //上个单独register运行结果基本相同
用时: 0.211000 seconds

void Interval(int number)的参数传递的确是值传递,但是不仅传递参数的数据类型,值大小,也传递其

存储类别,因为定义变量的完整形式为:

    存储类别    数据类型    变量名;

    参数传递的应该是完整的参数,三要素都包含,故编译时会考虑register和auto的区别,而不是统一处理。故

编译时,因为int number是形参,先不确定其存储位置(当然,知道其肯定不在静态存储区),不分配内存空

间,当实参到来时,会根据实参的存储类别来决定其存储位置,若为register则放在register中,若为auto则放在

动态存储区。

    至于为什么最后二者时间会一样,而且都是register的运行时间,可能的原因应该是编译器优化。

    为了充分利用计算资源,如果有空闲的寄存器,不管int的存储类别(除static,如auto),默认将int储存位置

预定在register,这样做到了既参数传递传递了完整的三要素,实际的运行中又优化全部作为register处理,结果

相同。

    但是,个人猜测,由于编译时编译器并不知道实际运行时CPU的寄存器使用情况,故应该不会强行指定所有int

存储在register中,而是在运行时视寄存器的使用情况来来决定是否优化。


二 static,extern和const区别,逻辑及内存上



一  二维数组的指针运算,到按行和按列?

whu 电信院教材






猜你喜欢

转载自blog.csdn.net/prolayman/article/details/79810883
今日推荐