C笔记

#ifndef e //定义没有分号结尾...
#define e
#else
#define k
#endif

预定义

#define a(b) #b // 一个#号说明b被当成一个字符串 结果为 "b"

#define a(b) s##b //两个#号表示b被当成字符串且与字符s链接

#define g()  do{ }while(0) //复杂定义使用,保证任何场合都适用

 前后加加的区别:

int a = 5, b = 7;
    a+++b;//12 a++ +b ++后为执行后加 ++前为执行前加
    int a = 5, b = 7;
    ++a+b;//13

区分定义类型于定义变量

typedef int*a;//定义类型
    int*a;//声明变量
    int b=10;//定义变量

定义返回值为某类型的函数

    typedef void (*a)(void *b);//定义一个返回值为void的函数
    void hi(void *m){
        printf("%s","hi");
    };
    a b=&hi;
    void *k=(void *)(0);
    b(k);

非本文件变量使用:

extern int a;//尽量少用...

struct 的声明可以省略typedef

数组误区:

int a[2][2]={
            {1,2},
            {3,4}
    };
    int *b[2]={
            "12",
            "34",
    };

a 表示一个存储着数组的数组,所以a[0]代表的是一个数组,所以sizeof(a[0])是一个数组的大小,sizeof(a)表示存储所有数据的大小

b表示一个存储一个指针的数组,所以a[0]代表一个指针,所以sizeof(a[0])是一个指针大小,sizeof(a)表示一个存储所有指针的总大小

误区二:

int a[]={1,2};

a为指向数组的名

int *b={1,2};//错误

a是指向整数的指针

int *c[]={1,2};//错误

a是指向整型数组的名,如:int *c[]={a};

数组的名有类似指针的功能,但本身是不能更改的

    int b[]={1,2,3};
    int *k=b;
    printf("%d",b[0]);
    printf("%d",*(b+1));//数组不是指针,不能自加操作
    printf("%d",*k);
    printf("%d",*++k);

指针:指向一个内存位置

数组名:数组名存放第一个数组的内存位置,但同时还包含有整个数组的信息

所以有得到数组的长度公式:
sizeof(a)/sizeof(a[0]);
结论:sizeof传入值为数组的时候得到数组的总大小,指针的时候为指针大小,结构体为结构体大小 ==
 
声明一维数组赋值多维数组,将丢弃其中的元素:
    char a[]={  //其实是错误语法,但部分编译器会取数组第一个元素
            {
                'a',
                'b',//丢弃
                'c'//丢弃
            },
            {
                'a',
                'b',//丢弃
                'c'//丢弃
            },
    };
    printf("%d",sizeof(a));//2
    printf("%d",sizeof(a[0]));//1 为a
不定参数的函数:
原理:因为函数的参数是值传递,传递过程中是建立到一个堆栈中的,所以当知道其中一个参数的位置且知道每个参数的类型的时候是可以获取到他们的
C标准中的实现:头文件是stdarg.h
   void te(int n,...){//第一个是参数数量,...是特定的(参数数量是手动传的!!!)
        va_list arglist;
        va_start(arglist,n);//设置头参数及参数数量
        int i;
        for(i=0;i<n;i++){
            printf("%d",va_arg(arglist,int));//这就是传入的参数
        }
        va_end(arglist);
    }
    //调用
    te(8,2,1,1,1,1,1,11,2312);//第一个参数是指后面共有几个参数
指针函数类型:
int ab(void){return 12;}
    typedef int (*nn)();//定义函数指针
    int (*tt)();//声明函数指针
    nn abk;
    abk =&ab;
    tt=&ab;
    printf("%d",((int (*)())tt)());

 

指针误区:

 

    char * a;
    char b[10]="test";
    //b可以赋值给A,因为b的数据在栈区,指针可以指向栈区
    a=b;
    char *c="test";
    char d[10];

    char *e[10];

    *e[0]='a';//错误,可能修改于未知的内存数据

    d=c;//错误,数组不能指向静态区数据

char *a;
    *a="12";

int (*c[2])d(); 

总结:指针定义后如果没有初始化,其指向位置是不确定的,此时不应该给指针赋值,最好在指针定义时初始化,不然在指针没指向任何元素前不要使用指针

指针定义后不能初始化是因为定义后他们是指针并非值

指针的自增或自减 或加值减值:移动的位置与指针的类型有关,加减的数量是类型大小的倍数,自增或自减之后当前指针的位置已变

 

打印输入后字符还在缓冲区,使用:

printf("WM_PAINT\n");
fflush(stdout);//fflush(stdin);
//stdio.h

强制输出,C++中endl搞定,还是c++方便

字符串指针更改字符问题:

char * a="afasdf";

此值不能修改,因为该指针指向的是常量,数据在静态区,非栈区

char a[]="afasdf";

可以修改,因为数据在栈区

只要非静态的数据,均可以使用指针来修改,例如:

    char * a="afasdf";
    char * b =(char *)malloc(strlen(*a)+1);
    b[0]='f';
    strcpy(b,a);

关于malloc,calloc,realloc,free:

    void * m=malloc(10);//分配10个字节的空间
    void * m=calloc(10);//分配10个字节空间并置于0
    void * m=calloc(10,10);//分配连续10个10个字节的空间
    realloc(m,-10);//指定空间加减空间
    free(m);

得到

memset(m,0,sizeof(m));//申请的内存最好重置

初始化的时候也可以使用:

char * a=strdup("afasdf");//可修改初始化

现在为栈区数据

malloc 内存没申请够一样可以赋值,只是覆盖掉了不相关的内存,可能会造成运行时错误

static void a();//限制为本文件内函数

 

结构体大小(内存对齐规则)

结构体大小必须是结构体中最大的类型的倍数

结构成员的起始位置必须是该类型(基本数据类型)的大小的倍数

结构体省内存方法

成员小的放置于前面,相同大小的尽量放置于一块,成倍数的放置于相邻位置

 

计算文件大小:

FILE* f=fopen(filename,"r");
int filelen;
fseek(f,0,SEEK_END);   //文件指针移到末尾
filelen=ftell(f);   //获得文件当前指针位置,即为文件长
fclose(f);

 读取文件成字符串:

FILE* f=fopen(filename,"r");
int filelen;
int i=0;
char * buf=NULL;
fseek(f,0,SEEK_END);   //文件指针移到末尾
filelen=ftell(f);   //获得文件当前指针位置,即为文件长度
rewind(f);   //将文件指针移到开头,准备读取
buf=malloc(filelen+1);    //新建缓冲区,存储独处的数据
for(i=0;i<filelen+1;i++)
    buf[i]=0;
fread(buf,filelen,1,f);
fclose(f);

使用MYSQL: (for cdt)

添加库:c/c++ build -> settings -> mingw c linker -> miscellaneous ->other objects 增加libmysql.lib (安装了MYSQL后在mysql的lib目录下)

引入头文件:#include "../include/mysql.h" (在mysql安装目录下可以找到)

    MYSQL mysql;
    MYSQL_RES *result;
    MYSQL_ROW row;

    mysql_init(&mysql);
    if (!mysql_real_connect(&mysql, "localhost""test""test""test"3306, NULL, 0))
    {
        printf("/n数据库连接发生错误!");
        exit(1);
    }
    if (mysql_query(&mysql, "SELECT * FROM ko_music_info")){
           printf("/n数据库查询发生错误");
    }else{
        result = mysql_store_result(&mysql);
        if (mysql_num_rows(result)){
            int numRows = mysql_num_rows(result);
            int numFields = mysql_num_fields(result);
            printf("\n- %d rows,field %d", numRows, numFields);
            int j = 1;
            while (row = mysql_fetch_row(result)){
                printf("\n ------------- %d --------------------\n", j);
                int i;
                for (i = 0; i < numFields; i++){
                    fprintf(stdout, " %s", row[i]);
                }
                j++;
            }
       }
       mysql_free_result(result);
    }
    mysql_close(&mysql);         

CURL使用:

下载curl源码:

进入lib目录下编译库文件: mingw32-make -f Makefile.m32

 

添加库:c/c++ build -> settings -> mingw c linker -> miscellaneous ->other objects 增加libcurldll.a (编译的时候生成)
 
ECLIPSE 添加外部DLL 也可以使用此方法添加
 

引入头文件:#include "../curl/include/curl/curl.h"  (curl源码包里)

 

    CURL * curl; //其他实例看手册
    CURLcode res;
    size_t a;
    curl=curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, "http://www.qq.com");
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);

抓取为字符

 

size_t write_data (void *ptr, size_t size, size_t nmemb, void *file){
    printf("s%",ptr);
    return nmemb;
}
void * get_url(*url){
    CURL *h;
    curl_global_init(CURL_GLOBAL_ALL);
    h=curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL,url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
    FILE * file=fopen("websource.html","a+b");
    curl_easy_setopt(curl,CURLOPT_WRITEDATA,file);//传入处理获得字符的句柄,文件字符或其他等等
    curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    fclose(file);
    return ((void *)0);
}

 

判断WIN还是LINUX

#if defined(WIN32) || defined(WIN64)
#include <windows.h>
#define sleep(n) Sleep(1000 * (n))
#else
#include <unistd.h>
#endif


返回VOID指针

void * pth(){}

return ((void *)0)

 

文件存储复杂数据类型

 

typedef struct a{
        int a;
        int b;
    } b;
    b k[2]={
        {10,8},
        {2,4}
    };
    FILE *file;
    file=fopen("a","w+b");
    fwrite(&k,sizeof(b),2,file);
    fclose(file);
    FILE *rfile;
    b *rk;
    rk=(b*)malloc(sizeof(b)*2);
    rfile=fopen("a","r+b");
    fread(rk,sizeof(b),2,rfile);
    fclose(rfile);
    printf("%d",(++rk)->a);

 

 

 

pthread_create 创建线程后要处理,否则无效

 

void * abc(void){
        printf("%s","hi");
        fflush(stdout);
        sleep(10);
        return (void *)0;
    }
    pthread_t t;
    /*pthread_t *t;//如果定义的是指针,记得分配空间
    t=(pthread_t *)malloc(sizeof(pthread_t));
*/
    pthread_create(t,NULL,(void *) abc,NULL);
    pthread_join(*t,NULL);//一定要处理,否则无效果
    
//pthread_exit(t);

 

有定义,无实现错误:

undefined reference to  '***';
例子:
int a();
a();
 
函数未实现,被调用:
is used uninitialized in this function **
例子:
typedef void (*b)();
b a;
a();

error: conflicting types for *

函数未在main之前声明.

遍历字符串,因为字符串以0结尾

char *a="aaaa";

char p;

while(p=*a){

  //使用p

  a++;

}

数组作为函数参数时,传递的只是其指针,所以

int t(char *a);跟int t(char a[])是相同的

注意:

char vt[100];//sizeof(t);=100

int t(char *vt){sizeof(vt)//4,指针长度}

 

enum 是整形,且不会有类型验证

enum{HI} a; enum{GOOD}b;

b=HI;//程序是正常的,但不建议这样用.

 

字符串操作函数均指有实体字符的值

如:char a[5]="abc"; char b['2']="1"; strcat(a,b);//a=abc1 而不是abc\01;且后面通常都会加\0结束符.

 

函数参数传递指针时,函数为为指针的拷贝

所以要修改指针时,需要传递指针的指针

 

GCC 编译生成汇编 

gcc -S cfile

GCC 编译不连接文件

gcc -c cfile

GCC 编译生成优化汇编

gcc -O2 -S cfile 

.o 文件反编译

objdump -d ofile.o

 

其他详细:http://blog.csdn.net/howdyhappy/article/details/2329101

posted @ 2012-07-24 16:18  liushan  阅读(258)  评论(0)    收藏  举报