2020年4月19日 星期日

C 語言 - #ifndef

#ifndef 用途

  • 在 .h 檔確保只會被編譯一次
  •     #ifndef HELLO_H // 有些人會定義成 _HELLO_H_
        #define HELLO_H // 但目的就是不會被重複編譯
    
        #include <stdlib.h>
    
        int helloIntro(char** str);
        int main() __attribute__((weak));
    
        #endif

C 語言 - 編譯多個含有 main function 的 C code

編譯多個含有 main function 的 C code


    理論上是不行,GCC 無法自行繞過某某函式去編譯,通常是給條件去讓編譯器來達到 "只有一個你想要的 main function" 編譯目的。有人會問為什麼會有多個 main function,我想多半是因為想 Debug。

1. 利用 #ifdef

  • other.c
  •     #ifdef DEBUG
        int main ()
        {
            return 0;
        }
        #endif
  • gcc
  •     gcc -DEBUG other.c -o other.x

2. 利用 __attribute__((weak))

  • other.h ( __attribute__((weak)) 只能在宣告 function 時作 )
  •     int main() __attribute__((weak));
  • other.c
  •     int main ()
        {
            return 0;
        }

參考資料 :
https://stackoverflow.com/questions/35510670/compile-c-code-without-its-main-function

2020年4月14日 星期二

C 語言 - sprintf / snprintf

sprintf (char *s, const char *format, ...)

    C 語言並沒有其他語言方便的 container 去作字串轉換,所以 sprintf 就顯得強大許多。原理就是 printf 但輸入到字串。但會有 overflow 的 issue 產生。
    int main()
    {
        char str[5];
        sprintf(str, "ABC");
        printf("%s\n", str); // output : ABC
        return 0;
    }
    int main()
    {
        char str[5];
        sprintf(str, "ABCDEF");
        printf("%s\n", str); // output : ABCDEF
        return 0;
    }

snprintf (char *s, size_t maxlen, const char *format, ...)

    snprintf 多了一個參數去限制寫入長度(包含'\0'),安全許多。另外我是用 gcc 編譯的,snprintf 會回傳寫入字串的長度 (不包含'\0'),所以當回傳值大於等於 maxlen,則代表字串被切了。
    int main()
    {
        int ret;
        char str[5];
        ret = snprintf(str, 5, "ABC");
        printf("%s\n", str); // output : ABC
        printf("%d\n", ret); // output : 3
        return 0;
    }/code>
    int main()
    {
        int ret;
        char str[5];
        ret = snprintf(str, 5, "ABCDEF");
        printf("%s\n", str); // output : ABCD
        printf("%d\n", ret); // output : 6
        return 0;
    }


參考資料:
https://blog.xuite.net/tzeng015/twblog/113272245-snprintf
https://linux.die.net/man/3/snprintf

2020年4月13日 星期一

C 語言 - Linux System Log

Linux - System Log

    Linux 當事件發生會產生 log,通常會存在 /var/log 底下。優先度如下。
  •     debug
  •     info
  •     notice
  •     warning
  •     err
  •     crit
  •     alert
  •     emerg/panic

C 實作 - void syslog(int priority, const char *format, ...)

    #include<stdio.h>
    #include<stdlib.h>
    #include<syslog.h> 
    syslog(LOG_INFO, "hello %s", "woring");
    syslog(LOG_ERR,  "hello %s", "test");
底下為參數 int priority
LOG_USER : A miscellaneous user process
LOG_MAIL : Mail
LOG_DAEMON : A miscellaneous system daemon
LOG_AUTH : Security (authorization)
LOG_SYSLOG : Syslog
LOG_LPR : Central printer
LOG_NEWS : Network news (e.g. Usenet)
LOG_UUCP : UUCP
LOG_CRON : Cron and At
LOG_AUTHPRIV : Private security (authorization)
LOG_FTP : Ftp server
LOG_LOCAL(0~7) : Locally defined

參考資料 :
https://ithelp.ithome.com.tw/articles/10159084
http://yu-minspace.blogspot.com/2007/09/linux-syslogd-openlogsyslogdsyslog.html

2020年4月12日 星期日

C 語言 - __attribute__((weak))

使用的情境

    假設我們不知道外部是否會提供 foo() 這個 function,若沒有則用自己的 foo()。
    extern int func(void);
    int __attribute__((weak)) func(void)
    {
        return 0;
    }

備註 - 不會在動態函式庫 (.so) 中生效

    string.so
    void real_func()
    {
        printf("strong func\n");
    }
    weak.so
    void real_func() __attribute__((weak))
    {
        printf("weak func\n");
    }
    main.c
    extern void real_func();
    void main()
    {
        real_func();
    }
結果 :
    // 動態連結無效,只看順序
    gcc main.c -lstrong -lweak // 輸出 : strong func
    gcc main.c -lweak -lstrong // 輸出 : weak func

    // 正常 .o 檔
    gcc main.c weak.o strong.o // 輸出 : strong func
    gcc main.c strong.o weak.o // 輸出 : strong func


參考資料 :
https://www.itread01.com/content/1541531526.html

Popular Posts