c語言變量強制轉換,C語言——“=”中的強制類型轉換

前言:在寫程序時候遇到了一些關于數據類型轉換的問題,編譯器也沒有報錯,運行時才發現數據不對,找bug花費了很多時間,但最終也發現是一些細節上的問題,特地在這里整理出一篇文章記錄。

實驗環境:

芯片架構:Cortex-M0+

開發IDE:Keil_v5

編譯器:armcc

問題代碼:

uint64_t TempData2;

uint8_t KeyeBuf1[8];

TempData2 = ( KeyeBuf1[0] + (KeyeBuf1[1] << 8) + (KeyeBuf1[2] << 16) + (KeyeBuf1[3] << 24)+

(KeyeBuf1[4] << 32) + (KeyeBuf1[5] << 40) + (KeyeBuf1[6] << 48));

在上述代碼中,先前已經聲明了TempData2的數據類型為無符號64位整型類型,在接下來的移位后累加數據總是出現差錯,檢查累加后數據范圍也沒有超過無符號64位整型數據范圍。

問題分析:

經過一系列的排查,最終發現了問題所在,主要是以下三方面造成的影響:

1.機器平臺與編譯器的影響

stdint.h是C99中引進的一個標準C庫的文件,目前大部分單片機的C編譯器均支持。關于編譯器支的更多數據類型完全可以在該文件中找到。以armcc編譯器為例,文件中,對于8位,16位,32位,64位無符號整數類型的數據定義為如下:

#include

uint64_t TempData2;

typedef unsigned char uint8_t;

typedef unsigned short int uint16_t;

typedef unsigned int uint32_t;

typedef unsigned __INT64 uint64_t;

查找該文件可得uint64_t的類型是unsigned __INT64類型,__INT64類型的解釋與機器平臺和編譯器相關。

機器平臺的硬件架構以及編譯器的編譯最終都會影響執行代碼的生成。Cortex-M0+是32位的處理器,內部的寄存器大多都是32位,這就導致了在默認情況下進行的運算,不管是8位,16位,32位都在32位寄存器中運算。

2.“=”符號運算順序的影響

=符號的執行過程細分下來可以分成兩步:

計算=右邊部分得出最終結果

最后把結果賦給=左邊變量

由于上述的運算順序導致,=左邊變量不管原先定位為多少位,對先執行的=右邊計算過程沒有影響,也就是說,在上述代碼過程中,即使左邊變量先定義為64位,在先進行右邊部分計算時,還是按照右邊部分數據最大的數據類型來數據對齊,而后進行計算。

3.移位程序移植性的影響

對于移位程序來說,右移數據基本不會出太大問題,但是左移就需要注意很多。在32位機器平臺上,8位,16位,32位數據類型都會在32位寄存器中進行移位,只要我們確保移位后的數據不會超過32位數據類型,那么程序就會正常運行。而上述數據類型一旦移位后的數據類型超過32位,那么處理器會丟失左移向前進的數據,留下最低的32位。

問題解決:

對于上述代碼進行分析,( KeyeBuf1[0] + (KeyeBuf1[1] << 8) + (KeyeBuf1[2] << 16) + (KeyeBuf1[3] << 24)+ (KeyeBuf1[4] << 32) + (KeyeBuf1[5] << 40) + (KeyeBuf1[6] << 48));中的Keye1數組數據類型都是8位,計算時都在32位寄存器中計算。前幾個數據的移位沒有超過32位數據類型不會出太大錯誤,從(KeyeBuf1[4] << 32)起,理論上移位后的數據超過了32位,只留下最低32位,導致數據出錯。即使最后賦給了一個64位的變量,也是將一個32位數據賦給64位,而這些問題在編譯時期編譯器并不會指出,需要我們自己多加注意。

最后的解決方法是將KeyeBuf1數據在運算時強制轉換為64位數據類型,這樣進行運算時都是64位數據對齊,最后賦給一個64位數據類型,就不會出現數據丟失的情況了。代碼如下:

TempData2 = ( KeyeBuf1[0] + (KeyeBuf1[1] << 8) + (KeyeBuf1[2] << 16) + ((uint64_t)KeyeBuf1[3] << 24)+

((uint64_t)KeyeBuf1[4] << 32) + ((uint64_t)KeyeBuf1[5] << 40) + ((uint64_t)KeyeBuf1[6] << 48));

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536581.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536581.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536581.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring框架IOC和AOP的實現原理(概念)

IoC&#xff08;Inversion of Control&#xff09; (1). IoC&#xff08;Inversion of Control&#xff09;是指容器控制程序對象之間的關系&#xff0c;而不是傳統實現中&#xff0c;由程序代碼直接操控。控制權由應用代碼中轉到了外部容器&#xff0c;控制權的轉移是所謂反…

面向視頻的全新AI架構 —— 阿里云智能視覺技術全解

2019獨角獸企業重金招聘Python工程師標準>>> 我們都知道&#xff0c;AI技術正在以可見的速度被應用于各行各業&#xff0c;然而絕大部分業務場景想應用AI技術&#xff0c;都需要算法工程師根據自身業務的標注數據&#xff0c;來進行單獨訓練&#xff0c;才能打磨出合…

c語言鞏固,鞏固一下C語言中的指針

寫了幾段代碼&#xff0c;再鞏固一下C語言知識。我的記憶方法跟文章中的不一樣。*是取值符號&#xff0c;&取地址符號&#xff0c;()限定子表達式的符號,[]是按索引取數組乘員的符號。優先級方面()>[]>*,&。對于int *(*p(int))[3]; 。我是這么分析的&#xff1a;…

c語言程序設計課程設計學生信息管理系統,C語言程序設計課程設計報告----學生信息管理系統.doc...

河南理工大學計算機學院《C語言程序設計》課程設計報告題目&#xff1a; 學生信息管理系統專業&#xff1a; 計算機科學與技術班級&#xff1a; 計算機XX班學號&#xff1a; 311009033232姓名&#xff1a; *****日期&#xff1a;2012年3月21日1.2意義熟悉C語言程序的編程環境、…

【轉】利用python的KMeans和PCA包實現聚類算法

轉自&#xff1a;https://www.cnblogs.com/yjd_hycf_space/p/7094005.html 題目&#xff1a; 通過給出的駕駛員行為數據&#xff08;trip.csv&#xff09;&#xff0c;對駕駛員不同時段的駕駛類型進行聚類,聚成普通駕駛類型&#xff0c;激進類型和超冷靜型3類 。 利用Python的s…

c 語言str.size,C/C++ strlen(str)和str.length()和str.size()的區別

strlen(str)和str.length()和str.size()都可以求字符串長度,返回字符串中字符的長度&#xff0c;不包括‘/0’。其中str.length()和str.size()是同義詞&#xff0c;返回同樣的值。strlen(str)是用于求字符數組的長度&#xff0c;其參數是char*。#include #include using namesp…

想跑次高頻策略?快來看看Numpy處理真格量化tick數據的技巧

使用澎博真格量化時&#xff0c;很多用戶希望用numpy處理tick數據&#xff0c;包括tick數據的留存和運算。 這里有一些技巧。 因為tick數據量比較大&#xff0c;為了降低系統的運算負擔&#xff0c;我們不應該在內存里保存大量tick數據。 比如我們只想保存過去10個tick。 可以在…

if語句寫階躍函數C語言,C語言第四章分支語句.ppt

C語言第四章分支語句.ppt例&#xff1a; 輸入三個實數&#xff0c;按從小到大的順序輸出。 main( ) {float a,b,c,t; scanf(“%f,%f,%f ”,&a,&b,&c); if (a>b) { ta; ab; bt; } if (a>c) { ta; ac; ct; } if (b>c) { tb; bc; ct; } printf(“%5.2f,%5.2f…

日本顯示屏巨頭JDI不敵業務壓力,宣布接受中方注資...

本次10億美元的融資金額中&#xff0c;其中7.2億美元據傳來自中國絲綢之路基金。 最初&#xff0c;在液晶領域日本企業一直都占據著主要市場&#xff0c;如夏普、NEC、東芝等。后來隨著韓國三星、LG的強勢進入&#xff0c;日本企業的生存空間開始被搶占&#xff0c;現如今中國…

c語言中 d 1是啥意思,空開D/C是什么意思?終于有人把它說清楚了!

原標題&#xff1a;空開D/C是什么意思&#xff1f;終于有人把它說清楚了&#xff01;空氣開關是每個人家里必用的東西&#xff0c;但是你到五金店一看&#xff0c;大大小小的開關插座多了去&#xff0c;讓人眼花繚亂。怎么選呢&#xff1f;空開有各種字母型號&#xff0c;這些字…

微信小程序開發 | 官方問答精選

2019獨角獸企業重金招聘Python工程師標準>>> SF問答精選《七》 多組件顯示與隱藏如何實現、function中的...SF問答精選《六》canvas不顯示問題SF問答精選《五》菜單內容左右聯動、生命周期函數SF問答精選《四》eslint 配置使用 co function&#xff1b;apache 反向代…

36歲自學C語言,C語言的數據類型

在C語言中&#xff0c;數據類型可以分為&#xff1a;基本數據類型&#xff0c;構造數據類型&#xff0c;指針類型&#xff0c;空類型四大類。基本數據類型基本數據類型最主要的特點是&#xff0c;其值不可以再分解為其他類型。也就是說&#xff0c;基本數據類型是自我說明。構造…

清北學堂培訓2019.4.4

第一次培訓&#xff0c;心情有點激動&#xff08;盡管沒了清明節&#xff09;&#xff0c;還見到了各地的dalao們&#xff0c;十分開森 Day 1&#xff08;李昊dalao&#xff09; 上午篇 上午呢&#xff0c;主要講了關于高精&#xff0c;快速冪&#xff0c;膜模意義下的運算&…

國二c語言作弊用u盤,計算機等級考試可以插u盤嗎(全國計算機等級考試報名系統官網)...

&#xff1a;不可以 會有嘀嘀嘀的報警聲的&#xff1a;我以前考時不讓帶的&#xff0c;人家讓你不能用優盤的話電腦會控制沒法用的。&#xff1a;首先肯定回你&#xff0c;不可以帶優盤或者其他作弊設備。很多計算機二級考點會把主機箱鎖死&#xff0c;根本插不了優盤。在你進入…

「SCOI2011」棘手的操作

傳送門 Description 有\(N\)個節點&#xff0c;標號從\(1\)到\(N\)&#xff0c;這\(N\)個節點一開始相互不連通。第$ i\(個節點的初始權值為\)a_i$ &#xff0c;接下來有如下一些操作&#xff1a; U x y 加一條邊&#xff0c;連接第 \(x\) 個節點和第\(y\) 個節點。 A1 x v 將…

swft c 語言 數組,如何在swift中實現數組的深拷貝

在Objective-C中如果想將一個數組賦值給另外一個數組&#xff0c;同時想讓兩個數組之間相互獨立(即改變其中的一個數組&#xff0c;不影響另外的一個)&#xff0c;有很多的辦法&#xff0c;比如我們可以直接copy,用類方法創建新數組。這樣得到的數組和原來的數組就是兩個完全獨…

tomcat CATALINA_HOME與CATALINA_BASE的區別

區別 https://blog.csdn.net/cfydaniel/article/details/41351927 Tomcat啟動分析(我們為什么要配置CATALINA_HOME環境變量&#xff09; http://www.cnblogs.com/heshan664754022/archive/2013/03/27/2984357.html轉載于:https://www.cnblogs.com/Andrew520/p/10664921.html

android 廣告欄效果,實現android廣告欄效果

public classBannerLayout extendsRelativeLayout {privateViewPager mViewPager; // 輪播容器// 指示器(圓點)容器privateLinearLayout indicatorContainer;privateDrawable unSelectedDrawable;privateDrawable selectedDrawable;private intWHAT_AUTO_PLAY 1000;private boo…

自我練習

<!doctype html><html><head><meta charset"utf-8"><title>無標題文檔</title><link rel"icon" href"../HTMLWork/day03/psb.ico.ico" type"img/*"></head><body> <a na…

android studio按鈕槽函數,AndroidStudio按鈕Button退出程序

AndroidStudio 3.1.41.創建一個新的項目&#xff0c;項目名稱為Button&#xff0c;界面為activity_button.xml2.打開activity_button.xml3.點擊HelloWorld標簽&#xff0c;按Delete刪除4.左側組件欄選擇Common - Button5.將Button組件拖到界面上&#xff0c;大概中間的位置6.右…