关于long long unsigned long 打印long 范围问题

JAVASCRIPT:#include &stdio.h&
int main() {
unsigned long long int num = ; //FYI: fits in 29 bits
int normalInt = 5;
printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
My number is 8 bytes wide and its value is l. A normal number is 0.
I assume this unexpected result is from printing the unsigned long long int. How do you printf() an unsigned long long int?
解决方案 Use the ll (el-el) long-long modifier with the u (unsigned) conversion. (Works in windows, GNU).
printf("%llu", );
本文地址: &
的#include<&stdio.h中GT;诠释主(){
无符号长长整型NUM = ; //供参考:适合在29位
INT normalInt = 5;
输出(“我的号码是%d字节宽,其值为%UL正常数量为%d \\ n。”的sizeof(NUM),NUM,normalInt);
返回0;} 输出: 我的号码是8个字节宽,其值为升。一个正常的数字是0。 我想这意想不到的结果是从印刷无符号长long int类型。你怎么的printf()的无符号长long int类型?解决方案 使用的LL(EL-EL)长隆改性剂与U(无符号)转换。 (工作在Windows中,GNU)。 的printf(“%LLU”,);
本文地址: &
扫一扫关注官方微信2007年6月 总版技术专家分月排行榜第三
2007年6月 VC/MFC大版内专家分月排行榜第一
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
本帖子已过去太久远了,不再提供回复功能。后使用快捷导航没有帐号?
查看: 10668|回复: 44
不得不说~~关于 *(unsigned long *) 和 (unsigned long)
在线时间1689 小时
威望23973分
芯币14120枚
TA的帖子TA的资源
然而我很悲伤地再次郑重声明:我木有错!具体请看我回复 水果君 那难得一见的长回帖的回帖!!
QQ图片41.png (14.49 KB, 下载次数: 2)
16:24 上传
这事情居然还可以从遥远的 2月2号 刚下班放假那天开始。
那天,水群里,水果君弄了个论坛的帖子,说让我去回帖,我看了一下,看到一个挺新鲜的东西,觉得有点意思,但看到下面的讨论我就觉得很晕。
当时稀里糊涂在群里和他们胡说八道了一番,废了很多劲才发现问题的关键。
那个帖子,链接如下:
帖子很短,基本都是代码,我烤过来........
void GPIO_DeInit(GPIO_TypeDef* GPIOx)
{
&&/* Check the parameters */
&&assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
&&
&&switch (*(uint32_t*)&GPIOx)
&&{
& & case GPIOA_BASE:
& && &RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);
& && &RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE);
& && &.....
//不明白switch行中GPIOx为什么要取址,GPIOx本来不就是地址么?
#define GPIOA& & ((GPIO_TypeDef*)GPIOA_BASE)
//求解释复制代码对于水果君和我,尽管我们的意见不一致,但其实可以说,我和他,都知道是怎么回事。
只不过,他的逻辑是,反正是一回事,能写多简单是多简单,而我的观点是:不要为了偷懒少敲那几个字母,让别人误会。
尽管我们都很清楚他其实是怎么回事。
没想到这事余孽未消,刚刚突然水群里又来一个类似的问题,这次问得更加没头没脑,直接把我这容易犯懵的大脑弄糊涂了。
绕了一圈睡了一觉后,我想了想,决定好好写个帖子,好好说说这事情
没有一件事情是容易的,所以,起念头时,一定要好好琢磨
在线时间1689 小时
威望23973分
芯币14120枚
TA的帖子TA的资源
首先,从 GPIOx 说起
这是ST库里的经典映射手法。
和PC上的程序不一样,在STM32上,可以通过
*(int *)0x = 34;
在地址为 0x上写入 34 这个内容。
——这里不考虑什么 FLASH RAM之类的问题。
所以,ST库映射寄存器的典型手法就是
比如说 GPIOA的寄存器地址,如果是从 0x开始存放什么 ODR IDR之类的。
因为 结构体成员在内存上也是按序排放的,所以,它就把
ODR IDR等等 寄存器 按顺序 定义成 GPIO 这个结构体。
typedef GPIO
这一部分具体可以去看 stm32fxxx.h,我就不多说了。
最后,GPIOA GPIOB GPIOC都会有一个 GPIOA_Base GPIOB_Base
这个基地址,指的就是 每个port端口 寄存器的 起始地址。ABCDEFGI口各自按顺序排好。
所以只要找到头,再借助这个结构体,就可以直接通过
GPIOA-&ODR这样的写法非常简单直观的 寻知道 GPIOA的ODR地址。
非常形象,非常生动。
而且很简洁,完全的利用了C语法本身的特性。
是以,从我个人的角度看,这是一个非常不错的 映射手法。
这基本也是那天晚上我语无伦次 发语音说的重点。
没有一件事情是容易的,所以,起念头时,一定要好好琢磨
在线时间1689 小时
威望23973分
芯币14120枚
TA的帖子TA的资源
现在,先来回答原来那个帖子的问题。
*(uint32_t*)&GPIOx
这句话到底是什么意思?
其实问题还是在上一个帖子里提到的 GPIOx的定义里
#define GPIOA& & ((GPIO_TypeDef*)GPIOA_BASE)
其实我为什么第一反应会觉得这个东西写的挺新鲜,因为以前我曾小小纠结过如何通过一个函数,让函数自己区分 GPIOA GPIOB这个问题。
而这里提供了一个 非常直接简单的方法:
*(uint32_t*)&GPIOx
对这种较复杂的表达式或者宏,解决的思路很简单,就是一步一步展开。但这个过于简单,而且这个话题也太口水了,我就直接带过去不罗嗦了,罗嗦了你们还以为是我无知大惊小怪......(多怨啊我,我只是一个喜欢 详细解释的好版主)
GPIOx 是传递进来的形参,它的可能值就是 GPIOA GPIOB之类的
((GPIO_TypeDef*)GPIOA_BASE)
GPIOA_BASE是一个数值,代表的是 GPIOA的寄存器的起始地址。
*(uint32_t*)&GPIOx
这个操作,等于,把 GPIOA_BASE 这个最初宏定义的数值,就是说,这是一个常数。
所以这个时候,就可以很方便的使用 switch-case结构了
因为case后面跟的只能是常数,而不能是变量或者其他任何数值。
这就是这个问题的所有答案
没有一件事情是容易的,所以,起念头时,一定要好好琢磨
在线时间1689 小时
威望23973分
芯币14120枚
TA的帖子TA的资源
本帖最后由 辛昕 于
16:56 编辑
水果君在那个帖子里认为,其实这个地方是多此一举,可以直接写成
(uint32)GPIOx
说实在的,这个,和 那个显得很麻烦的写法
*(uint32_t*)&GPIOx
效果确实是一样的。
只是,我强调 后面这种写法,我的理由在于:
看到前者,你不会联想到 GPIOx是一个地址,而看到后者,稍微有点经验的C程序员都马上会领悟到这一点。
这就很重要。
为什么,因为,在类似的环境下,我就会搞懵。
比如说,最开始主楼贴 的那个图。
那是 人民币君发的。
我一开始因为直接联想到 这个放假前的讨论,因此我想都没想,就直接说,这两个效果是一样的。
然而,果真是一样吗?呵呵,那还真不是。
QQ图片201.png (9.69 KB, 下载次数: 1)
16:50 上传
写到这里,我就懵逼了,看出问题了没?
一个是那个数其实是地址值,要去操作那个地址上的内容
另一个,压根就只是一个常数。
这两个操作的出来的结果和影响完全不一样。
虽然这可以解释为看走眼,糊涂,当然你也可以认为我经常犯懵,但是我个人的经验是——
不要盲目自信你不会犯懵。
因为一旦犯懵的时候,你可能要付出两三天或者两三个加班的夜晚去解决问题。
试问值得不值得?
而这也是我和水果君争论的核心所在:
虽然我的写法复杂一点,但是,我觉得我可以很明确的告诉别人这就是一个地址。
正如我发帖子或者在q群里讨论,总是不厌其烦,说的大白菜一样。
而不是假设你和我一样知道一些东西。
这样虽然我可以省事很多,少说很多话,打少很多字,但是却极有可能产生沟通的误解,因为双方很可能
不是建立在相同的已知上。
这也是我为什么非常厌恶和吐槽一些半导体厂商提供的文档的理由。
因为他们说的根本不是人话,不是站在开发者使用者的角度去说事。
似乎他们很希望和你分享他们设计芯片和外设原理一样,却不知道这样把我们搞的是一塌糊涂。
我们只不过想学会如何配置和使用,它们却罗罗嗦嗦说另一个方面的问题。
好了,就此结束。
辛辛,不好意思,今天才看到你们在这里讨论的帖子。回想起我回复的那个帖子,我感觉我的想法太过于稚嫩了,看到你们的回复后又理解了一些。&
没有一件事情是容易的,所以,起念头时,一定要好好琢磨
在线时间1267 小时
威望1461分
芯币4687枚
E金币2506枚
TA的帖子TA的资源
纯净的硅(高级), 积分 1461, 距离下一级还需 539 积分
纯净的硅(高级), 积分 1461, 距离下一级还需 539 积分
本帖最后由 cruelfox 于
18:48 编辑
我差点被你绕晕了。
(uint32) GPIOx&&还是写&&*(uint32_t*)&GPIOx
我倾向于前者,或者C++写 static_cast&uint32_t&(GPIOx)
因为 GPIOx 已经是一个地址了,地址值的比较么,直接当作32位整型(这里隐含32-bit平台前提)比较就是了。写成后面那种形式,这是何苦呢,呃,还要取一个地址……如果参数是寄存器传递的话,地址是哪儿呢?
就好比说有有符号的数要转换成无符号的
是写成 y=x; 呢,还是 y=(unsigned int)x; 呢,还是 y=*(unsigned int*)&x; 呢?
除了第一个写法会有编译警告,都是一样的效果。
在线时间1116 小时
芯币7810枚
E金币335枚
TA的帖子TA的资源
感谢版主非常详细的解释了这个问题,以前看32的时候还真没有认真注意这个细节的地方,有时候人真的会“自以为是”,很多东西都觉得懂了,其实还是似懂非懂,在往里问一点就搞不清楚。也确实说明我们应该认真细心的学,脚踏实地一个一个搞清楚才是正确的学习方法。
在线时间4019 小时
威望6900分
芯币14198枚
E金币405枚
TA的帖子TA的资源
我来对号入座了,我就是文中提到的水果君。
首先来讨论一个我认为很有意思的问题,就是这两个强制类型转换:
*(uint32_t*)&AAA 是否等价于 (uint32_t)AAA ?(假设我们不知道AAA的类型,变量还是常量)
为了便于讨论,我们假设变量uint32_t X=*(uint32_t*)&AAA, Y=(uint32_t)AAA;
乍一看,好像是有点等价的意思,但是仔细想想,又不是那么回事,这还取决于AAA的类型。
(1).现在假设AAA是2字节short型=0x1234;
那么X的结果是强制从AAA的地址中取走4字节,其中2字节未知:
X=0xXXXX1234 (小端情况下)
Y的结果就比较确定,编译器帮他把高位填0, Y=0x;
(2).假设AAA是64位long long类型=0x1234;前面的0我就不写了。
那么X还是取走4个字节,根据大小端而异,可能是高4字节,也可能是低四字节。
Y只是简单的舍弃了高四字节,结果比较确定。
(3). 假设AAA是个数组,这个情况比较特殊,数组名本身就是数组的首地址,取地址后还是相同的值:
因此X会取出数组中的元素
而Y却还是一个地址值。
(4). 一个不靠谱的假设AAA是个结构体
那么X可以取到结构体的成员
而Y的写法就直接报错了,不允许强制类型转换。
(5). AAA是uint32_t类型,那么没什么问题,X与Y等价。
由此可见:
X写法确实是无条件强制转换,基本是无所不能转,但是如果类型不匹配就很容出错了。
Y写法是有限制的编译器参与的半智能转换,因为编译器知道源类型与目标类型,会帮忙参与转换,或者类型转换不太靠谱的话,直接报错。
由此可以得出结论,在使用强制类型转换的时候,必须具有可行性,同时也必须清楚转换后的结果,也就是说,程序员(写程序的人)必须清清楚楚地知道源类型和目标类型到底是什么,否则还是去读书深造的好。
现在我来说说为什么我觉得uint32_t X=*(uint32_t*)&GPIOx有脱裤子放屁的嫌疑(从阅读程序的角度来说)。
首先有个变量GPIOx,是个指针,也就是个地址1,此地址上面存放的类型是GPIO_TypeDef。
然后对这个地址1取了个地址2,那么这个地址2的类型是GPIO_TypeDef **
现在对地址2进行强制类型转换,转成uint32_t*,也就是间接说明,不再把地址1当做地址(指针)看待,而是作为一个uint32_t类型。
然后在地址2中的uint32_t数据取出来,完毕。牛逼的程序员也看出来了,这就是拐外抹角的把GPIOx转成uint32_t类型。
一般刚入门的程序员看了会不会很懵逼?
好,说的有点乱,我们按教主的思路重新捋一下:
我们假设不知道GPIOx到底是个什么东西,就当做是一个不知道类型的普通变量。
引用:“——————————————————————————————————
水果君在那个帖子里认为,其实这个地方是多此一举,可以直接写成
(uint32)GPIOx
说实在的,这个,和 那个显得很麻烦的写法
*(uint32_t*)&GPIOx
效果确实是一样的。
只是,我强调 后面这种写法,我的理由在于:
看到前者,你不会联想到 GPIOx是一个地址,而看到后者,稍微有点经验的C程序员都马上会领悟到这一点。
————————————————————————————————引用结束”
看看我对脱裤子的理解:
首先一个变量GPIOx,不知道其类型
然后对此变量取了个地址,此地址类型也未知。
然后对这个地址进行强制转换成uint32_t类型的一个地址(此处影射GPIOx是个uint32_t类型)
最后,从这个地址中取出了一个uint32_t类型的变量,完成了最终这个语句的使命。
这样理解,也根本看不出GPIOx有地址的意思(只是明确了变量的地址是个具体类型的地址)。只是拐了个弯,把GPIOx强制转成uint32_t类型而已。
然而,把一个地址(指针)转成一个整形数,就很常见不过了。uint32_t Y=(uint32_t)GPIOx。
由此,可以看到两个转换的最终区别:脱裤子那种,是强制转换的变量地址的类型,间接对数据类型进行转换,而直接转换就是直接对变量进行转换。
看到你回这么长的贴,我也是挺感动的,然而很不好意思的告诉你。
虽然你没错,但我还是要比你更正确......
很简单,看好了。
在32位机器下,你是对的,你还是更简洁的。
然而如果这种写法,在16位机或者64位&
如果没有记错的话,您应是Super哥(老是在水军群改名字,我也挤不太清楚了)。看到你们的回复,我对我之前在那个帖子中稚嫩的回复感到惭愧。你们的回复,又让我理解深入了。感谢。&
<p id="rate_508" onmouseover="showTip(this)" tip="很给力!&威望 + 8 分
芯币 + 8 枚
" class="mtn mbn">
EEWORLD开发板置换群:,——电工们免费装β的天堂,商家勿入!加群暗号:喵
————————————————————————
少开箱,少点灯,少搭开发环境,如果你只会这些,对不起,我不认识你
在线时间425 小时
E金币336枚
TA的帖子TA的资源
纯净的硅(初级), 积分 550, 距离下一级还需 250 积分
纯净的硅(初级), 积分 550, 距离下一级还需 250 积分
小虾米来此一游,哈哈,两只大虾的贴子我来看看噢
我是一头搞电子的猪,猪是一种好色的动物,猪八戒就是代表. &&&&&&
在线时间3509 小时
威望3966分
芯币25150枚
E金币534枚
TA的帖子TA的资源
听君一席话胜读十年书
在线时间389 小时
芯币1013枚
TA的帖子TA的资源
一粒金砂(中级), 积分 14, 距离下一级还需 186 积分
一粒金砂(中级), 积分 14, 距离下一级还需 186 积分
在线时间1418 小时
威望6091分
芯币3706枚
E金币102枚
TA的帖子TA的资源
五彩晶圆(高级), 积分 6091, 距离下一级还需 3909 积分
五彩晶圆(高级), 积分 6091, 距离下一级还需 3909 积分
水果君在那个帖子里认为,其实这个地方是多此一举,可以直接写成
(uint32)GPIOx
说实在的,这个, ...
辛辛,不好意思,今天才看到你们在这里讨论的帖子。回想起我回复的那个帖子,我感觉我的想法太过于稚嫩了,看到你们的回复后又理解了一些。
在线时间1418 小时
威望6091分
芯币3706枚
E金币102枚
TA的帖子TA的资源
五彩晶圆(高级), 积分 6091, 距离下一级还需 3909 积分
五彩晶圆(高级), 积分 6091, 距离下一级还需 3909 积分
我来对号入座了,我就是文中提到的水果君。
首先来讨论一个我认为很有意思的问题,就是这两个强制类型转换 ...
如果没有记错的话,您应是Super哥(老是在水军群改名字,我也挤不太清楚了)。看到你们的回复,我对我之前在那个帖子中稚嫩的回复感到惭愧。你们的回复,又让我理解深入了。感谢。
然而我不得不悲伤地说,其实我是对的,水果君是错的。
请稍等,我更新主题帖&
在线时间1689 小时
威望23973分
芯币14120枚
TA的帖子TA的资源
如果没有记错的话,您应是Super哥(老是在水军群改名字,我也挤不太清楚了)。看到你们的回复,我对我之 ...
然而我不得不悲伤地说,其实我是对的,水果君是错的。
请稍等,我更新主题帖
没有一件事情是容易的,所以,起念头时,一定要好好琢磨
在线时间1689 小时
威望23973分
芯币14120枚
TA的帖子TA的资源
我来对号入座了,我就是文中提到的水果君。
首先来讨论一个我认为很有意思的问题,就是这两个强制类型转换 ...
看到你回这么长的贴,我也是挺感动的,然而很不好意思的告诉你。
虽然你没错,但我还是要比你更正确......
很简单,看好了。
在32位机器下,你是对的,你还是更简洁的。
然而如果这种写法,在16位机或者64位机 等非32位机下就会出错。
很简单,,非32位机的 地址非4字节,而是 16位机的2字节,64位机的8字节。
这种情况下,对应的指针字长也就成了 2字节 8字节。
于是结果已经很明显。
你每次都uint32去强转地址,问题是,你强转的是一个地址.......那也就是说。
对16位机,你多转了后面未知的2字节,对64位机,你少转了后面需要的4字节。
所以,必然是错的。
而原来那种看起来复杂的写法呢?
木有错,为毛?
因为,,uint32_t * 也是一个指针,或者地址(指针或地址随你叫吧)
因为在同一机器下,任何类型指针的字长都是一样的。
所以这种情况下,我读到的地址值永远不会少或者多。
这个问题意味着。
在你的写法里,你需要去假设指针字长,比如uint32,但这永远只能对一种机器字长适应。
而那个复杂的写法,则无此需求,不需要作任何假设,也就不会受限于任何机器字长的限制。
事实上,我写成
*(uint8_t *)
*(uint16_t *)
都木有任何关系
很显然,@[at]辛昕[/at](别名教主)对我的反驳是很无力的
在@[at]freebsder[/at]叔叔的蛊惑下,一直在找我的漏洞,我也觉得代码这东西没有绝对的对与错,虽然那种写法看起来很复杂并且高大上,一个语句展现了好几&
没有一件事情是容易的,所以,起念头时,一定要好好琢磨
在线时间130 小时
芯币2045枚
TA的帖子TA的资源
一粒金砂(高级), 积分 218, 距离下一级还需 282 积分
一粒金砂(高级), 积分 218, 距离下一级还需 282 积分
(uint32) GPIOx&&还是&&*(uint32_t*)&GPIOx
如果GPIOx是形参,无论哪种写法,得出的汇编都一样,都是直接取R0,
如果GPIOx 是全局变量,汇编结果也是一样,都是取GPIOx变量的内容
如果GPIOx变量存放到0x,直接取0x里面的内容
编译器非常聪明,认为对指针变量X取地址A再取A里面的内容和直接取X里面的内容是一样的!
虽然效果一样,但是明显给阅读程序带来了困难,一般人看到这个表达式都要思考一下才敢下决定。
如我在7楼所说,如果换一种类型,例如:
(uint16_t) GPIOx
*(uint16_t*)&GPIOx 未必一样,或许在小端机器上同&
在线时间4019 小时
威望6900分
芯币14198枚
E金币405枚
TA的帖子TA的资源
(uint32) GPIOx&&还是&&*(uint32_t*)&GPIOx
如果GPIOx是形参,无论哪种写法,得出的汇编都一样,都是直接取R ...
虽然效果一样,但是明显给阅读程序带来了困难,一般人看到这个表达式都要思考一下才敢下决定。
如我在7楼所说,如果换一种类型,例如:
(uint16_t) GPIOx&&和&&*(uint16_t*)&GPIOx 未必一样,或许在小端机器上同样被优化,但是大端机器上肯定就不同了。
EEWORLD开发板置换群:,——电工们免费装β的天堂,商家勿入!加群暗号:喵
————————————————————————
少开箱,少点灯,少搭开发环境,如果你只会这些,对不起,我不认识你
在线时间4019 小时
威望6900分
芯币14198枚
E金币405枚
TA的帖子TA的资源
看到你回这么长的贴,我也是挺感动的,然而很不好意思的告诉你。
虽然你没错,但我还是要比你更正确.... ...
很显然,@辛昕(别名教主)对我的反驳是很无力的
在@叔叔的蛊惑下,一直在找我的漏洞,我也觉得代码这东西没有绝对的对与错,虽然那种写法看起来很复杂并且高大上,一个语句展现了好几个C语言的知识点,而且结果正确,一点毛病没有,只是让人读起来需要有个停顿思考的时间。
C语言在程序移植这里确实存在许多诟病,在不同硬件平台上,数据类型的长度并不统一。
例如通常int在16位机为2字节,32位机为4字节,指针也一样,根据机型有2字节,4字节或者8字节的长度,记得还有3字节的……因为硬件平台种类实在是太多了,五花八门。
为了应付这类问题,C99标准出台了更具体的类型,如int16_t,uint32_t这样的具体长度类型,使程序在不同硬件平台更容易移植。但是……。
遗憾的是,这些类型中没有指针,我觉得因为指针也没法具体化。因此,教主提出了他的问题:在不同平台上如何用整型来表示指针?
其实这问题的根源完全来自于switch语句,因为在switch中只能使用整型数据类型,不可以是指针,如果非要去比较指针,那么只能转成整型。因此,如果把指针转为整型成了讨论的重点,但是很明显,教主的结论是错误的,他的写法并不能实现他要的结果。
大家都应该知道,指针是有类型的,解引用的时候会得到相应的类型:
*(uint32_t*)xxx&&结果将是uint32_t
*(int16_t*)xxx 结果就是int16_t
根本得不到他所想要的与平台相关的数据类型。
因此在C语言中,想要得到指针所对应的整型类型,只能通过手动指定,例如微软就是这么干的
#ifdef _WIN64
& & typedef __int64& && && & intptr_t;
& & typedef int& && && && &&&intptr_t;
这样intptr_t就可以确保能保存指针类型。
但是可惜这只是某些厂家这么干,ST的库中并没有这样的类型,否则这事就好办了(当然了,ST目前可能也没考虑推出64位的单片机)
我不知道*(uint32_t*)&GPIOx这样的代码是否是出自ST的标准库,我没有去考证,如果真这样写的话他们自己可能也看着别扭,所以我看到st的某个版本库里面看到的是直接比较指针,当然了,就不能使用switch语句了,而是if语句,像这样:
if (GPIOx == GPIOA) xxx_statement 。反正我觉得这样写是最直观最易读的了,给他们点个赞!
c语言的争议太多了,就像#define与typedef之争,#define与const之争,程序员的理论就是运行结果没错那就都不是大问题,不说了,累,继续搬砖了。
一直以为int16_t,uint32_t这种数据类型是程序员typedef才有的。原来编译器原本就认识啊!学习了!&
别闹了,跟我回家。
完全暴露出和我半斤八两的水平,咱跑吧,别在这丢人了。
这帖子接下来的时间交给 free叔和samos
我下次一定好好学反汇编..........&
EEWORLD开发板置换群:,——电工们免费装β的天堂,商家勿入!加群暗号:喵
————————————————————————
少开箱,少点灯,少搭开发环境,如果你只会这些,对不起,我不认识你
在线时间4019 小时
威望6900分
芯币14198枚
E金币405枚
TA的帖子TA的资源
忘了总结了:
虽然看似老婆都是别人家的好,但是代码并不是别人写的就一定好,即使你是一个新手,也不要随便拿来主义随便借鉴,包括我写的代码,很多都比较烂,写的并不严谨,只是为了应付能用就行(能保证在我的应用环境中不出错就行),因为把代码写完美确实是一件很不容易的事,很费时间和精力。
不要怂,你其实适合干工程............
虽然我现在也随便很多了..............&
EEWORLD开发板置换群:,——电工们免费装β的天堂,商家勿入!加群暗号:喵
————————————————————————
少开箱,少点灯,少搭开发环境,如果你只会这些,对不起,我不认识你
在线时间130 小时
芯币2045枚
TA的帖子TA的资源
一粒金砂(高级), 积分 218, 距离下一级还需 282 积分
一粒金砂(高级), 积分 218, 距离下一级还需 282 积分
本帖最后由 samos2011 于
14:40 编辑
有以下代码:
void GPIO_DeInit1(GPIO4_TypeDef* GPIOx) {
& && &&&xx = (char)GPIOx;
}
void GPIO_DeInit2(GPIO4_TypeDef* GPIOx) {
& && &&&xx = *(char*)&GPIOx;
}复制代码
在32位机测试结果如下:(ARMCC编译器,优化级别-O0,-O1,-O2,-O3都一样)
xx = (char)GPIOx;
0x9& && &LDR& && &r1,[pc,#100]&&; @0x
0x08& && &STRB& &&&r0,[r1,#0x00]复制代码
前者虽然效果非常好,但编译器给出警告: warning:&&#767-D: conversion from pointer to smaller integer
xx = *(char*)&GPIOx;
0x1000055E B501& && &PUSH& &&&{r0,lr}
0x8& && &MOV& && &r0,sp
0x7& && &LDR& && &r1,[pc,#92]&&; @0x
0x0& && &LDRB& &&&r0,[r0,#0x00]
0x8& && &STRB& &&&r0,[r1,#0x00]
0x BD08& && &POP& && &{r3,pc}复制代码
最终结果还是一样
当把char修改为int型,编译器才能对这句xx = *(char*)&GPIOx优化
xx = (int)GPIOx;
0x9& && &LDR& && &r1,[pc,#100]&&; @0x1000057C
0x8& && &STR& && &r0,[r1,#0x04]复制代码
xx = *(int*)&GPIOx;
0x17& && &LDR& && &r1,[pc,#92]&&; @0x1000057C
0x48& && &STR& && &r0,[r1,#0x04]复制代码
对于这个编译器警告,我猜想,编译器认为不应该把指针变量(即内存地址)强制转换为小于这个地址宽度的值,地址就应该当地址用,不要破坏地址
通过你们的争论,让我对这两个写法产生了好奇,至于用那种,没有警告没有错误就行!
在线时间1689 小时
威望23973分
芯币14120枚
TA的帖子TA的资源
很显然,@辛昕(别名教主)对我的反驳是很无力的
在@freebsder叔叔的蛊惑下,一直在找我的漏洞,我也觉 ...
别闹了,跟我回家。
完全暴露出和我半斤八两的水平,咱跑吧,别在这丢人了。
这帖子接下来的时间交给 free叔和samos
我下次一定好好学反汇编..........
我们都不是研究编译器的,也没有在那个编译器手册中看到这方面的规定
在32位机下 xx = *(long long*)&GPIOx; 同样给出警告
warning: C4487E: read from variable 'GPIOx' with offset out of bounds
也许ARMCC默认&
没有一件事情是容易的,所以,起念头时,一定要好好琢磨
论坛测评队员
EEWORLD 官方微信
Powered by

我要回帖

更多关于 java unsigned long 的文章

 

随机推荐