C/C++常识

1.局部变量和数组在内存栈结构中的分配细节

#include <stdio.h>
#define ARRAY_SIZE 10

void natural_numbers(void) {
    int i;
    int array[ARRAY_SIZE];

    i = 1;

    while (i <= ARRAY_SIZE) {
        array[i] = i - 1;
        i = i + 1;
    }
}

int main(){
    natural_numbers();
    printf("end");
}

内存中的分配图如下:
这里写图片描述

2.浮点数的二进制表示
以float为例,如下

#include <iostream>
#include <iomanip>
using namespace std;

void main()
{
    float x = 1.3;
    float y = 0.4;
    cout << setprecision(10) << x<<endl;
    cout<<setprecision(10) <<x + y<<endl;

    if (x + y != 1.7)
        cout << "addition failed?" << endl;
}

看输出结果

1.3
1.7
addition failed?
请按任意键继续. . .

是不是感觉结果在预测之中,但却一下子反应不过来?看着下图就明白了
float的二进制表示:

这里写图片描述

再来点更直观的

#include <iostream>
#include <iomanip>
using namespace std;

void main()
{
    float x = 1.3f;
    float y = 0.4;
    cout << setprecision(10) << x<<endl;
    cout<<setprecision(10) <<x + y<<endl;
}

输出结果

1.299999952
1.699999928

3.字节对齐
 自然对齐:
   对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的。
  
 为什么要字节对齐:
   需要字节对齐的根本原因在于CPU访问数据的效率问题。比如地址为0x00000002,则CPU如果取它的值的话需要访问两次内存,第一次取从0x00000002-0x00000003的一个short,第二次取从0x00000004-0x00000005的一个short然后组合得到所要的数据,如果变量在0x00000003地址上的话则要访问三次内存,第一次为char,第二次为short,第三次为char,然后组合得到整型数据。而如果变量在自然对齐位置上,则只要一次就可以取出数据。
  
在VS工程属性->代码生成->C/C++->结构体成员对齐中可以设置具体几字节对齐。

int main()
{
    struct {
        char a, b;
        double d;
        int i;
    } mystruct;
    int e = 0;
    return 0;
}

对于上面的结构体mystruct选用1字节对齐,可以看到结构体内部变量的地址紧密排列
这里写图片描述

4字节对齐,对应于32位cpu
这里写图片描述

8字节对齐,对应于64位cpu
这里写图片描述

4.++i和i++

#include <stdio.h>
int main(){
    int x=0,y=0;
    int a[5];
    int b[5];
    a[x++]=5;
    b[++y]=5;
    printf("x=%d,y=%d,a[0]=%d,a[1]=%d,b[0]=%d,b[1]=%d",x,y,a[0],a[1],b[0],b[1]);
    return 0;
} 

输出结果

x=1,y=1,a[0]=5,a[1]=2686868,b[0]=1982493216,b[1]=5

5.const相关

const int limit //整型变量limit不可二次赋值
const int *p //指针p指向的变量只读,p可以指向不同变量
int* const p //指针p指向的变量可以修改,p不能改变

6.static相关

int my_fn()

{
    static bool my_var_initialized = false;
    if (my_var_initialized) 
         printf("已初始化");
    my_var_initialized = true;
}

不论 my_fn函数调用多少次,static bool my_var_initialized = false;只在第一次调用时候执行。

7.extern相关

extern关键字中是否extern int *p;能指向int p[5] = {100,123};
原因在于,指向类型T的指针并不等价于类型T的数组extern int *p ;说明p是一个指针变量而不是数组,因此与实际的定义不同,从而造成运行时非法访问

int main(){
    extern int *p;
    extern int a;
    printf("%d\n", a);
    printf("%d\n", p[1]);
}

int p[5] = {100,123};
int a = 100;

如上面这样写运行就会出错,应该extern int p[];

8.结构体

int main(){
    struct bar
    {
         int b;
    } bar;
    bar.b= 10;
    printf("%d\n",bar.b);
}

可以正常运行,输出10;声明结构体struct bar{};
结构体的类型为bar;
此时在c语言声明结构体变量struct bar b;
在c++中可以只用bar b;

声明struct bar{} bar;
此时在声明结构体类型bar的同时声明一个结构体变量bar;
此时在c++中也只能用struct bar b;声明另外的结构体变量


int main(){
    struct bar
    {
         int bar;
    } bar;
    bar.bar= 10;
    printf("%d\n",bar.bar);
}

不能正常运行,具体原因还不是很清楚

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值