1. 不可变数据类型是永远不会被改变的。
const int i = 0; //指定变量i为不可变常量
int * j = (int *)&i; //强行将j的指针指向常变量i, &i指的是得到变量i的内存地址
* j = 1;
printf("%d %d", i, *j) 最终得到0,1

因为i是常变量(不可改变的变量),所以即使指针变量j指向了i的地址之后重新赋值。这个时候内存会为常变量开辟一个新的内存地址来存储原始值0,并且在输出的时候使用的还是原来的值。

*j指的是这个指针变量所指向的值,也就是它所存储的内存地址,通过该地址找到的值
如果这个时候输出j,那么将打印出*j中存储的内存地址

  1. 在16位机器上,下面这段代码输出结果:
int i = 65536;
    std::cout <<i;
    i = 65535;
    std::cout<<i;

65536部分
在c语言中int类型是带符号的32位整型。题中i=65536,我们把它转为2进制

1,0000,0000,0000,0000, 超过了16位二进制的范围,所以会把第一位去掉变成0000,0000,0000,0000,结果为0

65535部分
补码的表示方法是: 正数的补码就是其本身, 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后 +1. (即在反码的基础上 +1)
65535 转换成二进制位1111 1111 1111 1111. int类型采用补码形式,所以最后会通过补码变为-1。

计算方式:
原码:

[+1]原 = 0000 0001
[-1]原 = 1000 0001

反码
反码的表示方法是: 正数的反码是其本身,负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反

补码
补码的表示方法是: 正数的补码就是其本身, 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后 +1. (即在反码的基础上 +1)
[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补

参考资料

  1. 下面这段代码输出d为:
int a=1, b=0, c=-1,d=0;
	d = ++a || ++b && ++c;
	std::cout<<d<<endl;

++a的结果为2,但是在逻辑运算中它就是真值True, 所以为1。 根据短路效应,||运算中左边如果为True则右边的无须再计算了。所以结果为1

  1. 在C++程序中调用被C编译器编译后的函数,为什么要加extern “C”声明?

  2. extern int a;
    指的是告诉编译器在其他地方已经定义了变量a,需要从另外的内存中去找。

  3. typedef void(*FUN)()
    定义以个名为FUN的类型,参数为空,返回值是void.

  4. 指针和引用的区别
    指针指的是一块内存的地址,而引用指的是某个变量的别名
    引用不能指向一个空值,否则会报错,而指针可以。所以在引用一个变量时,需要考虑好该变量会不会有可能存在空值的情况,如果有空值的情况就需要使用指针。同样在函数中作为参数传递的时候,