为了理解使用嵌入式系统时的指针,我试图了解这段访问内存映射寄存器的代码:
uint32_t regval = *(uint32_t *)0x40048004U;
在我看来,没有类型转换,这意味着regval现在等于地址的内存内容。我想这应该够了但事实并非如此。但是当它进行类型转换时,你会将它视为单个操作的指针,这看起来有点多余。
因此,您正在将regval视为指向0x40048004U内存内容的未知地址的内存内容?为什么类型铸造甚至是必要的?
答案 0 :(得分:6)
我理解你在问我们为什么不能这样做:
uint32_t register_value = *0x40048004U;
(即"为什么我们不能取消引用常数整数?")。
有几个答案:
U
,L
等等)。*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 "$(SolutionDir)Foundation\Scripts\Powershell\CopyAssets.ps1" $(SolutionDir) $(publishUrl)"/>
</Target>
</Project>
不是指针。强制转换将文字常量 integer 重新解释为指针。
此外,即使将0x40048004U解释为地址,编译器也需要知道在取消引用时它指向的数据类型。