1. 程式人生 > >C語言之網路程式設計(伺服器和客戶端)

C語言之網路程式設計(伺服器和客戶端)

1、 套接字:源IP地址和目的IP地址以及源埠號和目的埠號的組合稱為套接字。其用於標識客戶端請求的伺服器和服務。

常用的TCP/IP協議的3種套接字型別如下所示。

(1)流套接字(SOCK_STREAM):

流套接字用於提供面向連線、可靠的資料傳輸服務。該服務將保證資料能夠實現無差錯、無重複傳送,並按順序接收。流套接字之所以能夠實現可靠的資料服務,原因在於其使用了傳輸控制協議,即TCP(The Transmission ControlProtocol)協議

(2)       資料報套接字(SOCK_DGRAM):

資料報套接字提供了一種無連線的服務。該服務並不能保證資料傳輸的可靠性,資料有可能在傳輸過程中丟失或出現數據重複,且無法保證順序地接收到資料。資料報套接字使用UDP(User Datagram Protocol)協議

進行資料的傳輸。由於資料報套接字不能保證資料傳輸的可靠性,對於有可能出現的資料丟失情況,需要在程式中做相應的處理。

(3)       原始套接字(SOCK_RAW):(一般不用這個套接字)

原始套接字(SOCKET_RAW)允許對較低層次的協議直接訪問,比如IP、 ICMP協議,它常用於檢驗新的協議實現,或者訪問現有服務中配置的新裝置,因為RAW SOCKET可以自如地控制Windows下的多種協議,能夠對網路底層的傳輸機制進行控制,所以可以應用原始套接字來操縱網路層和傳輸層應用。比如,我們可以通過RAW SOCKET來接收發向本機的ICMP、IGMP協議包,或者接收TCP/IP棧不能夠處理的IP包,也可以用來發送一些自定包頭或自定協議的IP包。網路監聽技術很大程度上依賴於SOCKET_RAW

2、 套接字基本函式:

(1)      建立套接字:int socket(int family, int type, intprotocol);

功能介紹:

      在Linux作業系統中,一切皆檔案,這個大家都知道,個人理解建立socket的過程其實就是一個獲得檔案描述符的過程,當然這個過程會是比較複雜的。可以從核心中找到建立socket的程式碼,並且socket的建立和其他的listen,bind等操作分離開來。socket函式完成正確的操作是返回值大於0的檔案描述符,當返回小於0的值時,操作錯誤。同樣是返回一個檔案描述符,但是會因為三個引數組合不同,對於資料具體的工作流程不同,對於應用層程式設計來說,這些也是不可見的。

引數說明:

      從socket建立的函式可以看出,socket有三個引數,family代表一個協議族,比較熟知的就是AF_INET,PF_PACKET等;第二個引數是協議型別,常見型別是SOCK_STREAM,SOCK_DGRAM, SOCK_RAW, SOCK_PACKET等;第三個引數是具體的協議,對於標準套接字來說,其值是0,對於原始套接字來說就是具體的協議值。

(2)      套接字繫結函式: intbind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);

功能介紹:

      bind函式主要應用於伺服器模式一端,其主要的功能是將addrlen長度 structsockaddr型別的myaddr地址與sockfd檔案描述符繫結到一起,在sockaddr中主要包含伺服器端的協議族型別,網路地址和埠號等。在客戶端模式中不需要使用bind函式。當bind函式返回0時,為正確繫結,返回-1,則為繫結失敗。

引數說明:

      bind函式的第一個引數sockfd是在建立socket套接字時返回的檔案描述符。

      bind函式的第二個引數是structsockaddr型別的資料結構,由於structsockaddr資料結構型別不方便設定,所以通常會通過對tructsockaddr_in進行地質結構設定,然後進行強制型別轉換成structsockaddr型別的資料,

(3)      監聽函式:int listen(int sockfd, int backlog);

功能介紹:

      剛開始理解listen函式會有一個誤區,就是認為其操作是在等在一個新的connect的到來,其實不是這樣的,真正等待connect的是accept操作,listen的操作就是當有較多的client發起connect時,server端不能及時的處理已經建立的連線,這時就會將connect連線放在等待佇列中快取起來。這個等待佇列的長度有listen中的backlog引數來設定。listen和accept函式是伺服器模式特有的函式,客戶端不需要這個函式。當listen執行成功時,返回0;執行失敗時,返回值位-1.

引數說明:

      sockfd是前面socket建立的檔案描述符;backlog是指server端可以快取連線的最大個數,也就是等待佇列的長度。

(4)      請求接收函式: int accept(int sockfd, structsockaddr *client_addr, socklen_t *len);

功能介紹:

      接受函式accept其實並不是真正的接受,而是客戶端向伺服器端監聽埠發起的連線。對於TCP來說,accept從阻塞狀態返回的時候,已經完成了三次握手的操作。Accept其實是取了一個已經處於connected狀態的連線,然後把對方的協議族,網路地址以及埠都存在了client_addr中,返回一個用於操作的新的檔案描述符,該檔案描述符表示客戶端與伺服器端的連線,通過對該檔案描述符操作,可以向client端傳送和接收資料。同時之前socket建立的sockfd,則繼續監聽有沒有新的連線到達本地埠。返回大於0的檔案描述符則表示accept成功,否則失敗。

引數說明:

      sockfd是socket建立的檔案描述符;client_addr是本地伺服器端的一個structsockaddr型別的變數,用於存放新連線的協議族,網路地址以及埠號等;第三個引數len是第二個引數所指內容的長度,對於TCP來說其值可以用sizeof(structsockaddr_in)來計算大小,說要說明的是accept的第三個引數要是指標的形式,因為這個值是要傳給協議棧使用的。

(5)客戶端請求連線函式: intconnect(int sock_fd, struct sockaddr *serv_addr,int addrlen);

功能介紹:

      連線函式connect是屬於client端的操作函式,其目的是向伺服器端傳送連線請求,這也是從客戶端發起TCP三次握手請求的開始,伺服器端的協議族,網路地址以及埠都會填充到connect函式的serv_addr地址當中。當connect返回0時說明已經connect成功,返回值是-1時,表示connect失敗。

引數說明:

      connect的第一個引數是socket建立的檔案描述符;第二個引數是一個structsockaddr型別的指標,這個引數中設定的是要連線的目標伺服器的協議族,網路地址以及埠號;第三個引數表示第二個引數內容的大小,與accept不同,這個值不是一個指標。

      在伺服器端和客戶端建立連線之後是進行資料間的傳送和接收,主要使用的接收函式是recv和read,傳送函式是send和write。因為對於socket套接字來說,最終實際操作的是檔案描述符,所以可以使用對檔案進行操作的接收和傳送函式對socket套接字進行操作。read和write函式是檔案程式設計裡的知識,所以這裡不再做多與的贅述。

3、 有了以上的知識,那麼我們就可以編寫一個簡單的伺服器和客戶端了

(1)       簡易伺服器:這個伺服器只能與一個客戶端相連線,如果有多個客戶端就不能用這個伺服器進行連線。

程式碼:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>


#define PORT 9990   //埠號
#define SIZE 1024   //定義的陣列大小

int Creat_socket()    //建立套接字和初始化以及監聽函式
{
	int listen_socket = socket(AF_INET, SOCK_STREAM, 0);   //建立一個負責監聽的套接字
	if(listen_socket == -1)
	{
		perror("socket");
		return -1;
	}
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	
	addr.sin_family = AF_INET;  /* Internet地址族 */
    addr.sin_port = htons(PORT);  /* 埠號 */
    addr.sin_addr.s_addr = htonl(INADDR_ANY);   /* IP地址 */
	
	int ret = bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr));  //連線
	if(ret == -1)
	{
		perror("bind");
		return -1;
	}
	
	ret = listen(listen_socket, 5);        //監聽
	if(ret == -1)
	{
		perror("listen");
		return -1;
	}
	return listen_socket;
}

int wait_client(int listen_socket)
{
	struct sockaddr_in cliaddr;
	int addrlen = sizeof(cliaddr);
	printf("等待客戶端連線。。。。\n");
	int client_socket = accept(listen_socket, (struct sockaddr *)&cliaddr, &addrlen);   //建立一個和客戶端交流的套接字
	if(client_socket == -1)
	{
		perror("accept");
		return -1;
	}
	
	printf("成功接收到一個客戶端:%s\n", inet_ntoa(cliaddr.sin_addr));
	
	return client_socket;
}

void hanld_client(int listen_socket, int client_socket)   //資訊處理函式,功能是將客戶端傳過來的小寫字母轉化為大寫字母
{
	char buf[SIZE];
	while(1)
	{
		int ret = read(client_socket, buf, SIZE-1);
		if(ret == -1)
		{
			perror("read");
			break;
		}
		if(ret == 0)
		{
			break;
		}
		buf[ret] = '\0';
		int i;
		for(i = 0; i < ret; i++)
		{
			buf[i] = buf[i] + 'A' - 'a';
		}
		
		printf("%s\n", buf);
		write(client_socket, buf, ret);
		
		if(strncmp(buf, "end", 3) == 0)
		{
			break;
		}
	}
	close(client_socket);
}

int main()
{
	int listen_socket = Creat_socket();
	
	int client_socket = wait_client(listen_socket);
	
	hanld_client(listen_socket, client_socket);
	
	close(listen_socket);
	
	return 0;
}

(2) 多程序併發伺服器:該伺服器就完全彌補了上一個伺服器的不足,可以同時處理多個客戶端,只要有客戶端來連線它,他就能響應。在我們這個伺服器中,父程序主要負責監聽,所以在父程序一開始就要把父程序的接收函式關閉掉,防止父程序在接收函式處阻塞,導致子程序不能建立成功。同理,子程序主要負責接收客戶端,並做相關處理,所以子程序在一建立就要把監聽函式關閉,不然會導致伺服器功能的紊亂。這個伺服器有一個特別要注意的是,子程序在退出時會產生殭屍程序,所以我們一定要對子程序退出後進行處理。

程式碼:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>

#define PORT 9990
#define SIZE 1024

int Creat_socket()         //建立套接字和初始化以及監聽函式
{
	int listen_socket = socket(AF_INET, SOCK_STREAM, 0);      //建立一個負責監聽的套接字  
	if(listen_socket == -1)
	{
		perror("socket");
		return -1;
	}
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	
	addr.sin_family = AF_INET;  /* Internet地址族 */
    addr.sin_port = htons(PORT);  /* 埠號 */
    addr.sin_addr.s_addr = htonl(INADDR_ANY);   /* IP地址 */
	
	int ret = bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr));    //連線
	if(ret == -1)
	{
		perror("bind");
		return -1;
	}
	
	ret = listen(listen_socket, 5);   //監聽
	if(ret == -1)
	{
		perror("listen");
		return -1;
	}
	return listen_socket;
}

int wait_client(int listen_socket)
{
	struct sockaddr_in cliaddr;
	int addrlen = sizeof(cliaddr);
	printf("等待客戶端連線。。。。\n");
	int client_socket = accept(listen_socket, (struct sockaddr *)&cliaddr, &addrlen);     //建立一個和客戶端交流的套接字
	if(client_socket == -1)
	{
		perror("accept");
		return -1;
	}
	
	printf("成功接收到一個客戶端:%s\n", inet_ntoa(cliaddr.sin_addr));
	
	return client_socket;
}

void hanld_client(int listen_socket, int client_socket)    //資訊處理函式,功能是將客戶端傳過來的小寫字母轉化為大寫字母
{
	char buf[SIZE];
	while(1)
	{
		int ret = read(client_socket, buf, SIZE-1);
		if(ret == -1)
		{
			perror("read");
			break;
		}
		if(ret == 0)
		{
			break;
		}
		buf[ret] = '\0';
		int i;
		for(i = 0; i < ret; i++)
		{
			buf[i] = buf[i] + 'A' - 'a';
		}
		
		printf("%s\n", buf);
		write(client_socket, buf, ret);
		
		if(strncmp(buf, "end", 3) == 0)
		{
			break;
		}
	}
	close(client_socket);
}

void handler(int sig)
{
	
	while (waitpid(-1,  NULL,   WNOHANG) > 0)
	{
		printf ("成功處理一個子程序的退出\n");
	}
}

int main()
{
	int listen_socket = Creat_socket();
	

	signal(SIGCHLD,  handler);    //處理子程序,防止殭屍程序的產生
	while(1)
	{
		int client_socket = wait_client(listen_socket);   //多程序伺服器,可以建立子程序來處理,父程序負責監聽。
		int pid = fork();
		if(pid == -1)
		{
			perror("fork");
			break;
		}
		if(pid > 0)
		{
			close(client_socket);
			continue;
		}
		if(pid == 0)
		{
			close(listen_socket);
			hanld_client(listen_socket, client_socket);
			break;
		}
	}
	
	close(listen_socket);
	
	return 0;
}


(3) 多執行緒併發伺服器:上一個多程序伺服器有一個缺點,就是每當一個子程序得到響應的時候,都要複製父程序的一切資訊,這樣就導致了CPU資源的浪費,當客戶端有很多來連線這個伺服器的時候,就會產生很多的子程序,會導致伺服器的響應變得很慢。所以我們就想到了多執行緒併發伺服器,我們知道執行緒的速度是程序的30倍左右,所以我們就用執行緒來做伺服器。

程式碼:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>


#define PORT 9990
#define SIZE 1024

int Creat_socket()         //建立套接字和初始化以及監聽函式
{
	int listen_socket = socket(AF_INET, SOCK_STREAM, 0);      //建立一個負責監聽的套接字  
	if(listen_socket == -1)
	{
		perror("socket");
		return -1;
	}
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	
	addr.sin_family = AF_INET;  /* Internet地址族 */
    addr.sin_port = htons(PORT);  /* 埠號 */
    addr.sin_addr.s_addr = htonl(INADDR_ANY);   /* IP地址 */
	
	int ret = bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr));    //連線
	if(ret == -1)
	{
		perror("bind");
		return -1;
	}
	
	ret = listen(listen_socket, 5);   //監聽
	if(ret == -1)
	{
		perror("listen");
		return -1;
	}
	return listen_socket;
}

int wait_client(int listen_socket)
{
	struct sockaddr_in cliaddr;
	int addrlen = sizeof(cliaddr);
	printf("等待客戶端連線。。。。\n");
	int client_socket = accept(listen_socket, (struct sockaddr *)&cliaddr, &addrlen);     //建立一個和客戶端交流的套接字
	if(client_socket == -1)
	{
		perror("accept");
		return -1;
	}
	
	printf("成功接收到一個客戶端:%s\n", inet_ntoa(cliaddr.sin_addr));
	
	return client_socket;
}

void hanld_client(int listen_socket, int client_socket)    //資訊處理函式,功能是將客戶端傳過來的小寫字母轉化為大寫字母
{
	char buf[SIZE];
	while(1)
	{
		int ret = read(client_socket, buf, SIZE-1);
		if(ret == -1)
		{
			perror("read");
			break;
		}
		if(ret == 0)
		{
			break;
		}
		buf[ret] = '\0';
		int i;
		for(i = 0; i < ret; i++)
		{
			buf[i] = buf[i] + 'A' - 'a';
		}
		
		printf("%s\n", buf);
		write(client_socket, buf, ret);
		
		if(strncmp(buf, "end", 3) == 0)
		{
			break;
		}
	}
	close(client_socket);
}

int main()
{
	int listen_socket = Creat_socket();
	
	while(1)
	{
		int client_socket = wait_client(listen_socket);
		
		pthread_t id;
		pthread_create(&id, NULL, hanld_client, (void *)client_socket);  //建立一個執行緒,來處理客戶端。
		
		 pthread_detach(id);   //把執行緒分離出去。
	}
	
	close(listen_socket);
	
	return 0;
}

(4)客戶端:客戶端相對於伺服器來說就簡單多了,客戶端只需要建立和伺服器相連線的套接字,然後對其初始化,然後再進行連線就可以了,連線上伺服器就可以傳送你想傳送的資料了。
程式碼:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>


#define PORT 9990
#define SIZE 1024

int main()
{
	int client_socket = socket(AF_INET, SOCK_STREAM, 0);   //建立和伺服器連線套接字
	if(client_socket == -1)
	{
		perror("socket");
		return -1;
	}
	struct sockaddr_in addr;
	memset(&addr, 0, sizeof(addr));
	
	addr.sin_family = AF_INET;  /* Internet地址族 */
    addr.sin_port = htons(PORT);  /* 埠號 */
    addr.sin_addr.s_addr = htonl(INADDR_ANY);   /* IP地址 */
	inet_aton("127.0.0.1", &(addr.sin_addr));

	int addrlen = sizeof(addr);
	int listen_socket =  connect(client_socket,  (struct sockaddr *)&addr, addrlen);  //連線伺服器
	if(listen_socket == -1)
	{
		perror("connect");
		return -1;
	}
	
	printf("成功連線到一個伺服器\n");
	
	char buf[SIZE] = {0};
	
	while(1)        //向伺服器傳送資料,並接收伺服器轉換後的大寫字母
	{
		printf("請輸入你相輸入的:");
		scanf("%s", buf);
		write(client_socket, buf, strlen(buf));
		
		int ret = read(client_socket, buf, strlen(buf));
		
		printf("buf = %s", buf);
		printf("\n");
		if(strncmp(buf, "END", 3) == 0)     //當輸入END時客戶端退出
		{
			break;
		}
	}
	close(listen_socket);
	
	return 0;
}






相關推薦

C語言網路程式設計伺服器客戶

1、 套接字:源IP地址和目的IP地址以及源埠號和目的埠號的組合稱為套接字。其用於標識客戶端請求的伺服器和服務。 常用的TCP/IP協議的3種套接字型別如下所示。 (1)流套接字(SOCK_STREAM): 流套接字用於提供面向連線、可靠的資料傳輸服務。該服務將保證資料能夠實現無差錯、無重複傳送,並按順序接

C語言網路程式設計域名解析

在網路程式設計時,知道域名是不能直接訪問一個主機的,需要轉換成相應的IP地址。有時在程式中需要將一個IP地址轉換成一個域名。本節將講解C程式中的IP地址與域名的轉換問題。 提示:在TCP/IP網路中,通訊雙方的主機必須知道彼此的IP地址方可進行正常的通訊,如果給出的主機的域

簡單的TCP協議 socket程式設計C語言伺服器客戶

         最近由於本人對網路程式設計的喜愛,所以對一點關於TCP協議socket程式設計的總結。由於本人的能力有限,寫的可能過於簡單,只適合初學者,歡迎大牛提出寶貴的意見,本人會感激不盡的。廢話少說了,進入正題。(下面程式碼是基於VC6.0)          下圖

C#.網路程式設計 Socket基礎Socket TCP協議 實現伺服器客戶簡單字串通訊

簡介:        本章節主要討論了Socket的入門知識,還未針對Socket的難點問題(比如TCP的無訊息邊界問題)展開討論,往後在其他章節中進行研究。 注意點: 伺服器(比如臺式電腦)的IP為1.1.1.2,那麼客戶端(其他裝置,比如手機,Ipad)連線的一定是

C#.網路程式設計 Socket基礎 基於WinForm系統Socket TCP協議 實現伺服器客戶.txt.word.png等不同型別檔案傳輸

一、簡介: 前面的兩篇介紹了字串傳輸、圖片傳輸: 其實,本文針對Socket基礎(二)進一步完成,以便可以進行多種檔案傳輸。 二、基於不同的流(檔案流、記憶體流、網路等)讀寫。 1、圖片傳輸 方法一:(在客戶端用檔案流傳送(即將圖片寫到檔案流去,以便傳送),

Windows C語言 UDP程式設計 server伺服器客戶--初級簡單版

UDP協議全稱是使用者資料報協議[1] ,在網路中它與TCP協議一樣用於處理資料包,是一種無連線的協議。在OSI模型中,在第四層——傳輸層,處於IP協議的上一層。UDP有不提供資料包分組、組裝和不能對資料包進行排序的缺點,也就是說,當報文傳送之後,是無法得知其

Linux學習網路程式設計TCP相關基礎知識

言之者無罪,聞之者足以戒。 - “詩序”、 1、網路位元組序: 在TCP的編寫過程中需要從網路位元組序轉換到主機位元組序,當然也需要從主機位元組序轉換到網路位元組序 htons 把 unsigned short型別從主機序轉換到網路序htonl把unsigned long型別從

libevent簡單介紹以及使用帶有伺服器客戶

這兩天使用了下libevent,只使用了網路IO事件(EV_READ和 EV_WRITE),查閱了下libevent的介面文件,這裡做點筆記,並附上程式碼,開發環境是win7+vs2010 這裡只介紹需要用到的libevent的介面函式,更多介面函式請檢視libevent官方文件 如果想了解

socket網路程式設計伺服器客戶通訊失敗的問題

伺服器程式碼如下 public class server { public static void main(String[] args) throws IOException { ServerSocket server=new S

網路程式設計——伺服器客戶資訊的獲取

  目錄 1、字串IP地址和二進位制IP地址結構的轉換 2.套接字檔案描述符的判定 3、IP地址與域名之間的相互轉換 4、協議名稱處理函式 1、字串IP地址和二進位制IP地址結構的轉換 #include <sys/socket.h> #inclu

Linux學習網路程式設計多程序併發伺服器

言之者無罪,聞之者足以戒。 - “詩序” 上面我們所說過的通訊都是一個伺服器一個客戶端之間的通訊,下面我們來交流一下多程序併發伺服器的相關知識 邏輯上就是這個樣子的,就是一個伺服器多個客戶端進行資料的傳輸。 1、傳送資料的函式: ssize_t send(int sockfd,

Linux學習網路程式設計epoll的用法

言之者無罪,聞之者足以戒。 - “詩序” epoll相關的函式包含在標頭檔案<sys/epoll.h> epoll是Linux核心為處理大批量控制代碼而作了改進的poll,是Linux下多路複用IO介面select/poll的增強版本,它能顯著減少程式在大量併發連線中只有少量活躍

Linux學習網路程式設計select

言之者無罪,聞之者足以戒。 - “詩序” 1、阻塞式I/O 下面看一下實現的邏輯: 2、非阻塞式I/O 下面看一下實現的邏輯: 3、I/O複用(select/epoll) (1)  int  select (int maxfdp, fd_set

Linux學習網路程式設計UDP程式設計

言之者無罪,聞之者足以戒。 - “詩序” 前幾篇文章說的都是TCP通訊的問題,這篇文章說一下UDP通訊的相關內容: 下面來看一下基於UDP的獲取時間的客戶伺服器的程式框圖: (1)、建立一個基於IPv4(AF_INET)的資料報套接字(SOCK_DGRAM) (2)、ssize

Linux學習網路程式設計TCP程式設計 模型總結

言之者無罪,聞之者足以戒。 - “詩序” TCP通訊也就是伺服器和客戶端的一種通訊方式,它的整體框架為: 針對TCP通訊所用到的函式,我來做一下說明: (1)插座創造一個套接字 int socket(int domain,int type,int protocol) 標頭檔

Linux學習網路程式設計TCP三次握手四次揮手

言之者無罪,聞之者足以戒。 - “詩序” 1、三次握手: 看一下三次握手的框圖: (1)、伺服器必須準備好接受外來連線 (2)、客戶端呼叫connect來主動開啟一個連線,此時客戶端TCP將會發送一個SYN分節 (3)、伺服器必須確認客戶的SYN (4)、客戶必須確認伺

Linux學習網路程式設計TCP程式設計

言之者無罪,聞之者足以戒。 - “詩序” 1,TCP是什麼? TCP傳輸控制協議 向用戶程序提供可靠的全雙工位元組流(位元組流:給每一個位元組編序) 2,UDP是什麼? UDP使用者資料報協議 是一種無連線的協議 3,獲取時間服務的客戶端 (1),建立一個的的I

C語言指標筆記1

指標(pointer)是C語言中最重要的概念之一,用於儲存變數的地址。 1.&運算子 (1)一元&運算子可給出變數的儲存地址。如過pooh是變數名,那麼&pooh是變數地址。 (2)如下例所示,使用運算子檢視不同函式中的同名變數儲存在什麼位置。 原始碼: //檢視

在Scala中使用函數語言程式設計函式高階函式

                                            圖示,這是一個普通

C語言面向物件程式設計:封裝與繼承

最近在用 C 做專案,之前用慣了 C++ ,轉回頭來用C 還真有點不適應。 C++ 語言中自帶面向物件支援,如封裝、繼承、多型等面向物件的基本特徵。 C 原本是面向過程的語言,自身沒有內建這些特性,但我們還是可以利用 C 語言本身已有的特性來實現面向物件的一些基本特徵。接下來