![]() |
||
Golden Member
![]() ![]() ![]() ![]() 加入日期: Feb 2004 您的住址: 從來處來
文章: 2,762
|
玩玩 c 指標
這沒什麼特別意義,純粹好玩而已,以前我故意弄一些很複雜的指標,試試能不能編譯。
後來想說能不能用這些莫名奇妙的指標寫出程式,結果發現可以的。 最近拿出重看,再小改一下.... 其實我也覺得很訝異,這樣也能寫出程式。 ![]() 代碼:
#include <stdio.h> #include <string.h> #include <stdlib.h> /* func1 is a function which returns a pointer to a function, whose parameter type is char and returning type is void. */ void (*func1(int))(char); void (*(*func11)(int))(char); // func11 is a pointer to a func1-typed function. /* func2 is an array of 3 elements, which contents are pointers to functions whose parameter type is int and returning type is void. */ void (*func2[3])(int); /* Combine func1 and func2. */ void (*(*func3[3])(int))(char); /* func4 is a pointer to a function which takes int as argument and returns a pointer to an array of 3 elements, which are pointers to char values. */ char *(*(*func4)(int))[3]; char (*func41(int))[30]; char (*(*func42)(int))[30]; char *(*func43(int))[3]; /* %$#^%@........ */ char *(*(*func5)(char *(*(*func6)(int))[3]))(void (*(*func7)[3])(int)); void (*(*func71)[3])(int); void func1_1(char c) { printf("You input letter '%c'.\n", c); } void func1_2(char c) { printf("You input letter '%c', and its next letter is '%c'.\n", c, c+1); } void (*func1(int v))(char c) { if(v % 2) return func1_1; else return func1_2; } void func2_1(int i) { printf("You got an integer '%d'.\n", i); } void func2_2(int i) { int randnum = rand() % 10 + 1; printf("Your integer multiplied by %d is: '%d'.\n", randnum, i*randnum); } void func2_3(int i) { printf("Your integer is an %s number.\n", i&1? "odd": "even"); } void (*func3_1(int v))(char c) { printf("You've entered func3_1: "); if(v % 2) return func1_1; else return func1_2; } void (*func3_2(int v))(char c) { printf("You've entered func3_2: "); if(v > 50) return func1_1; else return func1_2; } void (*func3_3(int v))(char c) { printf("You've entered func3_3: "); if(v % 3) return func1_1; else return func1_2; } char (*func41(int s))[30] { int i; char (*strs)[30]; strs = (char (*)[])malloc(sizeof(char) * s * 30); for( i = 0; i < s; i++ ) sprintf(strs[i], "This is string %d.\n", i); return strs; } char *(*func43(int s))[3] { int i, j; char *(*strs)[3]; char tmpstr[30]; strs = (char *(*)[])malloc(sizeof(char *) * s * 3); for( i = 0; i < s; i++ ) { for( j = 0; j < 3; j++ ) { sprintf(tmpstr, "You got string %d, %d.\n", i, j); strs[i][j] = strdup(tmpstr); } } return strs; } char *func5_2(void (*(*func7)[3])(int)) { int i, ri; printf("Here is %s():\n", __func__); ri = rand() % 100 + 1; for( i = 0; i < 3; i++) (*func7)[i](ri); return "\nAt the end of this day, one shall stand, one shall fall!\n"; } char *(*func5_1(char *(*(*func6)(int))[3]))(void (*(*func7)[3])(int)) { int i, j; char *(*tstrp)[3]; tstrp = func6(2); for( i = 0; i < 2; i++) { for( j = 0; j < 3; j++) { printf("func6: %s", tstrp[i][j]); free(tstrp[i][j]); } } free(tstrp); return func5_2; } int main(int argc, char *argv[]) { int i, j, ri; void (*pfunc)(char); // Test of func1 and func11 printf("Test func1 and func11:\n"); func11 = func1; pfunc = func1(1); pfunc('A'); pfunc = func11(2); // Since func11 is a pointer to a function, (*func11)(2) is the correct format, but simplified form func11(2) is also valid. pfunc('A'); /* Results: Test func1 and func11: You input letter 'A'. You input letter 'A', and its next letter is 'B'. */ // Test of func2 printf("\nTest func2:\n"); func2[0] = func2_1; func2[1] = func2_2; func2[2] = func2_3; srand(time(NULL)); ri = rand() % 100 + 1; for( i = 0; i < 3; i++) func2[i](ri); /* Results: Test func2: You got an integer '82'. Your integer multiplied by 4 is: '328'. Your integer is an even number. */ // Test of func3 printf("\nTest func3:\n"); func3[0] = func3_1; func3[1] = func3_2; func3[2] = func3_3; for( i = 0; i < 3; i++) { ri = rand() % 90 + 10; printf("%d: ", ri); pfunc = func3[i](ri); pfunc('A'); } /* Results: Test func3: 20: You've entered func3_1: You input letter 'A', and its next letter is 'B'. 93: You've entered func3_2: You input letter 'A'. 57: You've entered func3_3: You input letter 'A', and its next letter is 'B'. */ // Test of func41 printf("\nTest func41:\n"); char (*tstr)[30]; tstr = func41(3); for( i = 0; i < 3; i++) printf("%s", tstr[i]); free(tstr); /* Results: Test func41: This is string 0. This is string 1. This is string 2. */ // Test of func42 printf("\nTest func42:\n"); func42 = func41; tstr = func42(5); for( i = 0; i < 5; i++) printf("%s", tstr[i]); free(tstr); /* Results: Test func42: This is string 0. This is string 1. This is string 2. This is string 3. This is string 4. */ // Test of func43 printf("\nTest func43:\n"); char *(*tstrp)[3]; tstrp = func43(2); for( i = 0; i < 2; i++) { for( j = 0; j < 3; j++) { printf("%s", tstrp[i][j]); free(tstrp[i][j]); } } free(tstrp); /* Results: Test func43: You got string 0, 0. You got string 0, 1. You got string 0, 2. You got string 1, 0. You got string 1, 1. You got string 1, 2. */ // Test of func4 printf("\nTest func4:\n"); func4 = func43; tstrp = func4(2); for( i = 0; i < 2; i++) { for( j = 0; j < 3; j++) { printf("%s", tstrp[i][j]); free(tstrp[i][j]); } } free(tstrp); /* Results: Test func4: You got string 0, 0. You got string 0, 1. You got string 0, 2. You got string 1, 0. You got string 1, 1. You got string 1, 2. */ // Test of func71 printf("\nTest func71:\n"); func71 = &func2; ri = rand() % 100 + 1; for( i = 0; i < 3; i++) (*func71)[i](ri); /* Results: Test func71: You got an integer '62'. Your integer multiplied by 8 is: '496'. Your integer is an even number. */ // Test of func5 printf("\nTest func5:\n"); char *strp; char *(*pfunc2)(void (*(*func7)[3])(int)); func5 = func5_1; pfunc2 = func5(func43); strp = pfunc2(&func2); puts(strp); /* Results: Test func5: func6: You got string 0, 0. func6: You got string 0, 1. func6: You got string 0, 2. func6: You got string 1, 0. func6: You got string 1, 1. func6: You got string 1, 2. Here is func5_2(): You got an integer '38'. Your integer multiplied by 6 is: '228'. Your integer is an even number. At the end of this day, one shall stand, one shall fall! */ return 0; } |
|||||||
![]() |
![]() |
Golden Member
![]() ![]() ![]() ![]() 加入日期: Jun 2002 您的住址: 地獄18層
文章: 3,235
|
以前寫來玩玩的
給學生練習的 代碼:
<html> <body> <script type="text/javascript"> document.write("<table border=1>") for (i = 1; i <= 9; i++) { document.write("<tr>") for (j = 2; j <= 9; j++) { document.write("<td>" + j + "*" + i + "=" + j * i + "</td>") } document.write("</tr>") } document.write("</table>") </script> </body> </html>
__________________
徵你不要的AM4 CPU 徵你不要的SATA接頭斷裂SSD ![]() |
||
![]() |
![]() |
Major Member
![]() 加入日期: Aug 2001
文章: 211
|
其實 pointer to function 是很常用的東西,不過實務上我會盡量避免寫出有複雜指標的東西,因為不好維護。
如果會用 pointer to pointer 或 pointer to reference 一定有其理由存在,比如說要傳 pointer 給 function。
__________________
滿招損 謙受益 |
![]() |
![]() |
Basic Member
加入日期: Jan 2006
文章: 21
|
以前學生時代還懂點皮毛,現在工作要用到程式只會寫C# @@
|
![]() |
![]() |
Major Member
![]() 加入日期: Mar 2012
文章: 196
|
這樣也能寫出程式
![]() 引用:
|
|
![]() |
![]() |
Major Member
![]() 加入日期: Sep 2008
文章: 203
|
這看起來比較像是找工作面試的考題
![]() 記得之前我被一題打敗了 c = a+++b a ? b ? c ? 當然我 ![]() 不過實際coding在project時,寫成這樣大概會被...... ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
Golden Member
![]() ![]() ![]() ![]() 加入日期: Feb 2004 您的住址: 從來處來
文章: 2,762
|
引用:
這叫obfuscation吧, 還有專門的比賽,也算是一種趣味的程式競賽.... 不過其實可以用現有的程式做obfuscation. |
|
![]() |
![]() |
Advance Member
![]() ![]() 加入日期: Jul 2012 您的住址: 新竹
文章: 409
|
引用:
沒錯, 真正做事寫這種程式碼是等著被念而已... |
|
![]() |
![]() |
Major Member
![]() 加入日期: Aug 2001
文章: 211
|
引用:
C# 有 unsafe 關鍵字可以用指標,不過型別跟 C 似乎不是能夠完全對應,因為我曾用 C 寫 DLL,然後在 C# 裡用指標想直接取資料... 後來發現有問題,才改用別的方式。
__________________
滿招損 謙受益 |
|
![]() |
![]() |