在一次專案中,偶然使用了sscanf,這裡就不詳細說明它的用法,開門見山,說一下本文的意圖,也希望其他同族兄弟了解。
上程式**:
struct ***;
int main(int argc, char** ar**)
執行:./test enp2s0 12:23:34:45:45:56
列印結果:xyz.b輸出為空
gcc -g test.c -o test
上gdb除錯結果:
說明一下,第一步,初始化xyz變數記憶體為0;
第二步,通過strcpy,將xyz.b賦值,圖中顯示為16進製制;
第三部,執行sscanf後,xyz.a的數值諸葛元素賦值,但是xyz.b的前三個位元組被置0了。
最終導致xyz.b輸出為空。
原因說明:一定要摒棄老祖宗流傳下來的玄學,開發過程中遇到的問題一定是有原因的。這裡的問題顯然是在執行sscanf之後出現了,那就只能深入看一下sscanf的使用。
sscanf 型別說明符:
型別
合格的輸入
引數的型別c
單個字元:讀取下乙個字元。如果指定了乙個不為 1 的寬度 width,函式會讀取 width 個字元,並通過引數傳遞,把它們儲存在陣列中連續位置。在末尾不會追加空字元。
char * d
十進位制整數:數字前面的 + 或 - 號是可選的。
int *
e,e,f,g,g
浮點數:包含了乙個小數點、乙個可選的前置符號 + 或 -、乙個可選的後置字元 e 或 e,以及乙個十進位制數字。兩個有效的例項 -732.103 和 7.12e4
float * o
八進位制整數。
int * s
字串。這將讀取連續字元,直到遇到乙個空格字元(空格字元可以是空白、換行和製表符)。
char * u
無符號的十進位制整數。
unsigned int *
x,x十六進製制整數。
int *
sscanf(ar**[2], "%x:%x:%x:%x:%x:%x", &(xyz.a[0]), &(xyz.a[1]), &(xyz.a[2]), &(xyz.a[3]), &(xyz.a[4]), &(xyz.a[5]));
程式中使用了%x,對應輸入引數型別應該是int*,說明引數的原型別應該是4bytes,而這裡xyz.a 陣列中每個元素是乙個位元組,當做記憶體拷貝時,xyz.a[5] 實際被複製的按16進製表示是0x00000067。x86_64平台的記憶體儲存是小端位元組序(高位元組在高位,低位元組在低位),而這裡gdb展示的是從低位元組到高位元組,從左往右,所以這裡 xyz的頭三個位元組被3個0x00覆蓋了。
因此只能將程式中的字串mac位址轉化成 int ,scanf輸入引數的原型就不支援unsigned char。其實,單從這個程式而言,可以調換xyz.a 和 xyz.b的賦值順序,也可以實現,下面來看一下:
但是切記,實際專案中慎用這種方式轉化mac位址,要不然你一定會付出代價!!
Python的乙個坑
今天發現了python乙個坑。我們知道python中函式跟c 一樣,可以設定預設引數,比如 def func x,y 1 print x,y func x 10 10 1 y有乙個預設值1,所以函式呼叫的結果是列印10 1 但是如果預設值是這樣的 class food def init self s...
ImmersionBar的乙個坑
今天寫 時發現殺掉activitya 1後再啟動activitya 2時,因為activitya 2的immersionbar先初始化了,之後activitya 1的ondestroy才執行,而關鍵點是發現ondestroy中確實是需要殺掉的activitya 1,而immersionbar也不是單...
isinstance的乙個坑
在使用unittest的時候,用到了assertisinstance方法,該方法呼叫了isinstance方法,現有兩個檔案中的兩個類 test c a.py classa pass test c b.py from a import a class b a pass其中目錄結構如下 test c ...