[問題] 型式參數為void *的問題

看板C_and_CPP作者 (ppttcc)時間15年前 (2010/10/26 23:34), 編輯推噓18(18052)
留言70則, 8人參與, 最新討論串1/2 (看更多)
問題: 我想傳一個 tm 結構至自訂的函數中,但形式參數寫成void *, 函數定義如下,但產生問題 void* timefun(void * st) { cout<<st->tm_year;//此行有問題, //編譯器訊息為 void* is not a pointer-to-object type } 我想這問題是因為沒有人告訴編譯器st將會是個tm結構的指標, 自然也不可能取用結構的成員. 但是否仍有解?(除了將void 改為tm) 且如此一來將參數寫成void *的那些函數意義又是什麼? -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 114.38.10.138 ※ 編輯: ppttcc 來自: 114.38.10.138 (10/26 23:35)

10/26 23:35, , 1F
cout << (tm*)st->tm_year;
10/26 23:35, 1F
說也奇怪,這招編不過去> <

10/26 23:35, , 2F
在使用(dereference)之前, 用轉型使之成為正確的type就
10/26 23:35, 2F

10/26 23:36, , 3F
可以解讀該指標; C++也許有更理想的cast方式, 但小弟不
10/26 23:36, 3F

10/26 23:37, , 4F
熟XD 用void*的好處是省去傳遞type這件事, 由caller/
10/26 23:37, 4F

10/26 23:38, , 5F
callee自己橋好被傳遞的型態, 中間如果有轉發層就更不用
10/26 23:38, 5F

10/26 23:38, , 6F
care真實的型態, 純作interface就好:)
10/26 23:38, 6F

10/26 23:40, , 7F
1.轉型 2.萬用指標
10/26 23:40, 7F

10/26 23:43, , 8F
所有的指標都可以隱式轉換成void*, 這就是他萬用的原
10/26 23:43, 8F
※ 編輯: ppttcc 來自: 114.38.10.138 (10/26 23:45)

10/26 23:44, , 9F
因, 不過這樣一來就必須依賴轉型才能做正確的事情, 為
10/26 23:44, 9F

10/26 23:45, , 10F
了可以接很多種指標又不遺漏型別資訊, 1.是用繼承關係
10/26 23:45, 10F

10/26 23:46, , 11F
接父類別指標 2.是用寫函式模板, 為每個型別都訂製一
10/26 23:46, 11F

10/26 23:46, , 12F
個函式
10/26 23:46, 12F

10/26 23:51, , 13F
編不過請提供err msg, 只講編不過沒人能知道為何~_~
10/26 23:51, 13F

10/26 23:52, , 14F
還是同樣的error message
10/26 23:52, 14F

10/26 23:54, , 15F
cout << ((tm*)st)->tm_year; 這樣?
10/26 23:54, 15F
這樣就編過去了,感謝~

10/26 23:54, , 16F
慘了, 忘了優先順序嗎?? 早知道就全括號下去....Orz
10/26 23:54, 16F

10/26 23:55, , 17F
因為 -> 比轉型 () 的優先權還高
10/26 23:55, 17F

10/26 23:56, , 18F
static_cast<tm*>(st)->tm_year
10/26 23:56, 18F
這樣也編過去了,感謝~ ※ 編輯: ppttcc 來自: 114.38.10.138 (10/27 00:00)

10/27 00:00, , 19F
直接取tm_year的偏移值不就好了, *(st+tm_year偏移值)
10/27 00:00, 19F

10/27 00:05, , 20F
只取偏移值而沒轉型的話應該行不通吧?
10/27 00:05, 20F

10/27 00:06, , 21F
void*可以dereference offset?
10/27 00:06, 21F

10/27 00:06, , 22F
只取偏移還是要轉型回來才能正確解讀資料, 還有void*直
10/27 00:06, 22F

10/27 00:06, , 23F
接加offset好像是未定義行為吧?_?
10/27 00:06, 23F

10/27 00:07, , 24F
http://nopaste.csie.org/f028d <- 取偏移值大概像這樣
10/27 00:07, 24F

10/27 00:08, , 25F
void 一次要走幾個 byte 沒有在標準裡面定義 這個意思?
10/27 00:08, 25F

10/27 00:08, , 26F
要換成整數去加, void 做偏移是沒用的
10/27 00:08, 26F

10/27 00:09, , 27F
幫程式寫外掛不知道結構時,都直接取偏移值轉型
10/27 00:09, 27F

10/27 00:11, , 28F
+offset*(sizeof(char))才行吧 直接+offset在void會錯吧
10/27 00:11, 28F

10/27 00:12, , 29F
以這個case來說,實在不必要這麼複雜 XD
10/27 00:12, 29F

10/27 00:14, , 30F
是這樣嗎cout<<*(st+sizeof(tm_year));
10/27 00:14, 30F

10/27 00:14, , 31F
z-2-8-25 除了char以外其他都沒規定 void直接+可能會錯吧
10/27 00:14, 31F

10/27 00:15, , 32F

10/27 00:16, , 33F
cout<<(int)*((char*)st+tm_year's offset);
10/27 00:16, 33F

10/27 00:17, , 34F
會有tm_year undeclared (first use this function) 的err
10/27 00:17, 34F

10/27 00:18, , 35F
tm_year's offset是他的敘述, 你要自己換成offset的數值
10/27 00:18, 35F

10/27 00:18, , 36F
不是讓你直接貼上他的全部推文. 只是, 何必搞這麼複雜,
10/27 00:18, 36F

10/27 00:19, , 37F
這樣不是一開始就直接轉型成對的比較省事嗎....Orz
10/27 00:19, 37F

10/27 00:21, , 38F
通常轉型頻繁的出現, 代表設計不良
10/27 00:21, 38F

10/27 00:21, , 39F
我換成cout<<*(st+sizeof(long));後,產生一個error:
10/27 00:21, 39F

10/27 00:21, , 40F
st是void*, void*不應該直接+-offset, 所以你還是要先對
10/27 00:21, 40F

10/27 00:22, , 41F
pointer of type `void *' used in arithmetic
10/27 00:22, 41F

10/27 00:22, , 42F
st轉型成其他指標型態, 要用offset通常就轉成char*, 然
10/27 00:22, 42F

10/27 00:22, , 43F
後才加offset. 另外, 怎麼取出offset又看你的struct的定
10/27 00:22, 43F

10/27 00:23, , 44F
義而有所不同, 如果可以用OFFSET macro是還好, 不能的話
10/27 00:23, 44F

10/27 00:23, , 45F
除非你有興趣練習/追根究底, 不然其實不用搞這麼累Orz
10/27 00:23, 45F

10/27 00:25, , 46F
http://nopaste.csie.org/91227 是能印出2010沒錯啦....
10/27 00:25, 46F

10/27 00:28, , 47F
不過這種寫法實在很不健康
10/27 00:28, 47F

10/27 00:29, , 48F
抄作業時換點寫法才不會被教授發現
10/27 00:29, 48F

10/27 00:30, , 49F
真是辛苦了,感謝!
10/27 00:30, 49F

10/27 00:32, , 50F
to j 大, size_t 只到 65535 喔~
10/27 00:32, 50F

10/27 00:33, , 51F
所以可以用 offsetof 來取偏移~
10/27 00:33, 51F

10/27 00:34, , 52F
typedef _W64 unsigned int size_t;
10/27 00:34, 52F

10/27 00:34, , 53F
請看規格書規定, 謝謝~
10/27 00:34, 53F

10/27 00:35, , 54F
numeric_limits<size_t>::max() 我印出來是 4294967295
10/27 00:35, 54F

10/27 00:36, , 55F
再問一下,使用offset是否同時要考慮align?
10/27 00:36, 55F

10/27 00:39, , 56F
因為他這是平台相關的, 可以選擇不大於 signed long
10/27 00:39, 56F

10/27 00:39, , 57F
int 的型別來實作, 但是為了可攜性...
10/27 00:39, 57F

10/27 00:40, , 58F
7.17.4 應該沒翻錯吧 @_@
10/27 00:40, 58F

10/27 00:43, , 59F
用offsetof運算子就不用管那麼多了...不要自己去算
10/27 00:43, 59F

10/27 00:57, , 60F
size_t一般來說是平台上最大的unsigned int吧....
10/27 00:57, 60F

10/27 01:05, , 61F
我之前也都是當 uint 來用, 但是看到這個 : 7.18.3
10/27 01:05, 61F

10/27 01:06, , 62F
limit of size_t → SIZE_MAX 65535, 加上之前 t 大
10/27 01:06, 62F

10/27 01:08, , 63F
推的 intptr_t/uintptr_t 就知道這必須改寫了...
10/27 01:08, 63F

10/27 01:08, , 64F
至少有保證指標的值都可以完整存進來
10/27 01:08, 64F

10/27 02:18, , 65F
不用轉型的方法http://nopaste.csie.org/48f58
10/27 02:18, 65F

10/27 02:49, , 66F
... 建議原po 去google一下qsort,去1st link看 sample
10/27 02:49, 66F

10/27 02:51, , 67F
code 就知道了 void* 是"型別未定"指標 沒有多特別
10/27 02:51, 67F

10/27 02:52, , 68F
不可能直接轉array去拉element, 你又不是compiler
10/27 02:52, 68F

10/27 02:52, , 69F
拜託... 讓compiler做他該做的事 比較安全
10/27 02:52, 69F

10/29 21:49, , 70F
void*搭配template應該會有無限的可能
10/29 21:49, 70F
文章代碼(AID): #1CnlJrYC (C_and_CPP)
文章代碼(AID): #1CnlJrYC (C_and_CPP)