C语言的那点事

预处理

-----------------------------------------------------------------------------------------------

#include <stdio.h>
#define SQR(x) ((x)*(x))    //注意这种定义方式,加括号
int main()
{
    int a = -3;
    int b = -2;
    int q = a/b;
    int r = a%b;

    printf("q = %d\n",q);                    //q = 1
    printf("r = %d\n",r);                    //r = -1

    //__DATE__,__TIME__ 表示的是编译时的时间,而不是运行时
    printf("line = %d\nfile = %s\ndate = %s\ntime = %s\n",\
            __LINE__,__FILE__,__DATE__,__TIME__);

    //关于宏定义
    printf("SQR(1)\n");        //--SQR(1);注意

#define X 3
#define Y X*3
#undef X
#define X 2
    int z = Y;
    printf("z = %d\n",z);        //--z = 6;

#define _X86
#ifdef _X86
#pragma message("X86 macro activated!")
#endif
    /************************************************/

    //内存对齐
    /************************************************/
    struct TestStruct1
    {
        char c1;
        short s;
        char c2;
        int i;
    };

    struct TestStruct1 ts1;
    printf("c1 %p, s %p, c2 %p, i %p\n",        //--c1 (nil), s 0x2, c2 0x4, i 0x8 解释:内存对齐
            (unsigned int)(void *)&ts1.c1 - (unsigned int)(void *)&ts1,
            (unsigned int)(void *)&ts1.s - (unsigned int)(void *)&ts1,
            (unsigned int)(void *)&ts1.c2 - (unsigned int)(void *)&ts1,
            (unsigned int)(void *)&ts1.i - (unsigned int)(void *)&ts1);
    printf("sizeof(ts1) = %d\n",sizeof(ts1));    //--sizeof(ts1) = 12.注意,这里不是结构体成员之和8
    //PS:这里可在前面加上一句#pragma pack(1),使其按一个字节对齐。但是会降低程序效率,访问需要两个机器周期
    //也可以通过改变结构体TestStruct1中的成员顺序来优化程序。这样不会降低效率,而且可以消除其他很多问题。
    //例如,作为库被第三方软件使用时。
    /************************************************/

    //其他一些预处理
    /************************************************/
#pragma pack(8)    
    typedef struct
    {
        char a;
        long b;
    }TestStruct2;
    struct TestStruct3
    {
        char c;
        TestStruct2 d;
        long long e;
    };
#pragma pack()
    struct TestStruct3 ts3;
    printf("sizeof(ts3) = %d\n",sizeof(ts3));     //--sizeof(ts3) = 20 || 24

#define SQR(x) printf("The square of "#x" is %d.\n",((x) * (x)));
    SQR(8);    

#define XNAME(n) x##n    //如:XNAME(8)展开后为x8
    //PS:#和##应该尽量不用,在一个的宏定义中,最多可以出现一次"#"或"##"    
    /************************************************/

    return 0;
}



符号:

---------------------------------------------------------------------------------------------------------------------------------

#include <stdio.h> 
 
int main() 

    //注释符  
    /****************************************/ 
    //在编译时,编译器会将注释符替换为空格  
    int /*...*/i;                    //--正确  
    char * s = "abcdefgh //ijklmn";     //--正确  
    //Is it a\ 
    valid comment?                     //--正确  
//    in/*...*/t j;                    //--错误  
    /*****************************************/ 
  
     //左移和右移  
    /****************************************/ 
    //对于有符号数,在右移时,符号位将随同移动。当为正数时, 
    //最高位补0;而为负数时,符号位为1,最高位是补0或是补1 
    //取决于 编译系统。 
    0x01 << 2 + 3;            //-----结果为32,因为 + 优先级高 
     
    //左移和右移的位数不能大于数据的长度,不能小于0.  
//    0x01 << 2 + 30;            //错误 
//    0x01 << 2 - 3;            //错误      
    /***************************************/ 
 
    //关于++和-- 
    /*************************************/     
    int a = 3; 
    int b = (++a) + (++a) + (++a); 
    printf("a = %d\n",a);    //a = 6  
    printf("b = %d\n",b);    //b = 16 (5+5+6)。结果由编译器定,有的编译器结果为18。  
     
    int c = 0; 
    int d = (c++,c++,c++);    //d = 2 C语言遇到逗号,认为本计算单位结束,所以最后一个生效 
    c = 0;  
    int e = (++c,c++,c+10);    //依次为e=1,e=1,e=12;  
    printf("d = %d\n",d);    //d = 2; 
    printf("e = %d\n",e);    //e = 12; 
                             
    c = 0; 
    int f = (c++) + (c++) + (c++);     
    printf("f = %d\n",f);    //f = 0;上式c遇到分号才认为本计算  
                // 单位结束,此时c才做自加动作. 
 
    /*    这段程序会陷入一个死循环,主要问题在 g < 10,printf("Second = %d\n",g); 
    int g;                         
    for (g = 0,printf("First = %d\n",g);\ 
        g < 10,printf("Second = %d\n",g);\ 
        g++,printf("Third = %d\n",g)) 
    { 
        printf("Fourth = %d\n",g); 
    } 
    */ 
     
    int h = 1,m = 2; 
    int k; 
    k = h+++m; 
    printf("k = %d\n",k);        //k = 3,说明 h+++m = (h++) + m  
    /***********************************/  
     
    return 0; 
}



sizeof于strlen:

-------------------------------------------------------------------------------------------------------------

/* 
%u无符号十进制整数   %lu无符号长整型 
%d有符号十进制整数      %lf double 
%0无符号八进制      %g double 
%x无符号十六进制整数  %i == %d 
*/ 
 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
 
int fun(int b[]) 
{     
    return sizeof b; 

 
int main() 

 
    //关于sizeof 
    char *p = NULL ; 
//    int num = sizeof i; 
    printf("sizeof(p) = %d\n",sizeof(p));        //sizeof(p) = 4 
    printf("sizeof(*p) = %d\n",sizeof(*p));        //sizeof(*p) = 1 
     
    int a[100]; 
    printf("sizeof(a) = %d\n",sizeof(a));        //sizeof(a) = 400 
    printf("sizeof(a[100]) = %d\n",sizeof(a[100]));    //sizeof(a[100]) = 4 
    printf("sizeof(&a) = %d\n",sizeof(&a));        //sizeof(&a) = 4 
    printf("sizeof(&a[0]) = %d\n",sizeof(&a[0]));    //sizeof(&a[0]) = 4 
     
    printf("&a = %p\n",&a);                //&a = 0xbfdd5aec 
    printf("&a[0] = %p\n",&a[0]);            //&a[0] = 0xbfdd5aec 
     
    int b[100]; 
    printf("sizeof(b) = %d\n",fun(b));        //sizeof(b) = 4 

 

/*****************************************/

 char tp1[] = {'Q','W','E','R'};
 char tp2[] = "qwer";

 

printf("strlen(tp1) = %d\n", strlen(tp1));       //  7(这是一个不确定的数,遇到'\0'判断为结束)
 printf("sizeof(tp1) = %d\n", sizeof(tp1));      //  4
 printf("strlen(tp2) = %d\n", strlen(tp2));      //  4
 printf("sizeof(tp2) = %d\n", sizeof(tp2));      //  5

/*****************************************/
     
    struct student 
    { 
         
    }stu; 
    printf("sizeof(stu) = %d\n",sizeof(stu));    //sizeof(stu) = 0 
     
     
    typedef struct st_type    //柔性数组  
    { 
        double i; 
        int a[];    // 或[int a[0]  
    }type_a; 
    type_a *tp = (type_a *)malloc(sizeof(type_a) + 100 * sizeof(int)); 
    printf("sizeof(type_a) = %d\n",sizeof(type_a));//sizeof(type_a) = 8 
    printf("sizeof(*tp) = %d\n",sizeof(*tp));    //sizeof(*tp) = 8,柔性数组不占结构体编制,  
                            //不能算结构体的正式成员  
    free(tp); 
     
    printf("\n"); 
    /**********************************************/ 

  但是:

  typedef struct
  {
   char *s[50];
  }memo;
  问:sizeof(memo) = 200;
     
    /*字符为有符号数,只有七位有效,即取值范围为-256到255*/ 
    /*********************************************/ 
    char c[1000]; 
    int i; 
    for(i = 0; i < 1000; i++) 
    { 
        c[i] = -1 - i; 
    } 
    printf("strlen(c) = %d\n",strlen(c));        //strlen(c) = 255 
    printf("\n"); 
    /*********************************************/ 
     
    /*sizeof与strlen()*/ 
    /********************************************/ 
    char d[3]; 
    char *e = "abcde"; 
    printf("strlen(d) = %d\n",strlen(d));        //strlen(d) = 0 
    printf("sizeof(d) = %d\n",sizeof(d));        //sizeof(d) = 3 
    printf("strlen(e) = %d\n",strlen(e));        //strlen(e) = 5 
    printf("sizeof(e) = %d\n",sizeof(e));        //sizeof(e) = 4 
    printf("\n"); 
    /*******************************************/ 
     
    //下面这段代码会陷入死循环 ,因为k为无符号数, 
    //永远不可能 < 0,如果把k >= 0改为(int)k >= 0即可。  
    /************************************* 
    unsigned k; 
    for (k = 9; k >= 0; k--) 
    { 
        printf("%u\n",k); 
    } 
    ************************************/ 
     
    /*const修饰的变量可以用在case后*/ 
    const int k = 2; 
    switch(k) 
    { 
        case 1: printf("Is 1\n"); 
            break; 
        case 2: printf("Is 2\n"); 
            break; 
        case 3: printf("Is 3\n"); 
            break; 
        default: 
            break; 
    } 
    printf("\n"); 
    /**********************************/ 
     
    /* 
    const int *p;        //p可变,p指向的对象不可变 
    int const *p;        //p可变,p指向的对象不可变 
    int *const p;        //p不可变,p指向的对象可变 
    const int *const p;    //p不可变,p指向的对象不可变 
    */ 
 
    /* 
    const volatile int x = 10; 
    x = 2;                //错误,上面一条一句,虽然能 
                         编译通过,但是x被const修饰  
    */ 
     
    /*********************************/ 
    int f[5] = {1,2,3,4,5}; 
    int *ptr1 = (int *)(&f + 1); 
    int *ptr2 = (int *)((int)f + 1); 
     
    printf("%p\n",f);                //0xbf8b6894 
    printf("%p\n",ptr1);                //0xbf8b68a8 
    printf("%p\n",ptr2);                //0xbf8b6895 
    printf("%x, %d",ptr1[-1],*ptr2);        //5, 33554432 
    printf("\n");                     
    /******************************/ 
 
    //枚举  
    /******************************/ 
    enum Color 
    { 
        GREEN = 1, 
        RED, 
        BLUE, 
        GREEN_RED = 10, 
        GREEN_BLUE 
    }ColorVal; 
    printf("sizeof(ColorVal) = %d\n",sizeof(ColorVal));//sizeof(ColorVal) = 4 
    printf("\n"); 
    /******************************/ 
     
    /******************************** 
    typedef struct student 
    { 
        //code 
    }Stu_st,*Stu_pst; 
    //  
        A)struct student stu1 = Stu_st stu1; 
        B)struct student *stu2 = Stu_pst stu2 = Stu_st *stu2; 
    //     
    //另:const修饰的是变量而不管类型,包括typedef定义的类型 
    //    而typedef是对类型的重定义,而不是 变量。  
    ********************************/ 
     
    /* 
    #define INT32 int  
    typedef int int32; 
     
    int32 abc = 10;                //正确  
    unsigned int32 bcd = 10;    //错误,因为此时int32已是新的数据类型  
    unsigned INT32 cde = 10;    //正确,这里只是简单替换  
    */ 
     
    return 0; 
}



指针:

-------------------------------------------------------------------------------------------------------

#include <stdio.h>

int main()
{
    int a[5] = {1,2,3,4,5};
    int b = *a;

    printf("b = %d\n",b);        //--b = 1;这里的a作为右值相当于&a[0]
    
    char *p = "abcdef";

    //对指针的访问
    printf("&p = %p\n",&p);        //--&p = 0xbfe5af48;指针P的地址
    printf("p address = %p\n",p);    //--p address = 0x8048588;指针P存放的地址
    printf("p = %s\n",p);        //--p = abcdef;整型数组就不能用这种方式打印
    printf("*p = %c\n",*p);        //--*p = a
    printf("* (p + 4) = %c\n",* (p + 4));//--* (p + 4) = e
    printf("p[4] = %c\n",p[4]);    //--p[4] = e

    //对数组的访问
    char ca[] = "123456";
    printf("*ca = %c\n",*ca);    //--*ca = 1
    printf("* (ca + 4) = %c\n",* (ca + 4));//--* (ca + 4) = 5
    printf("ca = %s\n",ca);        //ca = 123456
    //PS:这里的偏移量是指元素的个数,而不是字节数,如果是整型数组,
    //一个偏移量就表示4字节。

    int c[5] = {1,2,3,4,5};
    int *ptr = (int *)(&a + 1);//&a + 1相当于 &a + sizeof(a),因为a是一个数组,其数据类型长度是5 * sizeof(int)
    printf("%d, %d\n",*(a + 1), *(ptr - 2));//--2, 4
    //PS:c的数据类型是一个包含5个成员的整型数组,其大小是5 * sizeof(int);
    //而&c + 1就表示移动一个5*sizeof(int)的大小,即下一个数组的首地址。
    //而ptr是一个整型指针,其数据类型长度为sizeof(int),所以ptr -2即为ptr - 2*sizeof(int)
    //c + 1是数组下一元素首地址。&c + 1是下一数组首地址。c = &c[0]

    
    char *pc = c;        //警告:虽然可以得到结果,但是这里隐含错误,类型不一致。
    printf("*(pc + 4) = %d\n",*(pc + 4));//--*(pc + 4) = 2

    char x[10] = {'A','B','C','D','E','F','G','H','I','J'};
    char (* p3)[3] = &x;    //警告:initialization from incompatible pointer type
    char (* p4)[3] = x;    //警告:这里数据类型不一致

    printf("p3 + 2 = %s\n",p3 + 2);    //p3 + 2 = GHIJ;警告:format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)[3]’
    printf("p4 + 2 = %s\n",p4 + 2); //p4 + 2 = GHIJ;
    
    return 0;
}


/////////////////////////////////////////////////////////////

#include <stdio.h>

int main()
{
    int a[5][5];
    int (* p)[4];
    p = a;
    printf("a_ptr = %p,p_ptr = %#p\n",&a[4][2],&p[4][2]);        //a_ptr = 0xbfa7b680,p_ptr = 0xbfa7b670
    printf("%p, %d\n",&p[4][2] - &a[4][2],&p[4][2] - &a[4][2]);    //0xfffffffc, -4

    return 0;
}


你可能感兴趣的:(linux,C语言)