4

我知道在c中,指针指向内存地址。在下面的代码中

char *cp;
someType *up; // Assuming that someType is a union of size 16 bytes
cp = sbrk(nu * sizeof(someType)); 

// Here is what confuses me
up = (someType *)cp;

根据此链接http://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays

  1. 如果cp指向的地址是0x1234,那么0x1234应该是新分配内存的开始吧?

  2. 因此,当“cp”被转换为指向 someType 的指针并分配给“up”时,它实际上说“up”是指向 0x1234 的指针,假设在 32 位系统中,每个内存地址占用 4 个字节,一个 someType 对象会使用4个内存地址来存储它的值,所以地址0x1234、0x1235、0x1236、0x1237共同存储了一个someType对象,这样对吗?

提前致谢。

4

5 回答 5

4

指针类型转换在机器级别不做任何事情。内存中的值仍然只是内存中一个普通的旧值。

在语言级别,该值用作地址。换句话说,它通常用作传递给需要内存位置的操作的值,例如程序集“加载”操作。

在语言级别,额外的结构被添加到机器操作中,这些“额外”之一是数据类型。编译器负责检查是否存在类型规则违规,但在运行时没有这样的约束。

结果,强制转换在运行时什么都不做,但在编译时它指示编译器不发出错误,因为指针值的类型现在将被视为与保存地址的变量兼容的类型。

于 2013-08-15T15:13:33.347 回答
4

即使在 32 位系统上,内存地址通常指的是单个字节,而不是四个。因此,您Header将覆盖 0x1234 和 0x1243 之间的 16 个内存地址。

于 2013-08-15T15:17:40.380 回答
1

首先要记住,指针是内存地址的抽象;不要假设指针值和 RAM 中的物理位置之间存在一一对应关系。指针也有与之相关的类型语义;向指针值加 1 使其指向所指向类型的下一个对象

char *cp;
int *ip;
struct huge *hp;

cp = cp + 1; // advances cp to the address of the next char (1 byte)
ip = ip + 1; // advances ip to the address of the next int (anywhere
             // from 2 to 8 bytes depending on the architecture)
hp = hp + 1; // advances hp to the address of the next struct huge (however
             // many bytes struct huge takes up)

这正是数组索引的工作原理;表达式a[i]被视为*(a + i);您从基地址偏移任何大小的i 元素,而不是i字节。

就演员而言...

指向 的指针与指向 的指针char是不同的、不兼容的类型Header。根据底层架构,它们可能具有不同的大小和表示。因此,该语言不允许通过简单的赋值将一个隐式转换为另一个;您必须使用强制转换将 rhs 值转换为 lhs 预期的类型。

于 2013-08-15T16:10:25.477 回答
1

要回答您的问题:

cp指向新分配内存的开头。

但是,up将包含与 相同的地址cp。请注意,尝试将指针从一种类型分配给另一种类型而不首先“强制转换”它是一种不好的形式 - 只是为了告诉编译器你真的打算做这样危险的事情。

通常在类型之间进行分配会导致各种问题 - 因此,如果您在没有强制转换的情况下执行此操作,编译器会抛出警告。然而,强制转换实际上对程序代码本身没有任何影响——它更像是程序员告诉编译器他们真正的意思是他们所做的事情的一种方法。


顺便说一句,指针up是在函数的堆栈上分配的。分配一个值up实际上将值放在堆栈上的内存位置。因此,通过分配cpup您只是将指针的值复制cp到分配给的堆栈中的位置upsbrk()调用分配的内存中没有任何内容。

于 2013-08-15T15:13:26.003 回答
1

如果cp指向的地址是0x1234,那么0x1234应该是新分配内存的开始吧?

正确的。

所以当 cp 被转换为指向 Header 的指针并赋值给 up 时,实际上说 up 是一个指向 0x1234 的指针,假设在 32 位系统中,每个内存地址占用 4 个字节,一个 Header 对象将使用 4 个内存地址存储它的值,所以地址0x1234、0x1235、0x1236、0x1237共同存储一个Header对象,这样对吗?

错误的。C 是严格字节寻址的。该Header对象将占用地址0x12340x1234 + sizeof(Header) - 1包括在内,无论sizeof(Header)是什么(在这种情况下可能是 16)。为了混淆这个问题,将 1 添加到任何指针都会将其数值增加它指向的sizeof任何内容,因此up + 1指向超出分配内存末尾的情况。然而cp + 1,它指向头对象表示中的第二个字节,不管它是什么。(根据定义sizeof(char)为 1。)


这与您的问题无关,但我必须警告您,sbrk使用非零参数调用导致您的程序在下一次调用malloc, reallocor后的某个不确定点崩溃free,并且几乎所有标准库函数都允许调用那些功能“在引擎盖下”。如果您想直接从操作系统进行大量分配,请使用mmap.

于 2013-08-15T15:18:22.197 回答