void和void指針解析(原)


(一)基本概念

    void 類型:空類型,用於特殊目的的沒有操作,也沒有值的類型。不能被顯式或隱式的轉換為任意非空類型,可以通過強制類型轉換為void類型。

    void指針:指向任何對象的指針都可以轉換為void*類型指針,且不會丟失信息。在ANSI C使用類型void*代替char*作為通用指針的類型。

(二)使用方法

1. void的使用吐舌鬼臉

第一種是:對函數返回的限定

    在不加返回值類型限定的情況之下,編譯器會將其處理為整型的類型。例如以下的情況:

#include <stdio.h>
// 參考了別人寫void的例子,但是這個例子十分形象
// 的表明了不加返回類型值限定時,編譯器的處理規則。
add (int a, int b) 
{ 
    return a + b; 
}
 
int main(int argc, char* argv[]) 
{ 
    printf("2 + 3 = %d", add (2, 3)); 
    return 0;
}

    對於每個函數,惡魔我們都要明確的指定其返回值的類型。該void的時候,就void。不要省略不寫,這回帶來大麻煩惡魔

第二種:對函數參數的限定

    當函數不允許接受參數時,必須使用void限定。例如以下兩種情況:

在C語言下:

#include <stdio.h>
// 以下兩個函數都可以進行正常的編譯,不會報錯。
// C的容忍度還是很大的。。。
int func()
{
    return 1;
}
 
int func1(void)
{
    return 1;
}
 
int main(int argc, char* argv[]) 
{ 
    printf("%d\n", func(2)); 
    printf("%d\n", func1(2)); 
    return 0;
} 

運行結果太棒了

20RQ76LKBLX5_Q_thumb

在C++語言下:

#include <iostream>
 
int func()
{
    return 1;
}
int func1(void)
{
    return 1;
}
int main(int argc, char* argv[]) 
{ 
    std::cout << func(1) << std::endl;
    std::cout << func1(1) << std::endl;
    return 0;
} 

運行結果哭泣的臉

7A8_IPQDX6VMHP7O5V2_thumb

    惡魔在C語言中,可以給無參數的函數傳送任意類型的參數,但是在C++編譯器中編譯同樣的代碼則會出錯。惡魔在C++中,不能向無參數的函數傳送任何參數。

2. void指針的使用

    在《C++ primer》中,對void指針的作用做了闡述:與另一指針比較;向函數傳遞void指針或從函數返回void指針;給void指針賦值。

    由於void指針可以指向任意類型的數據,亦即可用任意數據類型的指針對void指針賦值,因此還可以用void指針來作為函數形參,這樣函數就可以接受任意數據類型的指針作為參數。

以下摘至sgi stl中的代碼片段:吐舌鬼臉

/* __n must be > 0      */
static void* allocate(size_t __n)
{
  void* __ret = 0;
 
  if (__n > (size_t) _MAX_BYTES) {
    __ret = malloc_alloc::allocate(__n);
  }
  else {
    _Obj* __STL_VOLATILE* __my_free_list
        = _S_free_list + _S_freelist_index(__n);
    // Acquire the lock here with a constructor call.
    // This ensures that it is released in exit or during stack
    // unwinding.
    ifndef _NOTHREADS
    /*REFERENCED*/
    _Lock __lock_instance;
    endif
    _Obj* __RESTRICT __result = *__my_free_list;
    if (__result == 0)
      __ret = _S_refill(_S_round_up(__n));
    else {
      *__my_free_list = __result -> _M_free_list_link;
      __ret = __result;
    }
  }
 
  return __ret;
}
/* __p may not be 0 */
static void deallocate(void* __p, size_t __n)
{
  if (__n > (size_t) _MAX_BYTES)
    malloc_alloc::deallocate(__p, __n);
  else {
    _Obj* __STL_VOLATILE*  __my_free_list
        = _S_free_list + _S_freelist_index(__n);
    _Obj* __q = (_Obj*)__p;
 
    // acquire lock
      ifndef _NOTHREADS
    /*REFERENCED*/
    _Lock __lock_instance;
      endif /* _NOTHREADS */
    __q -> _M_free_list_link = *__my_free_list;
    *__my_free_list = __q;
    // lock is released here
  }
}

    對於指針的自增行為,要迎合ANSI C 的規范。在ANSI C中void指針不能自增的,這種行為是一種非法行為,因為未知void的大小。哭泣的臉

#include <iostream>
 
int main(int argc, char* argv[]) 
{ 
    int i = 0;
    void *p;
    int *pint;
    int *pint1;
    pint = &i;
    p = pint;
    std::cout << pint << std::endl;
    pint++;
    std::cout << pint << std::endl;
    std::cout << p << std::endl;
    pint1 = (int *)p;
    std::cout << pint1 << std::endl;
    return 0;
} 

運行的結果:

9OV3PPIYTPM41KMFY_thumb

文獻參考:

1. 《C++ primer》和《C語言程序設計》

2.http://wenku.baidu.com/view/22c4b8d86f1aff00bed51edc.html這篇文章很出名啊太陽,很多void的文章都是轉載這一篇文章的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM