壹
#include"xxx.c"咱們先體驗一波#include"xxx.c"文件能不能用: 1//FileName :main
2#include <stdio.h>
3#include <stdlib.h>
4
5/***************************
6 * .c文件聲明區域
7 **************************/
8#include"module1.c"
9#include"module2.c"
10
11/***************************
12 * Fuction: main
13 * Author :(最後一個bug)
14 **************************/
15int main(int argc, char *argv[]) {
16
17 Fuction1();
18 Fuction2();
19 printf("歡迎關注公眾號:最後一個bug\n");
20 return 0;
21}
1//FileName: Module1.c
2#include<stdio.h>
3/***************************
4 * Fuction: Fuction1
5 * Author :(最後一個bug)
6 **************************/
7void Fuction1()
8{
9 printf("Run Fuction1\n");
10}
1//FileName: Module2.c
2#include<stdio.h>
3/***************************
4 * Fuction: Fuction2
5 * Author :(最後一個bug)
6 **************************/
7void Fuction2()
8{
9 printf("Run Fuction2\n");
10}
看來這波操作可行,似乎還省去了.h文件,之前bug菌說過,分析.h文件的時候直接把.h文件在對應的.c文件中的位置處展開然後進一步分析即可,其實這.c文件也是如此,接著往下看。
1//FileName :main
2#include <stdio.h>
3#include <stdlib.h>
4
5char * cBug1 = "bugNo1"; //這裡是位置1
6char * cBug2 = "bugNo2";
7/***************************
8 * .c文件聲明區域
9 **************************/
10#include"module1.c"
11#include"module2.c"
12
13//char * cBug1 = "bugNo1";//這裡是位置2
14//char * cBug2 = "bugNo2";
15
16/***************************
17 * Fuction: main
18 * Author :(最後一個bug)
19 **************************/
20int main(int argc, char *argv[]) {
21
22 Fuction1();
23 Fuction2();
24 printf("歡迎關注公眾號:最後一個bug\n");
25 return 0;
26}
1//FileName: Module2.c
2#include<stdio.h>
3/***************************
4 * Fuction: Fuction1
5 * Author :(最後一個bug)
6 **************************/
7void Fuction1()
8{
9 printf("Run Fuction1\n");
10 printf("%s\n",cBug1);
11}
1//FileName: Module2.c
2#include<stdio.h>
3/***************************
4 * Fuction: Fuction2
5 * Author :(最後一個bug)
6 **************************/
7void Fuction2()
8{
9 printf("Run Fuction2\n");
10 printf("%s\n",cBug2);
11}
我們在位置1進行兩個變量的定義,成功編譯運行得到如上的結果,符合我們的預期,然而當我們去掉位置1進行位置2的定義,程序卻無法進行編譯,看來跟我們預期在編譯過程中直接展開.c文件是一致的。
這種方式在bug菌的編碼歷史長河中一般只在兩種情況下用到:有些歷史悠久的項目經過了N多位大佬的蹂躪,說實在的代碼結構上已經非常可怕了,往往每個源文件內容非常之長,為了保持代碼原樣,會採用#include"xxx.c"把這幾的相關文件嵌入進去,也便於自己後期維護。
在前期進行軟體調試的時候可能自己會在不同的文件中安插不同測試功能函數,通過這樣方法可以方便的引入和剔除。
比如說你需要對源文件中的一些靜態變量進行相關的監控處理,然而又不想在本文件中增加測試代碼,於是便可以在#include"xxx.c"中進行測試函數的編寫來供使用,比如 :
1//FileName :main
2#include <stdio.h>
3#include <stdlib.h>
4
5static int a = 5;
6/***************************
7 * .c文件聲明區域
8 **************************/
9#include"module1.c"
10
11/***************************
12 * Fuction: main
13 * Author :(最後一個bug)
14 **************************/
15int main(int argc, char *argv[]) {
16
17 Fuction1();
18 printf("main %d\n",a);
19 printf("歡迎關注公眾號:最後一個bug\n");
20 return 0;
21}
1//FileName: Module2.c
2#include<stdio.h>
3/***************************
4 * Fuction: Fuction1
5 * Author :(最後一個bug)
6 **************************/
7void Fuction1()
8{
9 printf("Run Fuction1\n");
10 printf("Fuction1 %d\n",a);
11}
貳
voidvoid在大部分小夥伴的程序中都只是用於函數無參數傳入,或者無類型返回。然而我們平時所定義的變量都會有具體的類型,int,float,char等等,那是否有void類型的變量呢?大家可以動手實驗一下,答案是:不行,編譯會出錯。上圖很明顯編譯器不允許定義void類型的變量,變量都是需要佔用一定內存的,既然void表示無類型,編譯器自然也就不知道該為其分配多大的內存,於是造成編譯失敗。雖然void不能直接修飾變量,但是其可以用於修飾指針的指向即無類型指針void*,無類型指針那就有意義了,無類型指針不是一定要指向無類型數據,而是可以指向任意類型的數據。大家其實在使用動態內存分配的使用就已經遇到了void *的使用,來我們一起看看如下幾個標準函數的原型定義:上面這些函數都是與內存操作有關的函數,可能一些小夥伴使用過也不一定知道每個參數的具體類型是什麼,這些void*部分的形參所傳入的實參都是不需要進行強制類型轉化的,所以根本就不需要關注傳入指針所指向的具體類型,然而函數所返回的void *一般都需要通過強制類型轉化為對應的具體類型,除非你最後所傳遞的變量也是void*類型。 1#include <stdio.h>
2#include <stdlib.h>
3#include <malloc.h>
4
5#define NUM 10
6/*************************************
7 * Fuction:了解一下void*的使用
8 * Author : (最後一個bug)
9 *************************************/
10int main(int argc, char *argv[]) {
11 int *p1 = (int *)malloc(NUM*sizeof(int));
12 int *p2 = (int *)malloc(NUM*sizeof(int));
13 int i = 0;
14
15 //初始化p1
16 for(i = 0;i < NUM;i++)
17 {
18 *(p1+i) = i;
19 }
20 //進行內存copy
21 memcpy(p2,p1,NUM*sizeof(int));
22
23 //輸出另外一個分配的內存
24 for(i = 0;i < NUM;i++)
25 {
26 printf("%d,",*(p2+i));
27 }
28 //釋放內存
29 free(p1);
30 free(p2);
31 return 0;
32}
1#include <stdio.h>
2#include <stdlib.h>
3/**********************************
4 * Fuction : add
5 * descir : 加法的相關數據及處理辦法
6 * Author : (最後一個bug)
7 **********************************/
8typedef struct _tag_Add
9{
10 int a;
11 int b;
12 int result;
13}sAdd;
14
15void Add(void *param)
16{
17 sAdd *p = (sAdd *) param;
18 p->result = p->a + p->b;
19}
20/**********************************
21 * Fuction : add
22 * descir : 乘法的相關數據及處理辦法
23 * Author : (最後一個bug)
24 **********************************/
25typedef struct _tag_Mul
26{
27 float a;
28 float b;
29 float result;
30}sMul;
31
32void Mul(void *param)
33{
34 sMul *p = (sMul *) param;
35 p->result = p->a * p->b;
36}
37
38/*************************************
39 * Fuction : sCal
40 * descir : 公共的調用接口
41 * Author : (最後一個bug)
42 ************************************/
43void sCal(void *param,void *fuc)
44{
45 ((void (*)(void*))fuc)(param);
46}
47
48/**********************************
49 * Fuction : main
50 * descir : 應用接口實例
51 * Author : (最後一個bug)
52 **********************************/
53int main(void)
54{
55 sAdd stAdd;
56 sMul stMul;
57
58 //數據初始化
59 stAdd.a = 10;
60 stAdd.b = 20;
61
62 stMul.a = 5;
63 stMul.b = 5;
64 //接口直接用
65 sCal(&stAdd,Add);
66 sCal(&stMul,Mul);
67 //對應的輸出
68 printf("a + b = %d\n",stAdd.result);
69 printf("a * b = %f\n",stMul.result);
70 printf("公眾號:最後一個bug\n");
71 return 0;
72 }
叄
「 逗號表達式 」 1#include <stdio.h>
2#include <stdlib.h>
3/******************************************
4 * Fuction: Main
5 * Descir : 測試一個逗號表達式
6 * Author :(最後一個bug)
7 *****************************************/
8int main(int argc, char *argv[]) {
9 int Val = 1;
10
11 Val = ++Val,Val+10,Val*10; //逗號表達式
12
13 printf("Val = %d",Val);
14
15 return 0;
16}
大家在平時閱讀代碼的時候應該都是按照從左至右,然後從上至下來的方式吧。基本上一個分號結束一行的書寫,由於電腦屏幕的限制,有效代碼暴露在人的視野中是有限的,同時人瞬間記憶時間也是有限的,如果在一個小小的屏幕上閱碼勢必會阻礙程式設計師的閱讀和理解,比如下面兩種書寫方式:
1/******************************************
2 * Fuction: 非逗號表達式書寫
3 * Descir :
4 * Author :(最後一個bug)
5 *****************************************/
6if(IsOk())
7{
8 sOkProc();
9 return GetOkCode();
10}
11else
12{
13 sNoProc();
14 return GetNoCode();
15}
16/******************************************
17 * Fuction: 採用逗號表達式書寫
18 * Descir :
19 * Author :(最後一個bug)
20 *****************************************/
21return (IsOk())?(sOkProc(),GetOkCode()):(sNoProc(),GetNoCode());
上面是兩種代碼書寫方式,第一種佔據了多行,而第二種進佔據一行,這樣同樣一個屏幕所容納的有效代碼第一種就明顯少於第二種方式,所以很多程式設計師都會選擇使用一種大長屏或者多屏進行開發。
第二種方式似乎很多小夥伴覺得代碼不夠美觀,也不便於維護,其實這僅僅只是一種習慣罷了,就好像編碼的時候 : 第一個大括號是否需要另外起一行,或者是使用==號一定要像if( 1== b)這樣把數據放左邊,當你習慣了這種編碼風格也會覺得用第二方式來得直接。
下面為大家介紹幾個用逗號表示式比較多的地方:
1#include <stdio.h>
2#include <stdlib.h>
3#define ROW_NUM (5)
4#define LINE_NUM (5)
5/******************************************
6 * Fuction: Main
7 * Descir :for 遍歷查找
8 * Author :(最後一個bug)
9 *****************************************/
10int main(int argc, char *argv[]) {
11 int i = 0,j = 0;
12 int Matrix[ROW_NUM][LINE_NUM] ={{1,1,1,1,1},\
13 {2,2,2,2,2},\
14 {3,3,3,3,3},\
15 {4,4,4,4,4},\
16 {5,5,5,5,5},\
17 };
18
19 for(i = 0,j = 0;(i < ROW_NUM)&&(j < LINE_NUM);i++,j += 2)
20 {
21 printf("Matrix[%d][%d] = %d\n",i,j,Matrix[i][j]);
22 }
23 printf("公眾號:最後一個bug\n");
24 return 0;
25}
1#include <stdio.h>
2#include <stdlib.h>
3/******************************************
4 * Fuction: Main
5 * Descir :弱化++前後問題
6 * Author :(最後一個bug)
7 *****************************************/
8int main(int argc, char *argv[]) {
9 int i = 0;
10
11 //1、常規操作
12 i = 0;
13 while(++i < 3)
14 {
15 printf(" i = %d\n",i);
16 }
17 printf("*****************\n");
18
19 i = 0;
20 while(i++ < 3)
21 {
22 printf(" i = %d\n",i);
23 }
24 printf("*****************\n");
25
26 //2、逗號表達式處理一下
27 i = 0;
28 while( i++,i < 3)
29 {
30 printf(" i = %d\n",i);
31 }
32 printf("*****************\n");
33
34 i = 0;
35 while( ++i,i < 3)
36 {
37 printf(" i = %d\n",i);
38 }
39 printf("*****************\n");
40
41 printf("公眾號:最後一個bug\n");
42 return 0;
43}
44
1#include <stdio.h>
2#include <stdlib.h>
3
4#define GET_INDEX(a ,b) ( a+= 2,a + b)
5/******************************************
6 * Fuction: Main
7 * Descir : 簡化宏
8 * Author :(最後一個bug)
9 *****************************************/
10int main(int argc, char *argv[]) {
11 int i = 0,Val = 0;
12 int Param1 = 0, Param2 = 0;
13 int Matrix[5] ={5,5,5,5,5};
14
15 printf(" Matrix = %d\n",Matrix[GET_INDEX(Param1,Param2)]);
16 printf("公眾號:最後一個bug\n");
17 return 0;
18}
逗號表達式其實就是橫向編碼的一種方式,能夠讓程式設計師更好的利用一行的空間,使得代碼更加緊湊,所以使用逗號表達式並沒炫技,而是增強了代碼的靈活度,不過話說回來逗號表達式在C混亂編碼大賽上的使用頻度是非常之高的。
分享C/C++技術文章