sscanf 的乙個坑

2021-10-08 03:25:28 字數 1704 閱讀 9068

在一次專案中,偶然使用了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 ...