【2015/11/1】C學習日誌_Day11&12 數據類型 指針 內存對齊 函數指針

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/hsgwpj/article/details/49561613
/*************************************************************************
    > File Name: class.c
    > Author: khalil
    > Mail: [email protected]
    > Created Time: Sat 31 Oct 2015 09:29:49 AM CST
 ************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//七月算法視頻課
//《編程之法》July
// ***nginx
// 深入理解nginx 模塊開發與架構解析(jb51.net)
//

#if 1
// a = b ;
// 左值: 空間(變量、內存中的值)
// 右值: 值;

// (++b)--;
// (a++)++;
// 他們都是錯的:表達式不能作爲左值!;
// ++b是得到的一個常量 不能進行運算。
//
// int a = 10;
// int b = 20;
//(1) b = ++a + b;
//    b = 11 + 20 = 31;
//(2) b = a++ + b;
//    b = 10 + 20 = 30 , a = 11;


//爲什麼使用前置++?:
//  前置++ 在C++中多一步操作 所以使用++
#endif

#if 0

int max(int a , int b);
int max2(int a , int b , int c);

int max(int a , int b)
{
    return a > b ? a:b;
}

int max2(int a , int b , int c)
{
//    return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c );
//      三目運算符是不推薦的,容易寫錯
    return max(max(a,b),c);
}

int main ( int argc , char **argv )
{
    int a = 10 ;
    int b = 20 ;
    int c = 30 ;
    int max_value = 0;

    max_value = max2( a, b, c);
    printf("%d\n",max_value);

    if ( 1 < a < 20 );
    // 如果1<a return 1 然後再 1<20 和想象中的並不一樣
    if ( 1 < a && a < 20 );
    // 這纔是可用的形式

    return 0 ;
}
#endif

#if 0
//組件化思想

char *my_strcpy(char *des , const char *src);

char *my_strcpy(char *des , const char *src)
{   //使用memcpy進行拷貝
    return (char *)memcpy(des,src,strlen(src)); //把src內容拷到des
}

int main ( int argc , char** argv )
{
    char *str1 = "hello,world!";
    char str2[20] = {0};

    my_strcpy(str2,str1);

    printf("str2:%s\n",str2);

    return 0;
}
#endif

#if 0
int main(int argc , char **argv)
{
    // && ||  的短路運算:提前預知真假
    //
    int a = 10 ;
    int b = 20 ;
    int c ;
    if ( a > 20 && b > 10 );
    // 只要條件1 不滿足 立即退出判斷 b>20 被短路,不用判斷
    if ( a > 5 || b < 6 );
    // 只要條件1 滿足   立即退出判斷 b<6  被短路,不用判斷

    c = (10 , 20);   //不能用int c = 10 ,20 ;
    printf("%d\n",c); // c = 20

    return 0 ;
}
#endif

#if 0
int main ( int argc , char ** argv)
{
    int array[]= {5,123,213,23,56,89,35};

    printf("%d\n",array[2]);
    printf("%d\n",2[array]);    // 一樣的

    printf("%c\n",2["hi!"]);
    // []  == +     []被當作操作數處理
    //
    // a [b] ==> b[a]
    //
    // a + b = b + a
}

#endif

#if 0
//自定義布爾值

#define false (0)
#define true  (1)

typedef unsigned char Bool;

int main ( int argc , char **argv )
{
    Bool ok = false;
    if (ok == false){
        printf("False!\n");
    }else{
        printf("True!\n");
    }
}
#endif

#if 0
int main (int argc , char ** argv)
{//隱式類型轉換
    char  a = 10;
    int   b = 20;

    b = a + b ; //a (char)  --> a (int)

    //1.數值範圍小的轉化爲大的
    //2.整形:有符號的轉換爲無符號的
    //3.整形和浮點類型: 都轉化爲double類型
    //

    int *p[20];     //一個指針數組 有20個指針
    int (*q)[20];   //一個指向20個單位的int數組的指針

}
#endif

#if 0

void my_bzero(void *src, size_t n);
void my_bzero(void *src, size_t n)
{
    memset(src, 0, n);
}
int main (int argc, char **argv)
{
    int a = 10;
    int array[10] = {1,2,3};    //不完全賦值
    char str[20]  = {0};
    int *p        = &a;         //定義一個指針記錄a的地址
    memset( str, 0, sizeof(str));
    bzero(str, sizeof(str));

    // 0 - 9 , 數組下標不要越界,預防差1多1錯誤
    array[5] = 10;

    array;   //數組名是一個常量,記錄了數組首地址
//  array = p;//不可被修改!

    p = array;
    //是否相同?
    p[1]        = 15;
    array[1]    = 15;

    int (*q)[10] = &array;  // <- 指向數組的指針
//  其實int數組的類型是 int[數組長度] 所以不能int **q = &array

    *((int*)(q + 1) - 1) = 20;
//  指向下一個數組再往前指一位到數組的末尾
    printf("%d\n",array[9]);
    return 0 ;
}
#endif

#if 0
int sum (int array[],int len);
int sum (int array[],int len)
{   //當參數時一個數組的時候,其實只傳遞了指針
    //也就是說,編譯器爲了提高效率,把數組轉換爲了指針
    //
    int i = 0;
    int result = 0;
    for ( i = 0; i < len; ++i)
    {
        result += array[i];
    }
    return result;
}

int main(int argc, char **argv)
{
    int array[] = {12,213,42,65,78};    //定義時數組和指針時不同的
    int *p = array;
    //外部聲明時,指針和數組不同
    int result = 0;

    //      指針和數組的相同與不同
    //
    // 1.在函數的參數傳遞中,指針和數組都被看作是指針,這是爲了提升
    // 程序運行的效率
    // 2.在表達式中,我們認爲:a[i] = *(a + i)  數組效率會高一些
    // 3.在定義的時候不同,數組名字不能被指針賦值,它是常量
    // 4.extern:
    //      test1.c: int array[100]     //定義式
    //      test2.c: extern int *array  //外部聲明
    //      array[2] = 10 ;             //會直接報錯
    //
    //
    result = sum(array,sizeof(array)/sizeof(int));
    return 0 ;
}
#endif

#if 0
int main(int argc, char **argv)
{
    char *str1 = NULL;
    char *str2 = NULL;
    #if 0
    // 多人共用一塊空間: 《淺拷貝》
    str1 = (char *)malloc(20);
    strcpy(str1,"hello,world!");
    str2 = str1;
    free(str1);
    #endif

    #if 1
    // 《深拷貝》:
    str1 = (char *)malloc(20);
    strcpy(str1,"hello,world!");
    str2 = (char *)malloc(strlen(str1) + 1);    //用strlen統計長度記得+1
    strcpy(str2, str1);
    free(str1);
    #endif
    printf("str2: %s\n",str2);
    return 0;
}
#endif

#if 0
int main (int argc , char** argv)
{
    int array[3][4] = {0};
    int (*p)[4] = array;    // int[4] *p

    p += 1;

    printf("%x\n",array);
    printf("%x\n",p);
    //
    // 內存是線性的
    //
    *((int *)p - 1) = 20;
    printf("a[0][3] = %d\n",array[0][3]);

    return 0;
}
#endif

#if 0
int main(int argc ,char **argv)
{
    int i = 0;

    for (i = 0; i < argc; ++i)
    {
        printf("argv[%d]: %s\n",i,argv[i]);
    }

    return 0;
}

#endif

#if 0
int main(int argc, char **argv)
{
    int i = 0;
    int j = 0;
    int tmp = 0;
    int *p_int = NULL;

    if (argc < 2)
    {
        fprintf(stderr,"Invalid arguments!\nUsage:./sort num1 num2 num3...\n");
        exit(1);
    }

    p_int = (int*)malloc(sizeof(int)*(argc - 1));
    if(p_int == NULL){
        fprintf(stderr,"Memory full!\n");
        exit(1);
    }

    for (i = 0; i < (argc - 1) ; ++i)
    {
        p_int[i] =  atoi(argv[i+1]);
    }

    for (i = 0; i < argc - 1; ++i)
    {
        for(j = i; j < argc - 1; ++j)
        {
            if(p_int[j] > p_int[j+1])
            {
                tmp = p_int[j];
                p_int[j] = p_int[j+1];
                p_int[j+1] = tmp;
            }
        }
    }

    for (i = 0; i < argc - 1; ++i)
    {
        printf("no.%d : %d\n",i,p_int[i]);
    }

    return 0;
}
#endif

#if 0
//擴展字符串
char *extend_str(const char *dest_str,const char *src_str,int length)
{
    if (dest_str == NULL || src_str == NULL)
    {
        fprintf(stderr,"InputErr!\n");
        exit(1);
    }
    char *dest = (char *)dest_str;
    char *src  = (char *)src_str;
    char *result = (char *)dest_str;
    int i = 0;
    int j = 0;

    for(i = 0; src[i] != '\0'; ++i)
    {
        if(src[i] == '-'){
            if(src[i-1] < src[i+1])
            {
                for(j = 1; j < (src[i+1] - src[i-1]); ++j)
                {
                    *dest++ = src[i-1] + j;
                }
            }else{

            }
        }else{
            *dest++ = src[i];
        }
    }

    return result;
}

int main(int argc, char **argv)
{
    char *str1 = "hello,a-c,a-z,world!\n";
    char *str2 = (char*)malloc(sizeof(char)*128);

    printf("before: %s\n",str1);
    extend_str(str2,str1,strlen(str1));
    printf("after:  %s\n",str2);
}
#endif

#if 0
char *delete_str(const char *dest_str,const char *src_str,int length,int len_des);

char *delete_str(const char *dest_str,const char *src_str,int length,int len_des)
{
    char *dest = (char*)dest_str;
    char *src  = (char*)src_str;

    int i = 0;
    int j = 0;
    int k = 0;
    int flag = 0;

    for(i = 0; i < length; ++i)
    {
        if(src[i] == dest[0]){
            for(j = 1; dest[j] != '\0'; ++j)
            {   //printf("%c\n",dest[j]);
                if(src[i+j] != dest[j]){
                    break;
                }
            }
            if(dest[j] == '\0'){
                for(k = i; src[k] != '\0'; ++k)
                {
                    src[k] = src[k+len_des-1];
                }
                i += len_des;
            }
        }else{

        }
    }
}

int main(int argc, char **argv)
{
    char str1[] = "hello,everyoneworld!";
    char str2[] = "everyone";

    printf("defore: %s\n",str1);
    delete_str(str2,str1,sizeof(str1)/sizeof(char),sizeof(str2)/sizeof(char));
    printf("after:  %s\n",str1);

    return 0;
}
#endif

#if 0
//函數指針
typedef void (*Move)(void);         //指向形如 void func(void) 的函數

//結構體
struct People{
    //屬性
    char    name[100];
    short   age;
    char    id[20];

    //操作
    Move move;
};

typedef struct A{
    int  a;
    char b;
}A;

typedef struct List_node{
    int                 data;   //數據域
    struct  List_node   *next;  //指針域
    A                   a;
}List_node;


int main (int argc, char **argv)
{
    //struct
    struct People people1;
    List_node node1 = {         //顯式聲明
        .data = 10,
        .next = NULL
    };
    List_node node2 = {0};
    List_node *p    = &node1;

    node1.next = &node2;
    (*p).data = 30;

    p->data = 40;               //原來的(*p)->data捨棄不用,換爲這種形式
    node1.a.b = 20;             //結構體套結構體
    printf("%d\n",node1.data);
    return 0;
}
#endif

#if 0
typedef struct A{
    char    a;      //1
    short   b;      //2
    int     c;      //4
    //a_bb cccc
}A;

typedef struct B{
    int     a;  //4
    char    b;  //5
    short   c;  //8
    char    d;  //9
    double  e;  //24
    char    f;  //32
}B;
//數據成員會以自己的開頭與自身的數據長度對齊
//同時結構體還會自動總體對齊於最大數據成員的長度

typedef struct C{
    char a;
    short b;
    struct D
    {
        char d;
        double e;
    } g;            //如果沒有g那麼D不佔空間
                    //對齊還是依據成員變量的空間
                    //而不是結構體中結構體的空間對齊
    int c;
    int f;
}C;

typedef struct W{
    char     a;//1
    double   b;//16
    short    c;//18
    union R{
        int     a;
        double  b;
    } d;       //32
    double   e;//40
    int      f;//48
}W;

int main(int argc, char **argv)
{
    A a;
    A *p = NULL;

    printf("size of (A):%d\n",sizeof(a));
    printf("size of (B):%d\n",sizeof(B));
    printf("size of (C):%d\n",sizeof(C));
    printf("size of (W):%d\n",sizeof(W));

    p = &a;

    //引用由於內存對齊而損失的一小塊內存
    *((char*)p + 1 ) = '1';

    printf("%p\n",&a.a);
    printf("%p\n",&a.b);
    printf("%p\n",&a.c);

    return 0;
}
#endif

#if 0
union A{
    int     value;      // 0x0000 0001
    char    c[4];       // c[0] c[1] c[2] c[3]
};
// 0x12345678
//
// 大端機器存的位置相反(高位在低位)
void judge_machine_type(void)
{
    union A a = {1};

    if(a.value == a.c[0]){
        printf("This machine is small machine!\n");
    }else{
        printf("This machine is big machine!\n");
    }
}
int main (int argc, char **argv)
{
    judge_machine_type();
    return 0;
}
#endif

#if 0
//函數

//函數必備:
//
// 1.函數名
// 2.參數列表
// 3.返回值

// 規則:
// 1.函數先聲明再定義
// 2.函數調用時,實參和型參在數量、順序、類型上要保持一致
//
int min(int a, int b);

int min(int a, int b)
{
    return a > b ? b : a;
}

int main(int argc, char **argv)
{

    return 0;
}
#endif

#if 1
//void print_int_array(int *array, int length);
//
//void print_int_array(int *array, int length)
//{
//    int i = 0;
//    if (array!= NULL && length > 0){
//        for( i = 0; i < length; ++i ){
//            printf("%d  ",array[i]);
//        }
//        printf("\n");
//    }
//}
typedef void (*Print_func)(void *, int);

static void print_int(void *array, int index);
static void print_float(void *array, int index);

static void print_int(void *array, int index)
{
    printf("%d ",*((int *)array + index));
}
static void print_float(void *array, int index)
{
    printf("%f ",*((float *)array + index));
}


void foreach(void *array, int length, Print_func print);

void foreach(void *array, int length, Print_func print)
{
    int i = 0;
    for(i = 0; i < length; ++i){
        print(array,i);
    }
    printf("\n");
}

int main (int argc, char **argv)
{
    int array[] = {12,123,4,5,67,8,90};
    int length = sizeof(array) / sizeof(int) ;
    float array1[] = {12.4,1.3,4.6,0.123};
    int length1 = sizeof(array1) / sizeof(float);

    foreach(array, length, print_int);
    foreach(array1, length1, print_float);
    return 0;
}
#endif


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章