void相關的無型別變數在使用時必須強制資料型別轉換問題。
- const char str[] = "CredO~";
- unsigned int int32 = 0x80;
- char ch = '?';
- void *args[] = {(void*)str,(void*)&int32,(void*)&ch};
- ...........這裡省略一步將args強制轉換成char * 型的過程...........
- putnum((unsigned int)*args[1]);/*putnum就是一個輸出值的封裝*/
今晚上我的同學要我看個程式碼,說無法解決,讓我看下。具體問題就在上面的程式碼。
問題描述:int32 = 0x11時,程式碼執行正確,但測試int32 = 0xaa;就是錯誤的,輸出結果很奇怪,在資料前面填充了資料,變成了0xffffffaa。
我拿到程式碼看了好一會,並除錯運行了下,發現確實是這樣的。只要資料最高位為“1”輸出就是錯誤的,也就是和最高位有關係。最高位一般只表示符號位,但現在是無符號變數,這就有點難以理解了。
判斷:由於不存在語法錯誤,指標的使用也沒有問題,那就只能是資料型別的問題了。
嘗試一: 將變數從無符號改為有符號,錯誤依舊,額~~~
嘗試二:在指標取值前先進行強制型別轉換。
- *(unsigned int *)args[1])
嘗試是正確的,也就是說和指標變數的型別有關,在使用時必須將void * 型指標變數轉換成一個有具體(並且是正確的)資料長度的型別。
雖然解決方法有了,但是原因還不明確,只能反彙編看看了
- /*原始的方式*/
- q = *args[1];
- 401460: 0f be 00 movsx eaxBYTE PTR [eax]
- /* p = *(unsigned int*)args[1];*/
- putnum((unsigned int)q);
- 401463: 89 04 24 mov DWORD PTR [esp],eax
- 401466: e8 f5 fe ff ff call 401360 <putnum>
- 40146b: e9 70 ff ff ff jmp 4013e0 <ezprintf+0x10>
- /*強制轉換後的方式*/
- /* q = *args[1];*/
- p = *(unsigned int*)args[1];
- 401460: 8b 00 mov eax,DWORD PTR [eax]
- E:/C/new 2.c:53
- putnum((unsigned int)p);
- 401462: 89 04 24 mov DWORD PTR [esp],eax
- 401465: e8 f6 fe ff ff call 401360 <putnum>
從加紅的結果很明顯能夠看出,問題在於:沒有進行正確的資料型別轉換,void * 轉換成 char *(正確的轉換型別應該是int *);所以當一開始的資料的最高位為1(單位元組的第7位,例如:b000000001xxxxxxx)時,就被當做符號位進行了符號位擴充套件,出現輸出資料前面被填充的現象(變為:b111111111xxxxxxx)。
結論:void型相關變數,在具體使用(和值相關)時必須進行型別強制轉換(並且是要正確的,符合邏輯的),以明確變數的資料長度,否則出現錯誤:
1、無法編譯通過(資料型別不匹配);
2、得到錯誤的資料(邏輯上有問題)。
2014.3.23
說明:在原來的帖子中,我說的是由於void * 沒有經行型別強制轉換,編譯器預設為 char *,這是一個很大的錯誤。在這裡指出說明(這個轉換是在其他程式碼中有動作)。出現問題的現象,是由於強制型別轉換的不合理,原變數是int 型,而在使用時資料被轉換成char 型,所以出現錯誤。
新編輯帖子中藍色部分是修正後的,有些錯誤的已經被刪除。這裡特別感謝老九,發現了這個錯誤。
相關推薦
void相關的無型別變數在使用時必須強制資料型別轉換問題。
const char str[] = "CredO~";unsigned int int32 = 0x80;char ch = '?';void *args[] = {(void*)str,(void*)&int32,(void*)&ch};...........這裡省略一步將args強制轉換
hibernate實體類構造方法內含有Timestamp型別變數時"Unable to locate approprite constructor"錯誤解決方法
在使用hibernate時,有時想獲取部分欄位的結果集,可以用如下方法: 可以在hql中使用select new 包名.類名(屬性1,屬性2,....) from 實體類,同時要在實體類中新增帶參的
【Objective-C學習筆記】變數和基本的資料型別
OC是增強了C的特性,所以在變數和基本資料型別上基本與C一致。 在OC中變數命名有如下規則: 由字母、數字、下劃線、$符號組成 必須以字母、下劃線、$符號開頭 大小寫敏感 在OC中定義變數的時候不能使用OC的保留字,OC的保留字如下: OC中有如下基本資料型別: in
Python入門學習:1.變數和簡單的資料型別
python入門學習:1.變數和簡單的資料型別 關鍵點:變數、字串、數字 1.1 變數的命名和使用1.2 字串1.3 數字1.4 註釋 1.1 變數的命名和使用 變數,顧名思義是一個可變的量,每個變數都儲存一個值--與變數關聯的資訊。 1message =
變數,input()方法,註釋,資料型別,if的用法
一.python是弱型別解釋性語言(沒有強制規定的型別) 1.直譯器種類: CPthon(官方推薦)c語言實現的 PYPY: 把python程式一次性進行編譯 2. idea.lanyus.com 破解JetBrains全家桶 . 二.變數的命名規則 &
變數與常量、資料型別、進位制轉換
資料在記憶體中的儲存方式【瞭解】 儲存資料的單位 在計算機中,最小的操作單位是 位元組 byte 1byte = 8bit 一個位元組對應8個二進位制位 1024byte = 1kb 1024kb = 1mb 1024mb = 1gb 1024gb =
javascript的強制資料型別轉換
強制資料型別轉換主要有三種: 將其它的資料型別轉換為字串 String 將其它的資料型別轉換為數值 Number 將其它的資料型別轉換為布林值 Boolean 1、將其它的資料型別轉換為Str
匿名塊、變數和簡單的資料型別
1.匿名塊的編寫 塊的結構和變數的宣告 declare 變數宣告部分; begin 邏輯處理執行部分; end; / 便於維護(模組化的SQL) 提高資料庫的安全性(把SQL原子操作封裝起來了,更安全) 提高效能(第一次建立物件的時候,資料庫儲存的
Python小白學習之路(八)—【變數】【基本資料型別分類】【集合】【集合的功能】
一、變數 變數的作用:記錄狀態的變化變數的值:描述不同的狀態 二、五大基本資料型別的分類 五大基本資料型別(數字 字串 列表 元祖 字典) 按照可變不可變來進行分類 可變:列表、字典 不可變:字串、數字、元祖 我個人理解,所謂可變,是指當修改內容是,內容改變,地址不變。(即新修改的內容可以覆蓋之
小端模式與強制資料型別轉換
當運算元的型別不同,而且不屬於基本資料型別時,經常需要強制型別轉換,將運算元轉化為所需要的型別。強制型別轉換具有兩種形式,稱為顯式強制轉換和隱式強制型別轉換。4.1.顯式強制型別轉換 顯式強制型別轉換需要使用強制型別轉換運算子,格式如下: type(<expressio
萌新向Python資料分析及資料探勘 第一章 Python基礎 第一節 python安裝以及環境搭建 第二節 變數和簡單的資料型別
本文將參考《Python程式設計 從入門到實踐》的講述順序和例子,加上自己的理解,讓大家快速瞭解Python的基礎用法,並將拓展內容的連結新增在相關內容之後,方便大家閱讀。 好了!我們開始第一章的學習。 第一章 Python基礎 第一節 Python安裝以及環境搭建 Python
變數的八種資料型別------06
目錄 一. PHP變數型別-布林型別 二: PHP標量型別-整型 三. PHP標量型別-浮點型 四: PHP標量型別-字串型 五: PHP特殊型別-資源 六: PHP特殊型別-空型別(NULL) 七: 複合型別-陣列 八: 複合型別-物件 一.
強制資料型別轉換
/* 時間:2018.03.06 14:41 目的:1. 強制轉化資料型別 2. 迴圈更新中的變數 i 規範使用中,不能定義為浮點型 */ #include<stdio.h> int main (void) { int i ;
Python基本語法_強制資料型別轉換
目錄 前言 本篇主要介紹Python的強制型別轉換。 軟體環境 系統 UbuntuKylin 14.04 軟體 Python 2.7.3 IPython 4.0.0 Python資料型別的顯式轉換 資料型別的顯示轉換,也稱為
Kotlin學習筆記2 : 變數常量與基本資料型別
一:繼承與類與方法定義: (1)繼承用一個英文冒號: extends---> : 預設的類是不可以被繼承的,只能繼承宣告為open或者abstract的類 open class Person (name: String , surname: String) { } (
C語言全域性變數初始化、資料型別長度
今天在工作中遇到兩個問題,記錄下來: 1. 定義了一個全域性變數,然後初始化,編譯的時候編譯不通過。如下: int a; a = 5; 編譯的時候一直報錯,且說下面的a沒有定義型別,預設類似是int。 後面才發現全域性變數不能再全域性初始化,要初始化則在定義的時候初始化,如
使用CURL斷點續傳時遇到的資料型別問題
使用vc2008+CURL開發 HTTP 檔案下載時,發現只要設定了斷點續傳,就無法執行下載,向CURL註冊的下載回撥函式根本就不會被呼叫。 程式碼如下: curl_easy_setopt(curl, CURLOPT_URL, szRemoteUrl); curl_easy
SQL 用於各種資料庫的資料型別(轉載) sqlserver 資料型別 取值範圍 長度
SQL 用於各種資料庫的資料型別 來源 http://www.runoob.com/sql/sql-datatypes.html 面向資料庫程式設計中,資料型別的取值範圍、長度,可能是需要經常檢視的資料。 Microsoft Access、MySQL 和 SQL S
Python資料型別(1)數字資料型別
Python資料型別簡介 Python語言是面向物件的一門程式語言。Python中的資料型別其實就是Python的內建基本物件。內建物件主要包括簡單型別和容器型別。簡單型別主要是數值型資料,容器型別是可以包含其他物件的集體,如序列,元組,對映,集合等。Python中的資料型別也是物件,資料型別像
為什麼泛型類的型別不能是基本資料型別
1.泛型的定義:在程式中我們將一個物件放入集合中,但是集合不會記住物件的型別,當我們在次使用物件的時候,物件變為Object型別,而程式中還是原來的型別,我們必須要自己轉換其型別,為了解決這個問題,則提出泛型。 2.泛型要求包容的是物件型別,而基本資料型別在Java中不屬於物件。但是基本資料型別