int*
,char*
和float*
等指针类型指向不同的类型。但我听说指针只是作为其他地址的链接实现 - 那么这个链接如何与类型相关联,编译器可以匹配链接地址的类型(此位置的变量) ?
答案 0 :(得分:6)
类型主要是c++中的编译时间。在编译时使用变量类型来确定操作(在其他C ++代码中)对该变量执行的操作。
当你bob
时,类型为int*
的变量++
,在运行时映射到通用指针大小的整数增加sizeof(int)
。
在某种程度上,这是谎言; C ++的行为是用抽象机器来指定的,而不是具体的。编译器将您的代码解释为在该abtract机器上表示操作(不存在),然后编写具体的汇编代码,以在具体硬件上实现这些操作(只要它们被定义)。
在该抽象机器中,int*
和double*
不仅仅是数字。如果取消引用int*
并写入某个内存,则对double*
执行相同操作,并且内存重叠,在抽象机中结果是未定义的行为。
在该抽象机器的具体实现中,使用相同地址解引用int*
或double*
的指针作为数字会产生相当明确的行为。
这种差异很重要。编译器可以自由地假设抽象机器(其中int*
和double*
是非常不同的东西)是唯一重要的现实。因此,如果您写入int*
,请写入double*
,然后从int*
读回,编译器可以跳过回读,因为它可以证明在抽象机器中写入double*
无法更改int*
指向的值。
所以
int buf[10]={0};
int* a = &buff[0];
double* d = reinterpret_cast<double*>(&buff[0]);
*a = 77;
*d = 3.14;
std::cout << *a;
编译器可以跳过std::cout << *a
处的明显读取。同时,如果它实际发生在真实硬件上,它将读取由*d
写入生成的位。
在推理C ++时,你必须同时考虑3件事;在编译时会发生什么,抽象机器行为以及代码的具体实现。其中两个(编译时和抽象机)int*
的实现方式与float*
不同。在实际运行时,int*
和float*
在寄存器或内存中都将是64位或32位整数。
在编译时完成类型检查。然后,或者从不排除RTTI(运行时类型信息)的情况。
RTTI就像dynamic_cast
之类的东西,它不适用于指向float*
或int*
等基元的指针。
在编译时该变量随身携带它到处都是int*
的事实。在抽象机器中,同上。在具体的编译输出中,它忘记了它是int*
。
答案 1 :(得分:0)
此阶段没有特定的“链接”,也没有任何隐藏的元数据存储在某个地方。由于编译C和C ++并最终生成独立的可执行文件,编译器“信任”程序员并简单地向他提供表示内存地址的数据类型。
如果此地址没有明确定义,则可以使用function changeFooBarToOne(foo) {
foo.bar = 1;
}
describe('changeFooBarToOne', () => {
it('modifies the bar property value to 1', () => {
const foo = { bar: 0 };
changeFooBarToOne(foo);
expect(foo.bar).toBe(1);
})
})
//another way
describe('changeFooBarToOne_1', () => {
it('modifies the bar property value to 1', () => {
const foo = { bar: 0 };
changeFooBarToOne(foo);
expect(foo).toEqual({bar : 1});
})
})
指针。如果您知道这将是特定内容的位置,则可以使用特定数据类型(例如void *
或int *
)对其进行限定。因此,编译器将能够直接访问后面的对象,但是这种地址的存储方式在每种情况下保持不变,并保持相同的格式。
请注意,此限定仅在编译时完成。它完全消失在最终的可执行代码中。这意味着将生成此生成的代码以处理某些类型的对象,但如果您反汇编机器代码,则一开始不会告诉您哪些对象。你必须自己解决这个问题。
答案 2 :(得分:0)
变量表示存储在一个或多个存储单元或&#34;字节&#34;中的数据。在定义变量时,编译器会将这组字节与名称和类型相关联。
硬件使用二进制数来访问存储器单元。这被称为&#34;地址&#34;记忆细胞。
当您将某些数据存储在变量中时,编译器将查找变量的名称并检查您要存储的数据是否与其类型兼容。如果是,则生成代码,将其保存在该地址的存储单元中。
由于此地址是数字,因此它本身可以存储在变量中。这个地址变量的类型是&#34;指向T&#34;的指针,其中T是存储在该地址中的数据的类型。
程序员有责任确保此地址变量确实对应于有效数据,而不是某些随机内存区域。编译器不会为您检查这个。