實驗要求
- 實現
sat_add(有符號飽和加法)與 sat_sub(無符號飽和減法)。
- 使用
stdint.h 固定寬度類型,條件編譯防重複包含,extern "C" 支持 C++ 調用。
- 小端系統運行。
頭文件 sat_math.h
#ifndef SAT_MATH_H
#define SAT_MATH_H
#include
#ifdef __cplusplus
extern "C" {
#endif
#define TMAX_INT32 ((int32_t)0x7FFFFFFF)
#define TMIN_INT32 ((int32_t)0x80000000)
/* 有符號飽和加法
* 返回值:運算結果
* *flag:0=正常, 1=正溢出(TMAX), -1=負溢出(TMIN)
*/
int32_t sat_add(int32_t x, int32_t y, int *flag);
/* 無符號飽和減法
* 返回值:運算結果
* *flag:0=正常, -1=溢出(借位)
*/
uint32_t sat_sub(uint32_t x, uint32_t y, int *flag);
#ifdef __cplusplus
}
#endif
#endif /* SAT_MATH_H */
實現文件 sat_math.c
#include "sat_math.h"
int32_t sat_add(int32_t x, int32_t y, int *flag) {
int32_t res = x + y;
if (flag) {
// 正溢出:兩正相加得負
if (x > 0 && y > 0 && res < 0) {
*flag = 1;
return TMAX_INT32;
}
// 負溢出:兩負相加得正
if (x < 0 && y < 0 && res > 0) {
*flag = -1;
return TMIN_INT32;
}
*flag = 0;
}
return res;
}
uint32_t sat_sub(uint32_t x, uint32_t y, int *flag) {
// 無符號減法溢出等價於 x < y (產生借位)
if (flag) {
*flag = (x < y) ? -1 : 0;
}
return x - y; // 硬件自動模 2^32 環繞,符合飽和語義下的「截斷」行為
// 若需飽和到 0:return (x < y) ? 0 : x - y;
}
關鍵點說明
#ifndef/#define/#endif 防止重複包含。
extern "C" 禁用 C++ 名字修飾,使 C++ 可直接鏈接。
- 使用
int32_t/uint32_t 保證跨平台固定寬度。
- 溢出判斷利用補碼特性,無需大數庫。
最佳回答代碼
//第二個函數的flag參數類型應該是指針或者引用吧,不然沒意義了,寫個引用的算了,如果是指針就照第一個改
//extern沒太搞懂,這兩個函數用不上這個啊,一般用C++寫全局變量時就是那種定義在cpp中但是其他.h .cpp也要用時聲明
//ooxx.h
#ifdef OOXX_H
#else
#define OOXX_H
#define i32 int
#define ui32 unsigned int
#define TMax 1
#define TMin -1
#define NULL 0
i32 sat_add( i32 x, i32 y, i32* flag );
ui32 sat_sub( ui32 x, ui32 y, ui32& flag );
#endif
//ooxx.c
#include "ooxx.h"
i32 sat_add( i32 x, i32 y, i32* flag ) {
i32 r = x + y;
if( flag && x > 0 && y > 0 && r < 0 ) { *flag = TMax; }
else if( flag && x < 0 && y < 0 && r > 0 ) { *flag = TMin; }
else { *flag = NULL; }
return r;
}
ui32 sat_sub( ui32 x, ui32 y, ui32& flag ) {
ui32 r = x - y;
if( x - r != y || y + r != x ) flag = -1;
else flag = NULL;
return r;
}