您的位置:首页 > 编程语言 > C语言/C++

C/C++常识

2015-12-17 00:31 363 查看
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);
}


不能正常运行,具体原因还不是很清楚
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: