*C [#hb6b6e11] //#ref(http://upload.wikimedia.org/wikipedia/commons/thumb/9/95/The_C_Programming_Language%2C_First_Edition_Cover_%282%29.svg/200px-The_C_Programming_Language%2C_First_Edition_Cover_%282%29.svg.png,right,around,nolink,C) #ref(http://upload.wikimedia.org/wikipedia/commons/thumb/3/35/The_C_Programming_Language_logo.svg/200px-The_C_Programming_Language_logo.svg.png,right,around,nolink,C) &color(White,#5F2F2F){ ''◆目次◆'' };&br; #contents *C11 [#k4c5d2ad] -[[Wikipedia.ja:C言語]] -[[C言語 - Wikibooks:http://ja.wikibooks.org/wiki/C%E8%A8%80%E8%AA%9E]] -[[苦しんで覚えるC言語:http://9cguide.appspot.com/]] -[[C言語は今でも価値のある言語か?:http://www.infoq.com/jp/news/2013/01/C-Language]] -[[[SDK] プロセスの列挙:http://shoppers-jp.com/tech/sdk037.html]] -[[コマンドライン引数の取得(プロセスファイルシステムを利用する) - Linux/C/C++ Tips:http://lldev.jp/linux_c_cpp/tips/pfs_cmdline.html]] -http://stackoverflow.com/questions/1585989/how-to-parse-proc-pid-cmdline -http://cx20.main.jp/blog/hello/category/win32-api/ -http://cx20.main.jp/blog/hello/2012/06/ -[[Wikipedia.ja:呼出規約]] -[[桂田研卒研ノート:http://nalab.mind.meiji.ac.jp/~mk/labo/text/]] -[[CからFortranルーチンを呼び出す:http://phase.hpcc.jp/phase/o2k/technical_doc_library/docs/porting/fortranfromc.html]] -[[11.1.4 ルーチン名の下線 (Sun Studio 12: Fortran プログラミングガイド):http://docs.oracle.com/cd/E19205-01/820-1203/aeula/index.html]] -[[C言語機能の比較:http://www.6809.net/tenk/?C%E8%A8%80%E8%AA%9E%E6%A9%9F%E8%83%BD%E3%81%AE%E6%AF%94%E8%BC%83]] **処理系 [#d2633a16] -[[GCC, the GNU Compiler Collection - GNU Project - Free Software Foundation (FSF):http://gcc.gnu.org/]] --[[MinGW]] --[[Cygwin]] -[["clang" C Language Family Frontend for LLVM:http://clang.llvm.org/]] -[[Microsoft Visual Studio Express]] --[[C99 library support in Visual Studio 2013:http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx]] -[[TCC : Tiny C Compiler:http://bellard.org/tcc/]] **ライブラリ・フレームワーク [#w5f859a1] -[[GTK+:http://www.gtk.org/]] **IDE・エディタ [#vaa4f864] ***フリーソフトウェア (オープンソースソフトウェア) [#n4409bbb] -[[Eclipse]] --[[Eclipse CDT:http://www.eclipse.org/cdt/]] -[[Emacs]] -[[Vim]] -[[Notepad++]] -[[サクラエディタ]] *C から Fortran の関数を呼び出す [#x01bff9e] Fortran の関数 ---- -fsin.f90 ---- pure function f_sin(x) result(y) bind(c, name='f_sin') use, intrinsic :: iso_c_binding real(kind=c_double), value :: x real(kind=c_double) :: y y = sin(x) end function f_sin ---- elemental pure function f_sin(x) result(y) bind(c, name='f_sin') とするとエラーになります.~ $ gfortran -c fsin.f90 $ nm fsin.o 00000000 b .bss 00000000 d .data 00000000 r .eh_frame 00000000 r .rdata$zzz 00000000 t .text 00000000 T _f_sin U _sin C の関数 ---- -sin.c ---- #include <stdio.h> #define _USE_MATH_DEFINES #include <math.h> extern double f_sin(double); int main(int argc, char** argv) { double x = M_PI * 0.5; printf("f_sin(%f) = %f\n", x, f_sin(x)); printf("sin(%f) = %f\n", x, sin(x)); return 0; } ---- $ gcc -o sin sin.c fsin.o $ ./sin f_sin(1.570796) = 1.000000 sin(1.570796) = 1.000000 *コマンドライン引数から整数 N を取得して標準出力に 1 から N までの和を出力 &aname(nsum); [#w46fe110] [[任意精度演算>Wikipedia.ja:任意精度演算]]を扱うためのライブラリである [[GMP:http://gmplib.org/]] を使用すると C で簡単に記述できます.~ ---- -nsum.c ---- // vim: ts=4 sw=4 expandtab: // gcc -Wall -Ofast -march=native -std=c11 -static -o nsum nsum.c -lgmp // gcc -Wall -Ofast -march=native -std=c11 -static -DNSUM1 -o nsum nsum.c -lgmp #include <ctype.h> #include <stdbool.h> #include <stdio.h> #include <string.h> #include <gmp.h> void usage(const char* restrict); bool valid_number(const char* restrict); void nsum1(const char* restrict); void nsum2(const char* restrict); void usage(const char* restrict s) { fprintf(stderr, "usage: %s N ...\n", s); } bool valid_number(const char* restrict s) { for (int i = 0; i < strlen(s); i++) { if (!isdigit(s[i])) { return false; } } return true; } void nsum1(const char* restrict s) { mpz_t n; mpz_t k; mpz_t inc; mpz_t arg; mpz_init_set_str(inc, "1", 10); mpz_init_set_str(k, "1", 10); mpz_init_set_str(n, "0", 10); mpz_init_set_str(arg, s, 10); while (mpz_cmp(k, arg) <= 0) { mpz_add(n, n, k); mpz_add(k, k, inc); } gmp_printf("Sum from 1 to %Zd = %Zd\n", arg, n); mpz_clear(arg); mpz_clear(inc); mpz_clear(k); mpz_clear(n); } void nsum2(const char* restrict s) { mpq_t n; mpq_t k; mpq_t inc; mpq_t arg; mpq_init(n); mpq_init(k); mpq_init(inc); mpq_init(arg); mpq_set_str(inc, "1", 10); mpq_set_str(k, "1/2", 10); mpq_set_str(n, "0", 10); mpq_set_str(arg, s, 10); mpq_add(n, arg, inc); mpq_mul(n, n, arg); mpq_mul(n, n, k); gmp_printf("Sum from 1 to %Qd = %Qd\n", arg, n); mpq_clear(arg); mpq_clear(inc); mpq_clear(k); mpq_clear(n); } int main(int argc, char** argv) { void (*nsum)(const char* restrict); if (argc < 2) { usage(argv[0]); return 2; } #if defined (NSUM1) nsum = nsum1; #else nsum = nsum2; #endif for (int i = 1; i < argc; i++) { if (valid_number(argv[i]) == false) { continue; } nsum(argv[i]); } return 0; } ---- *[[fwdsumatrapdf>SumatraPDF/fwdsumatrapdf]] &aname(fwdsumatrapdf); [#be8d6381] **C, C++ 版 [#a48a3eb3] C, C++ 版は他の言語で作られたバイナリよりも高速に動作します.~ [[MinGW]] の GCC でビルドできます.~ C の場合 $ cd /c/w32tex/bin $ gcc -std=c11 -static -o fwdsumatrapdf.exe fwdsumatrapdf.c -luser32 -lshell32 -ladvapi32 -lshlwapi C++ の場合 $ cd /c/w32tex/bin $ g++ -std=c++11 -static -o fwdsumatrapdf.exe fwdsumatrapdf.cpp -luser32 -lshell32 -ladvapi32 -lshlwapi Clang/LLVM でもビルド可能です.~ C の場合 $ cd /c/w32tex/bin $ clang -std=c11 -static -o fwdsumatrapdf.exe fwdsumatrapdf.c -luser32 -lshell32 -ladvapi32 -lshlwapi C++ の場合 $ cd /c/w32tex/bin $ clang++ -std=c++11 -static -o fwdsumatrapdf.exe fwdsumatrapdf.cpp -luser32 -lshell32 -ladvapi32 -lshlwapi Microsoft Visual Studio Express の C/C++ Optimizing Compiler for x86/x64 でもビルド可能です.~ C の場合 >cd /d c:\w32tex\bin >cl fwdsumatrapdf.c user32.lib advapi32.lib shlwapi.lib C++ の場合 >cd /d c:\w32tex\bin >cl fwdsumatrapdf.cpp user32.lib advapi32.lib shlwapi.lib ---- -C:\w32tex\bin\fwdsumatrapdf.c -C:\w32tex\bin\fwdsumatrapdf.cpp ---- /* vim: ts=4 sw=4 expandtab: * * MinGW * $ gcc -std=c11 -static -o fwdsumatrapdf.exe fwdsumatrapdf.c -luser32 -lshell32 -ladvapi32 -lshlwapi * $ g++ -std=c++11 -static -o fwdsumatrapdf.exe fwdsumatrapdf.cpp -luser32 -lshell32 -ladvapi32 -lshlwapi * * Clang/LLVM * $ clang -std=c11 -static -o fwdsumatrapdf.exe fwdsumatrapdf.c -luser32 -lshell32 -ladvapi32 -lshlwapi * $ clang++ -std=c++11 -static -o fwdsumatrapdf.exe fwdsumatrapdf.cpp -luser32 -lshell32 -ladvapi32 -lshlwapi * * Microsoft Visual Studio Express * >cl fwdsumatrapdf.c user32.lib advapi32.lib shlwapi.lib * >cl fwdsumatrapdf.cpp user32.lib advapi32.lib shlwapi.lib */ #include <windows.h> #include <shlwapi.h> #include <ddeml.h> #if !defined (_MSC_VER) #include <shellapi.h> #endif #if defined (__cplusplus) #include <cstdio> #include <cstring> #include <cstdlib> #include <cwchar> #include <cerrno> #include <clocale> using namespace std; #else #include <stdio.h> #include <string.h> #include <stdlib.h> #include <wchar.h> #include <errno.h> #include <locale.h> #endif #if defined (__cplusplus) #define restrict #elif defined (_MSC_VER) && (_MSC_VER >= 1400) #define restrict __restrict #elif defined (__STDC_VERSION__) && (__STDC_VERSION__ < 199901L) #define restrict #endif #if defined (_MSC_VER) #if (_MSC_VER >= 1400) #define snwprintf(buffer, count, format, ...) _snwprintf_s(buffer, count, _TRUNCATE, format, __VA_ARGS__) #else #define snwprintf _snwprintf #endif #endif HDDEDATA CALLBACK SumatraDdeCallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD); BOOL CALLBACK GetSumatraHWND(HWND, LPARAM); static int RunSumatraPDF(const wchar_t* restrict); static int DdeExecute(const wchar_t* restrict, const wchar_t* restrict, const wchar_t* restrict); #define FWDSUMATRAPDF_BUF_SIZE 1024 #define TIMEOUT 10000 static BOOL existSumatraHWND = FALSE; HDDEDATA CALLBACK SumatraDdeCallback(UINT uType, UINT uFmt, HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hdata, DWORD dwData1, DWORD dwData2) { return NULL; } BOOL CALLBACK GetSumatraHWND(HWND hwnd, LPARAM lParam) { wchar_t* title = NULL; wchar_t windowText[FWDSUMATRAPDF_BUF_SIZE] = L""; UNREFERENCED_PARAMETER(lParam); GetWindowTextW(hwnd, windowText, FWDSUMATRAPDF_BUF_SIZE); if (windowText[0] == L'\0') { return TRUE; } if ((title = wcsrchr(windowText, L'S')) == NULL) { return TRUE; } if (wcscmp(title, L"SumatraPDF") != 0) { return TRUE; } existSumatraHWND = TRUE; return TRUE; } static int RunSumatraPDF(const wchar_t* restrict pdf) { int err = 0; HKEY subKey = NULL; const wchar_t* keyPath = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\SumatraPDF.exe"; DWORD dwType = 0; DWORD sz = 0; wchar_t sumatrapdfRegistry[FWDSUMATRAPDF_BUF_SIZE] = L""; const wchar_t* sumatrapdfWin32Default = L"C:\\Program Files\\SumatraPDF\\SumatraPDF.exe"; const wchar_t* sumatrapdfWin64Default = L"C:\\Program Files (x86)\\SumatraPDF\\SumatraPDF.exe"; wchar_t* sumatrapdf = (wchar_t*)L"SumatraPDF.exe"; const wchar_t* reuseInstance = L"-reuse-instance"; wchar_t sumatrapdfCommandLine[FWDSUMATRAPDF_BUF_SIZE] = L""; static HWND hList; STARTUPINFOW si; PROCESS_INFORMATION pi; EnumWindows((WNDENUMPROC)GetSumatraHWND, (LPARAM)hList); if (existSumatraHWND == TRUE) { return err; } if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyPath, 0, KEY_QUERY_VALUE, &subKey) != ERROR_SUCCESS) { err = 1; } if (subKey != NULL) { if (RegQueryValueExW(subKey, NULL, NULL, &dwType, NULL, &sz) != ERROR_SUCCESS) { err = 1; } } if (subKey != NULL) { if (RegQueryValueExW(subKey, NULL, NULL, &dwType, (BYTE*)sumatrapdfRegistry, &sz) != ERROR_SUCCESS) { err = 1; } } if (subKey != NULL) { RegCloseKey(subKey); subKey = NULL; } if (err == 0) { if (wcslen(sumatrapdfRegistry) != 0) { if (PathFileExistsW(sumatrapdfRegistry)) { sumatrapdf = sumatrapdfRegistry; } else { err = 1; } } } if (err != 0) { err = 0; if (PathFileExistsW(sumatrapdfWin32Default)) { sumatrapdf = (wchar_t*)sumatrapdfWin32Default; } else if (PathFileExistsW(sumatrapdfWin64Default)) { sumatrapdf = (wchar_t*)sumatrapdfWin64Default; } else { sumatrapdf = (wchar_t*)L"SumatraPDF.exe"; } } #if defined (_MSC_VER) SecureZeroMemory(&si, sizeof(si)); SecureZeroMemory(&pi, sizeof(pi)); #else ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); #endif si.cb = sizeof(si); snwprintf(sumatrapdfCommandLine, FWDSUMATRAPDF_BUF_SIZE-1, L"\"%ls\" %ls \"%ls\"", sumatrapdf, reuseInstance, pdf); if (CreateProcessW(NULL, sumatrapdfCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0) { err = 3; return err; } WaitForInputIdle(pi.hProcess, TIMEOUT); return err; } static int DdeExecute(const wchar_t* restrict server, const wchar_t* restrict topic, const wchar_t* restrict command) { int err = 0; DWORD idInstance = 0; HSZ hszServer = NULL; HSZ hszTopic = NULL; HCONV hConvClient = NULL; HDDEDATA hDdeData = NULL; HDDEDATA hDdeTransactionData = NULL; if (DdeInitializeW(&idInstance, (PFNCALLBACK)SumatraDdeCallback, APPCMD_CLIENTONLY, 0) != DMLERR_NO_ERROR) { fputws(L"DdeInitializeW error\n", stderr); err = 4; goto exn; } if ((hszServer = DdeCreateStringHandleW(idInstance, server, CP_WINUNICODE)) == NULL) { fputws(L"DdeCreateStringHandleW error\n", stderr); err = (int)DdeGetLastError(idInstance); goto exn; } if ((hszTopic = DdeCreateStringHandleW(idInstance, topic, CP_WINUNICODE)) == NULL) { fputws(L"DdeCreateStringHandleW error\n", stderr); err = (int)DdeGetLastError(idInstance); goto exn; } if ((hConvClient = DdeConnect(idInstance, hszServer, hszTopic, NULL)) == NULL) { fputws(L"DdeConnect error\n", stderr); err = (int)DdeGetLastError(idInstance); goto exn; } if ((hDdeData = DdeCreateDataHandle(idInstance, (BYTE*)((wchar_t*)command), (DWORD)((wcslen(command) + 1)*sizeof(wchar_t)), 0, NULL, CF_UNICODETEXT, 0)) == NULL) { fputws(L"DdeCreateDataHandle error\n", stderr); err = (int)DdeGetLastError(idInstance); goto exn; } if ((hDdeTransactionData = DdeClientTransaction((BYTE*)hDdeData, (DWORD)-1, hConvClient, NULL, 0, XTYP_EXECUTE, TIMEOUT, NULL)) == NULL) { fputws(L"DdeClientTransaction error\n", stderr); err = (int)DdeGetLastError(idInstance); goto exn; } exn: if (hDdeTransactionData) { if (DdeFreeDataHandle(hDdeTransactionData) == FALSE) { err = (int)DdeGetLastError(idInstance); if (err) { fputws(L"DdeFreeDataHandle error\n", stderr); } } } if (hDdeData) { if (DdeFreeDataHandle(hDdeData) == FALSE) { err = (int)DdeGetLastError(idInstance); if (err) { fputws(L"DdeFreeDataHandle error\n", stderr); } } } if (hszServer) { if (DdeFreeStringHandle(idInstance, hszServer) == FALSE) { fputws(L"DdeFreeStringHandle error\n", stderr); err = (int)DdeGetLastError(idInstance); } } if (hszTopic) { if (DdeFreeStringHandle(idInstance, hszTopic) == FALSE) { fputws(L"DdeFreeStringHandle error\n", stderr); err = (int)DdeGetLastError(idInstance); } } if (hConvClient) { if (DdeDisconnect(hConvClient) == FALSE) { fputws(L"DdeDisconnect error\n", stderr); err = (int)DdeGetLastError(idInstance); } } if (idInstance) { if (DdeUninitialize(idInstance) == FALSE) { fputws(L"DdeUninitialize error\n", stderr); err = 5; } } return err; } int #if defined (_MSC_VER) wmain(int argc, wchar_t** argv) #else main(void) #endif { int err = 0; wchar_t* pdf = NULL; wchar_t* tex = NULL; wchar_t* line = NULL; int active = 0; wchar_t forwardSearch[FWDSUMATRAPDF_BUF_SIZE] = L""; #if !defined (_MSC_VER) int argc = 0; wchar_t** argv = CommandLineToArgvW(GetCommandLineW(), &argc); #endif if (argc != 4) { fwprintf(stderr, L"usage: %ls pdffile texfile line\n", argv[0]); err = 2; return err; } pdf = argv[1]; tex = argv[2]; line = argv[3]; if (wcslen(pdf) >= (FWDSUMATRAPDF_BUF_SIZE/4)) { fwprintf(stderr, L"%ls is too long.\n", pdf); err = -4; return err; } if (wcslen(tex) >= (FWDSUMATRAPDF_BUF_SIZE/4)) { fwprintf(stderr, L"%ls is too long.\n", tex); err = -3; return err; } if (wcslen(line) >= (FWDSUMATRAPDF_BUF_SIZE/4)) { fwprintf(stderr, L"%ls is too long.\n", line); err = -2; return err; } if (wcstol(line, NULL, 0) == 0 || errno == ERANGE) { fwprintf(stderr, L"%ls can't convert to the line number.\n", line); err = -1; return err; } if ((err = RunSumatraPDF(pdf)) != 0) { return err; } snwprintf(forwardSearch, FWDSUMATRAPDF_BUF_SIZE-1, L"%ls%ls%ls%ls%ls%ls%ls%d%ls", L"[ForwardSearch(\"", pdf, L"\",\"", tex, L"\",", line, L",0,0,", active, L")]"); if ((err = DdeExecute(L"SUMATRA", L"control", forwardSearch)) != 0) { return err; } return err; } ----