首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言高頻庫函數速查手冊:stat、memset、rand 等核心函數詳解與實戰陷阱

     編輯:關於C語言

文件狀態獲取:stat 族函數

函數原型

#include 
#include 

int stat(const char *pathname, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf); // 不跟隨符號鏈接
int fstat(int fd, struct stat *statbuf);               // 基於文件描述符

關鍵結構體成員 (struct stat)

成員含義常用宏/判斷
st_mode文件類型與權限S_ISREG() S_ISDIR() S_ISLNK() S_IRUSR 等
st_inoinode 號硬鏈接同 inode
st_dev設備號跨設備判斷
st_nlink硬鏈接數>1 表示有硬鏈接
st_uid / st_gid所有者用戶/組 ID權限檢查
st_size文件大小 (字節)常規文件有效
st_atime / st_mtime / st_ctime最後訪問/修改/狀態變更時間time_t 類型
st_blksize / st_blocks塊大小/佔用塊數磁盤佔用估算

實戰模板:安全獲取文件大小

long long get_file_size(const char *path) {
    struct stat st;
    if (stat(path, &st) == -1) return -1; // errno 已設置
    if (!S_ISREG(st.st_mode)) return -2;  // 非常規文件
    return (long long)st.st_size;
}

內存填充:memset 深度解析

原型與語義

#include 
void *memset(void *s, int c, size_t n);
  • 將 s 起始的 n 個字節**全部**設置為 (unsigned char)c。
  • 返回 s。
  • 只能按字節填充,不可直接用於 int/float 數組初始化非 0/-1 值。

正確用法示例

// 1. 結構體/數組歸零 (最常用)
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));

// 2. 字符填充
char buf[100];
memset(buf, 'A', sizeof(buf)); // 全 'A'

// 3. 指針數組置 NULL (行為未定義! 標準不保證 NULL 全 0 位模式)
// 錯誤: memset(ptr_arr, 0, sizeof(ptr_arr));
// 正確: for (i=0; i

常見陷阱

  1. 參數順序:memset(dst, val, size),別寫反。
  2. 類型懲罰:對非字符類型填充非 0/-1 導致不可移植行為。
  3. 重疊內存:memset 不處理重疊,源目重疊行為未定義 (用 memmove 處理重疊拷貝)。
  4. 優化消除:釋放前清零敏感數據用 explicit_bzero / memset_s (C11) 防止編譯器優化掉。

隨機數生成:rand / srand / RAND_MAX

基礎 API

#include 
int rand(void);          // 返回 0 ~ RAND_MAX
void srand(unsigned seed); // 設置種子
#define RAND_MAX 32767   // 至少 32767 (15 位)

現代最佳實踐:拒絕 rand(),用 (C++) 或 OS 熵源 (C)

場景推薦方案原因
C 一般用途random() / srandom() (BSD 擴展)周期長、質量優於 rand
C 加密級getrandom() (Linux 3.17+) / /dev/urandom密碼學安全
C++11+std::mt19937 + std::uniform_int_distribution標準庫、高質量、類型安全
跨平台 CPCG / xoshiro256** 等無狀態生成器單頭文件、極快、統計學優良

若必須用 rand():正確區間映射

// [0, n-1] 均勻分佈 (拒絕採樣消除模偏)
int rand_range(int n) {
    if (n <= 0) return 0;
    int limit = RAND_MAX - (RAND_MAX % n);
    int r;
    do { r = rand(); } while (r >= limit);
    return r % n;
}

// [min, max] 閉區間
int rand_int(int min, int max) {
    return min + rand_range(max - min + 1);
}

// 雙精度浮點 [0.0, 1.0)
double rand_double(void) {
    return (double)rand() / (RAND_MAX + 1.0);
}

綜合實戰:文件隨機讀取片段

#include 
#include 
#include 
#include 
#include 
#include 

void print_random_chunk(const char *path, size_t chunk_sz) {
    struct stat st;
    if (stat(path, &st) || !S_ISREG(st.st_mode)) return;
    if (st.st_size < chunk_sz) chunk_sz = st.st_size;

    int fd = open(path, O_RDONLY);
    if (fd < 0) return;

    off_t max_off = st.st_size - chunk_sz;
    off_t off = (off_t)((double)random() / (RAND_MAX + 1.0) * (max_off + 1));
    lseek(fd, off, SEEK_SET);

    char *buf = malloc(chunk_sz);
    if (buf) {
        read(fd, buf, chunk_sz);
        fwrite(buf, 1, chunk_sz, stdout);
        free(buf);
    }
    close(fd);
}

總結速查卡

函數頭文件核心用途關鍵注意點
stat/lstat/fstatsys/stat.h文件元信息檢查返回值,用宏判斷類型,st_size 可能超過 32 位
memsetstring.h字節級填充只填 0/-1 安全,指針/浮點/結構體非零填充不可移植
rand/srandstdlib.h偽隨機數質量差、有模偏、非線程安全、勿用於安全場景
random/srandomstdlib.h更好偽隨機BSD 擴展,Linux/Unix 通用
getrandomsys/random.h加密安全隨機Linux 3.17+,阻塞行為可控
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved