判斷乙個數是由符號數還是無符號數

2021-06-23 09:23:08 字數 1562 閱讀 5388

這是在《c專家程式設計》一書上提到的乙個問題。我在網上搜尋了一下,找到了一些解法,總結如下。

首先是《c專家程式設計》上提到解法:

#define isunsigned(a) (a>=0 && ~a>=0)

#define isunsigned(type) ((type)0-1 > 0)

第二個從型別來判斷,沒有問題。

1、判斷乙個數是否是無符號數

#define isunsigned(a)  (a>=0  &&  ~a>=0)

解析:(1)如果乙個數小於0,則它是有符號數;

(2)如果乙個數大於0,則對它按位取反(包括符號位),若仍大於0,則為無符號數,否則為有符號數。

2、判斷乙個型別是否是無符號型別

#define isunsigned(type)  ((type)0 - 1 >0)

解析:1、根據c語言的型別自動提公升原則,如果type是有符號的,則與1計算的結果是有符號的,計算過程不發生型別提公升,結果小於0;

2、如果type是無符號的,則發生型別提公升,1先轉換為無符號型別,計算結果同樣為無符號型別,結果大於0。

而第乙個只能用在k&r c裡,在ansi c裡就不行了。當這個巨集被用在int/unsigned int時,沒有任何問題。但是當使用在char和short上就會出錯。

分析: 此巨集在int/unsigned int好使的原因是巨集中的a的精度始終不會發生變化,而當a是char和short時,表示式~a>=0會先將a變為int然後再取反(因為常量0的型別為int),而int當然是有符號的,對它取反就有可能小於0。

要修正這個錯誤其實很簡單,那就是要保證先進行取反操作再做精度提公升,我們可以採用對a取反a=~a(這樣就不會有型別提公升),判斷結束後再取一次反,恢復a的值。

這樣得到新的**:

#define isunsigned(a) (a >=0 && (a=~a,a >=0 ? (a=~a,1):(a=~a,0)))

另一種方法是:把變數的最高位置1,然後判斷變數是否大於0。如果大於0,就是無符號數;否則就是有符號數。

#defined isunsigned(a) (a|=(0x1<<(sizeof(a)*8-1))>0?1:0)

還有人給出的方法是使用函式過載的方法:

void f(int val) 

void f(unsigned int val)

在判斷a是否有符號整數的地方呼叫函式f(a)就可以了吧

下面是對上面測試程式:

#include #define isunsigned(a) ((a|=(1<<(sizeof(a)*8-1)))>0?1:0)

#define isunsigned2(n) (n>=0&&~n>=0)

#define isunsigned3(n) (n>=0&&-n>=0&&n-1>=0)

#define isunsigned4(n) (n>=0&&(n=~n,n>=0?(n=~n,1):(n=~n,0)))

#define test(n) if(isunsigned4(n))\

cout<<#n" is unsigned"<

怎樣判斷乙個數是無符號型別還是有符號型別

1.用函式過載的方法 char gettype unsigned int i char gettype int i 2.利用表示式中存在有符號型別和無符號型別時所有的運算元都自動轉換為無符號型別。1 當a為無符號數時a a為0,而 1為有符號數,因此轉為無符號數,為乙個很大的數 2 當a為有符號數時...

判斷乙個數是偶數還是奇數

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!遞迴入門 互動遞迴 到目前為止,看到的遞迴函式都是直接呼叫自己。雖然大多數的遞迴函式都符合這一形式,但其實遞迴的定義更為廣泛,如果某個函式被細分成了幾個子函式,那麼可以在更深的巢狀層次上應用遞迴呼叫。例如 如果函式 f 呼叫函式 g 而函式 g 反...

判斷乙個數是否是回文數

題目 定義回文數的概念如下 如果乙個非負數左右完全對應,則該數是回文數,如 121,22 如果乙個負數的絕對值左右完全對應,則該數是回文數,如 121,22 public static void main string args printrandm arr,3 1 5 4 system.out.p...