为什么类型转换指针是必要的?

时间:2017-08-02 19:25:09

标签: c pointers types casting embedded

为了理解使用嵌入式系统时的指针,我试图了解这段访问内存映射寄存器的代码:

uint32_t regval = *(uint32_t *)0x40048004U;

在我看来,没有类型转换,这意味着regval现在等于地址的内存内容。我想这应该够了但事实并非如此。但是当它进行类型转换时,你会将它视为单个操作的指针,这看起来有点多余。

因此,您正在将regval视为指向0x40048004U内存内容的未知地址的内存内容?为什么类型铸造甚至是必要的?

6 个答案:

答案 0 :(得分:6)

我理解你在问我们为什么不能这样做:

uint32_t register_value = *0x40048004U;

(即"为什么我们不能取消引用常数整数?")。

有几个答案:

  • C&C的整数常量语法没有指针值的任何注释,只有有符号/无符号/短/长值(使用UL等等)。
  • 如果您可以执行*0x40048004U,则没有指示数据类型的指针 - 计算机要从该地址读取多少字节?签了吗?无符号? (记住,常量的类型与内存地址的类型有关,而不是它指向的值)
  • 因此,要求使用显式强制转换运算符*(valueType*)0xDEADBEFF意味着可以使用与非常量值的强制转换相同的语法指定类型 - 无需引入新的单独语法,并且这种强制转换是静态操作,其运行时性能为零。

答案 1 :(得分:5)

C是在内存很小的时候设计的,并且没有为编译器类型推理发布数千个博士。

虽然在这种特殊情况下编译器可能会推断出

uint32_t regval = *0x40048004U;

应该是隐含的uint32_t指针的解除引用,而不是乘法运算中的缺失参数,实际情况是存在可能失败的情况(例如,当有多个时int x = 0x00->foo成员名为foo)。

所以相反,要求规定一切都有一个类型,如果你想使用某些东西,就好像它是一个不同的类型,你必须明确这一点。 45年来一直如此。 Fnord。

答案 2 :(得分:3)

指针间接运算符*只能应用于指针。当然,它的操作是访问指针指向的数据对象。 但它必须知道指向对象的大小和类型

如果你刚才说

uint32_t regval = *0x40048004;

编译器无法知道大小和类型。 (您可能认为这是隐含在左侧分配给uint32_2的事实,但C不会那样工作。)

如果你想要“记住”这种类型的东西,只需创建并初始化一个指针变量:

uint32_t *regptr = (uint32_t *)0x40048004;
uint32_t regval = *regptr;

答案 3 :(得分:2)

指针的类型决定了运行时期望在给定地址和后续地址处找到的内容。例如,如果> var(arithmetic) [1] 0.0159136 > var(opt) [1] 0.02724814 的类型为p,则char *是该地址的单字节。如果其类型为*p,则它期望在该地址处找到(可能)4个字节,表示整数。如果int *的类型是指向某个100字节结构的指针,那么它期望在那里找到100个字节的结构。

此外,类型确定指针数学。 p是p的下一个 thing 的地址,可能是1个,4个或100个字节。

答案 4 :(得分:0)

您需要显示整数常量将用作指针。您需要向编译器显示此指针指向的对象类型。接下来,您将获得此指针指向的对象的值(在这种情况下,它将是32位字)。

答案 5 :(得分:0)

类型转换指针不是必需的; <?xml version="1.0" encoding="utf-8"?> <!-- This file is used by the publish/package process of your Web project. You can customize the behavior of this process by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121. --> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <WebPublishMethod>FileSystem</WebPublishMethod> <PublishProvider>FileSystem</PublishProvider> <LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration> <LastUsedPlatform>Any CPU</LastUsedPlatform> <SiteUrlToLaunchAfterPublish /> <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish> <ExcludeApp_Data>False</ExcludeApp_Data> <DeleteExistingFiles>False</DeleteExistingFiles> <PipelineDependsOn> CopyAssets; $(PipelineDependsOn); </PipelineDependsOn> <publishUrl>C:\inetpub\wwwroot\local.MyApp\Website</publishUrl> </PropertyGroup> <Target Name="CopyAssets"> <Message Text="Inside of CopyAssets" Importance="high"/> <Exec Command="%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe -File &quot;$(SolutionDir)Foundation\Scripts\Powershell\CopyAssets.ps1&quot; $(SolutionDir) $(publishUrl)"/> </Target> </Project> 不是指针。强制转换将文字常量 integer 重新解释为指针。

此外,即使将0x40048004U解释为地址,编译器也需要知道在取消引用时它指向的数据类型。