C中的内存寻址和指针

时间:2012-11-16 11:49:55

标签: c

这取自C,并以此为基础。 我们假设我们有一个32位指针

char* charPointer;

它指向内存中包含一些数据的某个位置。它知道这个指针的增量是1个字节,等等。 另一方面,

int* intPointer;

也指向内存中的某个位置,如果我们增加它,它知道如果我们加1则它应该增加4个字节。

问题是,我们如何能够使用这些指针来处理完整的32位可寻址空间(2 ^ 32) - 4千兆字节,如果显然它们中包含一些允许它们彼此分离的信息,例如char*int*,因此这不会留下32个字节,但会少一些。

在输入这个问题时,我开始思考,也许它是所有的合成糖,真的是编译器?也许原始指针只是32位,它不关心类型?是这样的吗?

6 个答案:

答案 0 :(得分:18)

您可能会对编译时间与运行时间感到困惑。

在编译期间,gcc(或任何C编译器)知道指针的类型,特别是知道该指针变量指向的数据的类型。因此gcc可以发出正确的机器代码。因此,int *变量的增量(在具有32位int的32位机器上)被转换为4(字节)的增量,而char*变量的增量被转换增量为1。

在运行时,编译后的可执行文件(它不关心或需要gcc)只处理机器指针,通常是字节地址(或某些单词的开头)。

类型(在 C 程序中)在运行时期间是未知的。

其他一些语言(Lisp,Python,Javascript,....)要求在运行时知道类型。在最近的C ++(但不是C)中,一些对象(具有虚函数的对象)可能有RTTI

答案 1 :(得分:13)

确实是语法糖。请考虑以下代码片段:

int t[2];
int a = t[1];

第二行实际上是

的捷径
int a = *(t + 1); // pointer addition

本身是

的捷径
int a = *(int*)((char*)t + 1 * sizeof(int)); // integer addition

在编译器检查了类型后,它会删除强制类型转换器,并且只能处理地址,长度和整数。

答案 2 :(得分:3)

是。原始指针是32位数据(或16位或64位,具体取决于体系结构),并且不包含任何其他内容。它是int *char *struct sockaddr_in *只是编译器的信息,知道在递增时实际添加的数字是什么,以及当你取消引用它时它将具有的类型。

答案 3 :(得分:3)

您的假设是正确的:要了解如何处理不同类型的指针,请尝试运行此程序:

int main()
{
    char * pc = 0;
    int * pi = 0;

    printf("%p\n", pc + 1);
    printf("%p\n", pi + 1);

    return 0;
}

你会注意到,在char *中添加一个会使其数值增加1,而对int *执行相同操作会增加4(这是我机器上int的大小)。

答案 4 :(得分:2)

正如你最后所说的那样 - C中的类型只是一个编译时概念,告诉编译器如何为变量执行的各种操作生成代码。

最后,指针只是归结为它们指向的地址,一旦编译代码,语义信息就不再存在了。

答案 5 :(得分:1)

增加int *指针与增量char *不同,因为指针变量声明为int *。您可以将int *转换为char *,然后它将以1个字节递增。

所以,是的,这只是语法糖。它使某些类型的数组处理更容易,并使void *用户感到困惑。