2014年1月28日 星期二

變數的長度及 printf 參數。

今天要把 MAC address 由字串轉成 16 進制數字時,才發現很麻煩。因為它是 6 個 bytes,太長了。尋找解決的過程經歷了一些故事,所以來記錄一下。

其實之前有碰到 memory address 的部份,由使用者輸進來的是字串,但運算時常常需要把它轉成 16 進制數字。在我手上的程式一般是使用 simple_strtoul 這個函式,但是它的傳回值是 unsigned long ,只有 4 個 bytes,所以長度不夠。

接下來就在想說要分段嗎?的時候,跟同事聊天,所以產生了一個很蠢的插曲。因為突然發現來源是存在 unsigned char[6] 裡面,目的是 unit8_t[6] 裡面,所以我想,是不是直接 = assign 過去就好。結果錯很大…
第一,是 unsigned char[12] 不是 unsigned char[6],所以裡面是 12 個字元,不是 6 個 8 bits Hex 值。
第二,同上,裡面是字元啊~~!所以 "ff" 就變成了 "66 66" 0rz

所以沒辦法,就回到,是不是該把它拆成兩段,再來用 simple_strtoul ?還是乾脆自己寫一個來轉?就在邊猶豫邊在程式碼裡面捲來捲去時,突然看到了…啊還有 unsigned long long 這東西啊!8 bytes 不但夠用,還有剩啊!

除此之外,指引我明燈的正是我的救星! simple_strtoull (怕有人沒看清楚,它有兩個L)的傳回值啊!

立馬把接收結果的變數調大成 unsigned long long,改呼叫 simple_strtoull ,裡面參數都一樣,真是無痛。

但是一執行下去,啊怎麼轉出來的結果還是少了兩個 bytes 啊!?還好檢查了一下 ARP table,裡面抓到的 MAC address 是正常的。那就是我自己的 debug 訊息印錯了而己。因為我的 printf 裡面用的是 %X。所以它只能印出 4 個 bytes。

回到重點,整理一下變數的長度跟 printf 時要用的參數。
這是用 sizeof 印出來的,常用的變數長度:
  char size is:1
  int size is:4
  float size is:4
  long size is:4
  long long size is:8

而 printf 用到的參數,我想也沒什麼特別的,就只有這個以前學校從來沒學過,但現在倒是會用到的:
 %lld:long long
 %llu:unsigned long long
 %llx:long long 型態以 16 進制印出

其它常見的就不列了。

沒有留言:

張貼留言