最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于C語言實現(xiàn)域名解析(附帶源碼)

 更新時間:2025年12月12日 08:45:57   作者:南城花隨雪。  
域名解析(DNS,Domain Name System)是互聯(lián)網(wǎng)最基礎(chǔ)的服務(wù)之一,本項目通過兩種實現(xiàn)方式講解域名解析,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下

一、項目背景詳細(xì)介紹

域名解析(DNS,Domain Name System)是互聯(lián)網(wǎng)最基礎(chǔ)的服務(wù)之一:將人類可讀的域名(例如 www.example.com)轉(zhuǎn)換為計算機可用的 IP 地址(例如 93.184.216.34)。幾乎所有互聯(lián)網(wǎng)通信都依賴 DNS。作為系統(tǒng)/網(wǎng)絡(luò)編程、運維與安全工程師的基礎(chǔ)技能,理解并實現(xiàn)域名解析有助于掌握以下關(guān)鍵點:

  • 套接字(socket)編程基礎(chǔ);
  • 使用系統(tǒng)庫(如 getaddrinfo)進行易用高層解析;
  • 理解 DNS 協(xié)議(基于 UDP 的報文格式)并自己實現(xiàn)一個簡易 DNS 客戶端以加深理解;
  • IPv4 與 IPv6 的區(qū)別、反向解析(PTR)、超時、重試與報錯處理;
  • 在受控環(huán)境下測試與調(diào)試(如使用本地 DNS 服務(wù)器或公共 DNS)。

本項目通過兩種實現(xiàn)方式講解域名解析:

  1. 系統(tǒng)接口法(推薦, 簡單可靠):使用標(biāo)準(zhǔn)庫函數(shù) getaddrinfo() / getnameinfo() 實現(xiàn)同步解析。優(yōu)點:跨平臺、支持 IPv4/IPv6、自動處理搜索域和服務(wù)名。適合大多數(shù)應(yīng)用場景。
  2. 自實現(xiàn) DNS 客戶端(進階,學(xué)習(xí)用):直接構(gòu)造 DNS 請求報文通過 UDP 發(fā)送到 DNS 服務(wù)器(如 8.8.8.8),解析返回的資源記錄(A、AAAA、CNAME)。優(yōu)點:深入理解 DNS 協(xié)議、可以自定義查詢行為、用于教學(xué)和調(diào)試。缺點:需處理更多協(xié)議細(xì)節(jié)(字節(jié)序、報文壓縮、超時重傳等)。

二、項目需求詳細(xì)介紹

功能性需求

實現(xiàn)一個命令行工具 resolver,支持下列功能:

  • 使用系統(tǒng)接口解析域名(顯示 IPv4 與 IPv6 地址)。
  • 使用自實現(xiàn) DNS 客戶端向指定 DNS 服務(wù)器(可配置)發(fā)送查詢并解析 A/AAAA/CNAME 記錄。
  • 支持正向解析(域名 → IP)與反向解析(IP → 域名)。
  • 對錯誤(找不到主機、超時、網(wǎng)絡(luò)不可達(dá)等)給出清晰提示。
  • 在自實現(xiàn) DNS 客戶端中,處理簡單的 DNS 名稱壓縮,并支持超時與重試(基礎(chǔ)級)。

非功能性需求

  • 代碼用純 C 實現(xiàn)(兼顧可移植性),在 Linux 下可直接編譯。
  • 結(jié)構(gòu)清晰,函數(shù)注釋詳盡,便于教學(xué)演示。
  • 主體代碼放在單一代碼塊內(nèi),內(nèi)部用注釋分隔“模塊/文件”。
  • 提供示例用法與測試樣例。

三、相關(guān)技術(shù)詳細(xì)介紹

1. 系統(tǒng) DNS 接口(getaddrinfo/getnameinfo)

getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res):跨 IPv4/IPv6 的推薦方式。返回鏈表形式的 addrinfo,其中包含 sockaddr 可直接用于 connect 或可轉(zhuǎn)換為字符串。

getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags):用于反向解析(IP → 主機名)或?qū)?sockaddr 轉(zhuǎn)換為數(shù)字字符串。

優(yōu)點:處理搜索域、可并發(fā)安全(線程安全實現(xiàn)依賴平臺),推薦使用。

2. DNS 協(xié)議(報文結(jié)構(gòu),簡要)

DNS 報文(RFC 1035)大體結(jié)構(gòu):

  • 16-bit ID
  • 16-bit flags
  • 16-bit QDCOUNT(問題條目數(shù))
  • 16-bit ANCOUNT(回答條目數(shù))
  • 16-bit NSCOUNT(權(quán)威記錄數(shù))
  • 16-bit ARCOUNT(額外記錄數(shù))
  • 問題(QNAME,QTYPE,QCLASS)
  • 資源記錄(NAME,TYPE,CLASS,TTL,RDLENGTH,RDATA)

QNAME 為標(biāo)簽序列(每段前綴長度字節(jié),末尾 0)。返回報文中 RDATA 對于 A 為 4 字節(jié) IPv4 地址、AAAA 為 16 字節(jié) IPv6 地址。注意 DNS 報文中會有名稱壓縮(兩個字節(jié)的指針以 11 開頭);實現(xiàn)時需解析壓縮格式。

3. UDP 套接字編程與超時處理

自實現(xiàn) DNS 客戶端使用 UDP 套接字向 DNS 服務(wù)器發(fā)送查詢并等待響應(yīng);需設(shè)置接收超時(setsockopt(..., SO_RCVTIMEO, ...)),并在超時或錯誤時實現(xiàn)重試機制(例如最多重試 3 次)。

四、實現(xiàn)思路詳細(xì)介紹

本文實現(xiàn)分兩部分(兩種方法):

方法一:系統(tǒng)接口法(getaddrinfo)

  • 創(chuàng)建 hints:設(shè)置 ai_family = AF_UNSPEC(同時支持 IPv4 和 IPv6),ai_socktype = SOCK_STREAM(或 0),ai_flags = AI_CANONNAME(請求返回規(guī)范名)。
  • 調(diào)用 getaddrinfo(domain, NULL, &hints, &res), 遍歷 res 鏈表,使用 getnameinfoinet_ntop 打印 IP 地址字符串。
  • 反向解析使用 getnameinfo。

該方法短小精悍且功能完備。

方法二:自實現(xiàn) DNS 客戶端(UDP)

構(gòu)造 DNS 查詢報文:

隨機 ID(16-bit)

flags 設(shè)置為標(biāo)準(zhǔn)遞歸查詢(Recursion Desired)

QDCOUNT = 1

構(gòu)造 QNAME(標(biāo)簽序列)

QTYPE = A(1)或 AAAA(28)

QCLASS = IN(1)

發(fā)送到 DNS 服務(wù)器 UDP 53 端口。

等待響應(yīng),解析頭部獲取 ANCOUNT,解析資源記錄:

  • 解析 NAME(處理壓縮)
  • 解析 TYPE、CLASS、TTL、RDLENGTH、RDATA
  • 對 A / AAAA / CNAME 做輸出
  • 處理超時與重試,如 2 秒超時,最多重試 3 次。
  • 注意網(wǎng)絡(luò)字節(jié)序(htons/ntohs)。

實現(xiàn)時會包含名稱解壓函數(shù) dns_name_unpack(),用于把壓縮的域名解析為可讀字符串。

五、完整實現(xiàn)代碼

/***************************************************************
 * 文件:resolver.c
 * 功能:C 語言實現(xiàn)域名解析(兩種方式)
 *   - 方法 A:使用系統(tǒng)接口 getaddrinfo/getnameinfo(推薦)
 *   - 方法 B:自實現(xiàn)簡易 DNS 客戶端(UDP 查詢 A / AAAA / CNAME)
 *
 * 編譯(Linux):
 *   gcc resolver.c -o resolver
 *
 * 用法示例:
 *   ./resolver sys www.example.com         # 使用系統(tǒng)接口解析
 *   ./resolver dns 8.8.8.8 www.example.com # 使用自定義 DNS 客戶端,指定 DNS 服務(wù)器
 *   ./resolver reverse sys 93.184.216.34   # 反向解析(IP->域名)使用系統(tǒng)接口
 *
 ***************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
#include <sys/time.h>

/* -----------------------------
   通用工具函數(shù)與定義
   ----------------------------- */

#define MAXBUF 512

static void pprint_addrinfo(struct addrinfo *res) {
    char host[NI_MAXHOST];
    for (struct addrinfo *p = res; p != NULL; p = p->ai_next) {
        void *addr;
        const char *ipver;
        if (p->ai_family == AF_INET) {
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
            addr = &(ipv4->sin_addr);
            ipver = "IPv4";
        } else if (p->ai_family == AF_INET6) {
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
            addr = &(ipv6->sin6_addr);
            ipver = "IPv6";
        } else {
            continue;
        }
        if (inet_ntop(p->ai_family, addr, host, sizeof(host)) == NULL) {
            strncpy(host, "unknown", sizeof(host));
            host[sizeof(host)-1] = 0;
        }
        printf("  %-4s  %s\n", ipver, host);
    }
}

/* -----------------------------
   方法 A:使用系統(tǒng)接口 getaddrinfo / getnameinfo
   ----------------------------- */

static int resolve_with_getaddrinfo(const char *name) {
    struct addrinfo hints, *res;
    int rv;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;    // 支持 IPv4 和 IPv6
    hints.ai_socktype = 0;          // 任意 socket 類型
    hints.ai_flags = AI_CANONNAME;  // 返回規(guī)范名(如可用)

    rv = getaddrinfo(name, NULL, &hints, &res);
    if (rv != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    printf("Canonical name: %s\n", res->ai_canonname ? res->ai_canonname : "(none)");
    printf("Addresses for %s:\n", name);
    pprint_addrinfo(res);

    freeaddrinfo(res);
    return 0;
}

/* 反向解析:IP -> 主機名 */
static int reverse_with_getnameinfo(const char *ipstr) {
    struct sockaddr_storage sa;
    socklen_t sa_len;
    char host[NI_MAXHOST];

    memset(&sa, 0, sizeof(sa));
    if (strchr(ipstr, ':')) {
        // IPv6
        struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&sa;
        sa6->sin6_family = AF_INET6;
        if (inet_pton(AF_INET6, ipstr, &(sa6->sin6_addr)) != 1) {
            fprintf(stderr, "Invalid IPv6 address: %s\n", ipstr);
            return 1;
        }
        sa_len = sizeof(struct sockaddr_in6);
    } else {
        // IPv4
        struct sockaddr_in *sa4 = (struct sockaddr_in *)&sa;
        sa4->sin_family = AF_INET;
        if (inet_pton(AF_INET, ipstr, &(sa4->sin_addr)) != 1) {
            fprintf(stderr, "Invalid IPv4 address: %s\n", ipstr);
            return 1;
        }
        sa_len = sizeof(struct sockaddr_in);
    }

    int rv = getnameinfo((struct sockaddr *)&sa, sa_len, host, sizeof(host), NULL, 0, NI_NAMEREQD);
    if (rv != 0) {
        fprintf(stderr, "getnameinfo: %s\n", gai_strerror(rv));
        return 1;
    }
    printf("Reverse lookup: %s -> %s\n", ipstr, host);
    return 0;
}

/* -----------------------------
   方法 B:自實現(xiàn)簡易 DNS 客戶端(UDP)
   僅支持查詢 A(1) / AAAA(28) / CNAME (5)
   ----------------------------- */

/* DNS header: 12 bytes */
#pragma pack(push, 1)
struct dns_header {
    unsigned short id;
    unsigned short flags;
    unsigned short qdcount;
    unsigned short ancount;
    unsigned short nscount;
    unsigned short arcount;
};
#pragma pack(pop)

/* DNS question tail (type & class) */
struct dns_question_tail {
    unsigned short qtype;
    unsigned short qclass;
};

/* 資源記錄固定頭部(不含可變長度 NAME 與 RDATA) */
#pragma pack(push,1)
struct dns_rr_fixed {
    unsigned short type;
    unsigned short class;
    unsigned int ttl;
    unsigned short rdlength;
};
#pragma pack(pop)

/* 將域名從點分格式轉(zhuǎn)換為 DNS 報文的標(biāo)簽格式:
   e.g., "www.example.com" -> [3]www[7]example[3]com[0]
   返回寫入的字節(jié)數(shù)到 buf(不超過 buflen)。
*/
static int dns_name_pack(const char *name, unsigned char *buf, int buflen) {
    int nlen = strlen(name);
    if (nlen == 0) {
        if (buflen < 1) return -1;
        buf[0] = 0;
        return 1;
    }
    int pos = 0;
    const char *label = name;
    const char *p = name;
    while (1) {
        if (*p == '.' || *p == '\0') {
            int len = p - label;
            if (len > 63) return -1; // label too long
            if (pos + 1 + len >= buflen) return -1;
            buf[pos++] = (unsigned char)len;
            if (len > 0) {
                memcpy(&buf[pos], label, len);
                pos += len;
            }
            if (*p == '\0') {
                // terminate with zero
                if (pos >= buflen) return -1;
                buf[pos++] = 0;
                break;
            }
            label = p + 1;
        }
        p++;
    }
    return pos;
}

/* 解析 DNS 報文中的名稱(包含指針壓縮)
   packet:完整報文起始地址
   pktlen:報文總長度
   offset:當(dāng)前讀取偏移(輸入時指向名稱開始),函數(shù)結(jié)束時 offset 會更新到名稱后的第一個字節(jié)
   out:輸出緩沖區(qū)存放解析出的點分格式字符串
   outlen:輸出長度
   返回:0 成功,-1 失敗
*/
static int dns_name_unpack(unsigned char *packet, int pktlen, int *offset, char *out, int outlen) {
    int orig_offset = *offset;
    int pos = 0;
    int jumped = 0;
    int max_jumps = 0;
    int cur = *offset;
    while (cur < pktlen) {
        unsigned char len = packet[cur];
        if (len == 0) {
            // end of name
            if (!jumped) *offset = cur + 1;
            if (pos == 0) {
                // root
                if (pos + 1 > outlen) return -1;
                out[pos] = '\0';
            } else {
                if (pos + 1 > outlen) return -1;
                out[pos] = '\0';
            }
            return 0;
        }
        if ((len & 0xC0) == 0xC0) {
            // pointer: next byte + (len & 0x3F) << 8
            if (cur + 1 >= pktlen) return -1;
            int b2 = packet[cur + 1];
            int pointer = ((len & 0x3F) << 8) | b2;
            if (pointer >= pktlen) return -1;
            if (!jumped) *offset = cur + 2;
            cur = pointer;
            jumped = 1;
            if (++max_jumps > 10) return -1; // avoid loops
            continue;
        } else {
            // label
            cur++;
            if (cur + len > pktlen) return -1;
            if (pos + len + 1 >= outlen) return -1;
            memcpy(out + pos, packet + cur, len);
            pos += len;
            out[pos++] = '.';
            cur += len;
        }
    }
    return -1;
}

/* 構(gòu)造并發(fā)送 DNS 查詢(type: 1=A, 28=AAAA)
   dns_server: dotted IP string, e.g., "8.8.8.8"
   name: 域名
   type: qtype (1/A, 28/AAAA)
   timeout_sec: 接收超時時間(秒)
   返回:0 成功(并將打印解析結(jié)果),非0表示失敗
*/
static int dns_query_simple(const char *dns_server, const char *name, unsigned short qtype, int timeout_sec) {
    unsigned char buf[512];
    memset(buf, 0, sizeof(buf));

    struct dns_header hdr;
    memset(&hdr, 0, sizeof(hdr));
    srand((unsigned int)time(NULL));
    hdr.id = (unsigned short) (rand() & 0xFFFF);
    hdr.flags = htons(0x0100); // standard query, recursion desired
    hdr.qdcount = htons(1);

    // 寫 header
    memcpy(buf, &hdr, sizeof(hdr));
    int offset = sizeof(hdr);

    // 寫 QNAME
    int n = dns_name_pack(name, buf + offset, sizeof(buf) - offset);
    if (n < 0) {
        fprintf(stderr, "dns_name_pack failed\n");
        return 1;
    }
    offset += n;

    // 寫 QTYPE & QCLASS
    struct dns_question_tail qt;
    qt.qtype = htons(qtype);
    qt.qclass = htons(1); // IN
    memcpy(buf + offset, &qt, sizeof(qt));
    offset += sizeof(qt);

    // 發(fā)送 UDP 包
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        perror("socket");
        return 1;
    }

    struct sockaddr_in serv;
    memset(&serv, 0, sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_port = htons(53);
    if (inet_pton(AF_INET, dns_server, &serv.sin_addr) != 1) {
        fprintf(stderr, "Invalid DNS server IP: %s\n", dns_server);
        close(sock);
        return 1;
    }

    // 發(fā)送并等待回復(fù)(帶重試)
    int tries = 3;
    int rv = 1;
    for (int t = 0; t < tries; t++) {
        ssize_t sent = sendto(sock, buf, offset, 0, (struct sockaddr*)&serv, sizeof(serv));
        if (sent != offset) {
            perror("sendto");
            continue;
        }

        // 設(shè)置 recv 超時
        struct timeval tv;
        tv.tv_sec = timeout_sec;
        tv.tv_usec = 0;
        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));

        unsigned char resp[4096];
        struct sockaddr_in from;
        socklen_t fromlen = sizeof(from);
        ssize_t rlen = recvfrom(sock, resp, sizeof(resp), 0, (struct sockaddr*)&from, &fromlen);
        if (rlen < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                // timeout
                if (t == tries - 1) {
                    fprintf(stderr, "DNS query timeout\n");
                } else {
                    // retry
                    continue;
                }
            } else {
                perror("recvfrom");
            }
            continue;
        }

        // parse response
        if (rlen < (ssize_t)sizeof(struct dns_header)) {
            fprintf(stderr, "DNS response too short\n");
            continue;
        }
        struct dns_header rhdr;
        memcpy(&rhdr, resp, sizeof(rhdr));
        unsigned short qdcount = ntohs(rhdr.qdcount);
        unsigned short ancount = ntohs(rhdr.ancount);
        // skip questions
        int roff = sizeof(struct dns_header);
        for (int i = 0; i < qdcount; i++) {
            char qname[256];
            if (dns_name_unpack(resp, rlen, &roff, qname, sizeof(qname)) != 0) {
                fprintf(stderr, "Failed to unpack question name\n");
                break;
            }
            // skip qtype & qclass
            if (roff + sizeof(struct dns_question_tail) > rlen) break;
            roff += sizeof(struct dns_question_tail);
        }

        // parse answers
        printf("Answers (%d):\n", ancount);
        for (int i = 0; i < ancount; i++) {
            char aname[512];
            if (dns_name_unpack(resp, rlen, &roff, aname, sizeof(aname)) != 0) {
                fprintf(stderr, "Failed to unpack answer name\n");
                break;
            }
            if (roff + sizeof(struct dns_rr_fixed) > rlen) {
                fprintf(stderr, "Truncated RR header\n");
                break;
            }
            struct dns_rr_fixed rrf;
            memcpy(&rrf, resp + roff, sizeof(rrf));
            roff += sizeof(rrf);
            unsigned short type = ntohs(rrf.type);
            unsigned short rclass = ntohs(rrf.class);
            unsigned short rdlen = ntohs(rrf.rdlength);
            if (roff + rdlen > rlen) {
                fprintf(stderr, "Truncated RDATA\n");
                break;
            }
            if (type == 1 && rdlen == 4) {
                // A
                char addrbuf[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, resp + roff, addrbuf, sizeof(addrbuf));
                printf("  NAME: %s  TYPE=A  ADDR=%s\n", aname, addrbuf);
            } else if (type == 28 && rdlen == 16) {
                // AAAA
                char addrbuf[INET6_ADDRSTRLEN];
                inet_ntop(AF_INET6, resp + roff, addrbuf, sizeof(addrbuf));
                printf("  NAME: %s  TYPE=AAAA ADDR=%s\n", aname, addrbuf);
            } else if (type == 5) {
                // CNAME (rdata is a name)
                int tmp_off = roff;
                char cname[512];
                if (dns_name_unpack(resp, rlen, &tmp_off, cname, sizeof(cname)) == 0) {
                    printf("  NAME: %s  TYPE=CNAME RDATA=%s\n", aname, cname);
                } else {
                    printf("  NAME: %s  TYPE=CNAME (unpack failed)\n", aname);
                }
            } else {
                printf("  NAME: %s  TYPE=%d  (rdlen=%d bytes)\n", aname, type, rdlen);
            }
            roff += rdlen;
        }

        rv = 0; // success
        break;
    }

    close(sock);
    return rv;
}

/* -----------------------------
   簡單命令行接口
   支持:
     resolver sys <domain>
     resolver reverse sys <ip>
     resolver dns <dns_server> <domain>
   ----------------------------- */

int main(int argc, char *argv[]) {
    if (argc < 3) {
        fprintf(stderr, "Usage:\n");
        fprintf(stderr, "  %s sys <domain>                  # use system resolver\n", argv[0]);
        fprintf(stderr, "  %s reverse sys <ip>              # reverse lookup via system resolver\n", argv[0]);
        fprintf(stderr, "  %s dns <dns_server> <domain>     # use custom DNS client\n", argv[0]);
        return 1;
    }

    if (strcmp(argv[1], "sys") == 0) {
        // system resolver
        return resolve_with_getaddrinfo(argv[2]);
    } else if (strcmp(argv[1], "reverse") == 0 && argc >= 4 && strcmp(argv[2], "sys") == 0) {
        return reverse_with_getnameinfo(argv[3]);
    } else if (strcmp(argv[1], "dns") == 0 && argc >= 4) {
        const char *dns_server = argv[2];
        const char *domain = argv[3];
        // query A and AAAA
        printf("Query A records via DNS server %s for %s\n", dns_server, domain);
        dns_query_simple(dns_server, domain, 1, 2);
        printf("\nQuery AAAA records via DNS server %s for %s\n", dns_server, domain);
        dns_query_simple(dns_server, domain, 28, 2);
        return 0;
    } else {
        fprintf(stderr, "Unknown command or insufficient args\n");
        return 1;
    }
}

到此這篇關(guān)于基于C語言實現(xiàn)域名解析(附帶源碼)的文章就介紹到這了,更多相關(guān)C語言域名解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • opengl實現(xiàn)任意兩點間畫圓柱體

    opengl實現(xiàn)任意兩點間畫圓柱體

    這篇文章主要為大家詳細(xì)介紹了opengl實現(xiàn)任意兩點間畫圓柱體,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • C++類靜態(tài)成員與類靜態(tài)成員函數(shù)詳解

    C++類靜態(tài)成員與類靜態(tài)成員函數(shù)詳解

    靜態(tài)成員不可在類體內(nèi)進行賦值,因為它是被所有該類的對象所共享的。你在一個對象里給它賦值,其他對象里的該成員也會發(fā)生變化。為了避免混亂,所以不可在類體內(nèi)進行賦值
    2013-09-09
  • 一文詳解C++中的mutable關(guān)鍵字

    一文詳解C++中的mutable關(guān)鍵字

    在C++中mutable關(guān)鍵字正如字面意思所示,表示「可變的」之意,一般在以下兩種情況中使用較多,一是修飾類中的變量,用來突破const的限制,二是在Lambda表達(dá)式中使用,用來捕獲修改表達(dá)式之外的變量值,下面我們就針對這兩種使用場景逐個介紹
    2023-10-10
  • C++ 中消息隊列函數(shù)實例詳解

    C++ 中消息隊列函數(shù)實例詳解

    這篇文章主要介紹了C++ 中消息隊列函數(shù)實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • 數(shù)組指針、指針數(shù)組以及二位數(shù)組的深入解析

    數(shù)組指針、指針數(shù)組以及二位數(shù)組的深入解析

    下面來講講多維數(shù)組與指針的關(guān)系。與普通數(shù)組一樣,使用多維數(shù)組時,實際上將其自動轉(zhuǎn)換為指向該數(shù)組第一個元素的指針
    2013-09-09
  • c/c++ 函數(shù)返回指針和引用所引發(fā)的問題

    c/c++ 函數(shù)返回指針和引用所引發(fā)的問題

    本文主要介紹了c/c++ 函數(shù)返回指針和引用所引發(fā)的問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-05-05
  • Define,const,static用法總結(jié)

    Define,const,static用法總結(jié)

    const定義的全局?jǐn)?shù)據(jù)變量,其基本作用和define相同,但又在define的基礎(chǔ)上增加了好多功能
    2013-10-10
  • C++全面細(xì)致講解復(fù)數(shù)類

    C++全面細(xì)致講解復(fù)數(shù)類

    本文章向大家介紹C++ 標(biāo)準(zhǔn)庫中的復(fù)數(shù)類,主要包括C++ 標(biāo)準(zhǔn)庫中的復(fù)數(shù)類使用實例、應(yīng)用技巧、基本知識點總結(jié)和需要注意事項,具有一定的參考價值,需要的朋友可以參考一下
    2022-06-06
  • C++高性能服務(wù)器框架之線程模塊

    C++高性能服務(wù)器框架之線程模塊

    該模塊基于pthread實現(xiàn),sylar說,由于c++11中的thread也是由pthread封裝實現(xiàn)的,并且沒有提供讀寫互斥量,讀寫鎖,自旋鎖等,所以自己封裝了pthread,本文主要詳細(xì)介紹了C++高性能服務(wù)器框架中的線程模塊,需要的朋友可以參考下
    2023-06-06
  • Qt實現(xiàn)TCP網(wǎng)絡(luò)編程

    Qt實現(xiàn)TCP網(wǎng)絡(luò)編程

    這篇文章主要為大家詳細(xì)介紹了Qt實現(xiàn)TCP網(wǎng)絡(luò)編程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評論

中宁县| 涡阳县| 民丰县| 莱芜市| 平安县| 元氏县| 二手房| 崇文区| 甘肃省| 铜川市| 岗巴县| 芦山县| 东台市| 白银市| 宜川县| 武定县| 灵宝市| 红桥区| 纳雍县| 云龙县| 保德县| 德钦县| 翁牛特旗| 武川县| 刚察县| 荆州市| 蒙城县| 大英县| 左云县| 柘荣县| 英德市| 洛扎县| 手游| 响水县| 来凤县| 富蕴县| 亚东县| 青河县| 靖边县| 唐山市| 隆尧县|