文章关键字 ‘C’

C语言中的字符串常量

2010年11月30日,星期二

说起字符串常量,学过C语言的人都不陌生。字符串常量的书写方式是一对双引号包围一串字符,如:

"Hello, world"

当一个字符串常量出现于一个表达式中时,表达式所使用的值就是这些字符所储存的地址,而不是这些字符本身。因此,你可以把字符串常量赋值给一个“指向字符的指针”,后者指向这些字符所储存的地址,如:

char *str = "Hello, world";

但是,你不能把字符串常量赋值给一个字符数组,因为字符串常量的直接值是一个指针,而不是这些字符本身。简单的说,字符串常量的值是这些字符在内存中的地址。

现在考虑下面一段代码:

if("Demon")
    printf("true");
else
    printf("false");

你认为会输出什么,true or false?

C语言中size_t的陷阱

2010年11月26日,星期五

今天写了一个类似这样的程序:

#include <stdio.h>
#include <string.h>
int main()
{
    int i = -1;
    if(i > strlen("Demon"))
        printf("Hello World");
    else
        printf("Hello Demon");
    return 0;
}

输出的竟然是Hello World!-1 > 5?!

仔细想想,原来问题出在strlen上,strlen返回的类型是size_t,size_t的定义为:

typedef unsigned int size_t;

即无符号的整型,而i的类型是int,即有符号的整型。当有符号整型和无符号整型进行运算时,有符号整型会先自动转化成无符号。-1转化成无符号数为4294967295,远远大于5。

今后遇到有符号数和无符号数之间的运算时要千万小心。

隐藏系统托盘图标的小程序TrayHider

2010年10月15日,星期五

前几天有人问怎么隐藏程序的系统托盘图标,于是研究了一下,写了个小程序,虽然不知道为什么要隐藏系统托盘图标。

  • 仅支持32位系统,不支持64位
  • 双击左栏图标就可以隐藏对应的程序系统托盘图标
  • 热键Ctrl + Alt + D可以隐藏/显示程序主窗口
  • 支持命令行参数,如TrayHider.exe  QQ.exe隐藏QQ的托盘图标

参考链接:

  1. Вопросик .. для наших Win32 гуру
  2. Shell Tray Info – Arrange your system tray icons
  3. 隐藏Windows系统托盘图标(改进版)

C语言调用API获取程序自身的路径

2010年10月14日,星期四

VBS获取程序自身的路径很简单

WScript.Echo WScript.ScriptFullName

C语言其实也也很简单,只可惜以前太菜

TCHAR szFileName[MAX_PATH];
GetModuleFileName(NULL, szFileName, MAX_PATH);
MessageBox(NULL, szFileName, TEXT(""), 0);

参考链接:GetModuleFileName Function

GUI程序获取命令行参数

2010年10月13日,星期三

在Console程序中可以用main函数中的argc和argv遍历命令行参数。

#include <stdio.h>

int main(int argc, char *argv[])
{
    int i;
    for(i = 0;i < argc;i++)
        printf("%s\n", argv[i]);
    return 0;
}

那么在GUI程序中怎么遍历命令行参数呢?虽然WinMain函数的lpCmdLine参数中传入了程序的命令行参数,但是该参数不包含应用程序名(即main函数中的argv[0]),而且自己解析出每个参数也比较麻烦。

最简单的方法是先用GetCommandLineW函数获取命令行,然后用CommandLineToArgvW函数将命令行转化成C语言main函数argc和argv的形式。

#include <windows.h>
#include <stdio.h>
#include <shellapi.h>

int WINAPI WinMain(HINSTANCE hInstance, 
            HINSTANCE hPrevInstance, 
            LPSTR lpCmdLine, 
            int nShowCmd)
{
    LPWSTR *szArglist;
    int nArgs, i;
    
    szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
    for (i = 0; i < nArgs; i++)
    {
        MessageBoxW(NULL, szArglist[i], L"", 0);
    }
    return 0;
}

只可惜没有CommandLineToArgvA函数,想用ANSI版的话得自己用WideCharToMultiByte函数转换一下。