C基础知识

1、C开发环境:

使用的软件:DEVCPP_skycn.exe

2、HelloWorld.c 编写:

    #include
    int main(int argc, char args[]){
        printf("hello world");
        system("pause");      
        return 0; 
    }
c语言可以调用window指令。
例如eclipse.exe就是启动jar包来启动应用的。eclipse是java编写的
查看eclipse.ini里面
    -startup
    plugins/org.eclipse.equinox.launcher_1.3.0.v20140415-2008.jar
就是调用这个jar文件启动的

所以我们c程序调用java代码就可以
    system("java Hello_World");  

3、C的基本数据类型:

byte
short  2个字节
int    4个字节
long   4个字节
float  4个字节
double 8个字节
char   1个字节
boolean

例如:
        main(){
           signed int i = 3;
           //无符号只是注明最高位是数值位,但不会改变二进制表示的取值 
           unsigned int i2 = 4200000000;
           char c = 'a';
           long long ago = -420000000;

           printf("i的值为%d\n", i);
           printf("i2的值为%u\n", i2);
           printf("c的值为%c\n", c);

           printf("short的长度为%d\n", sizeof(short)); 
           printf("int的长度为%d\n", sizeof(int)); 
           printf("long的长度为%d\n", sizeof(long)); 
           printf("float的长度为%d\n", sizeof(float)); 
           printf("double的长度为%d\n", sizeof(double)); 
           printf("char的长度为%d\n", sizeof(char)); 
           printf("long long的长度为%d\n", sizeof(long long)); 
           printf("long int的长度为%d\n", sizeof(long int)); 
           printf("short int的长度为%d\n", sizeof(short int));
           system("pause");
        }
注意:
    int数据:4个字节,32位。能表示的数字是 2的32次方(4294967296) 个数字
    取值范围:0 ~ 2的32次方-1   (0~4294967295)

    如果最高位取出来作为符号位,用于表示正负,不再表示数值,剩下31个数值位。
        符号位如果为0,31个数值位表示的数字是正数。
        符号位如果为1,31个数值位表示出来的是负数。
    结合符号位,int型的取值范围 -2的31次方 ~ 2的31次方-1(-2147483648 ~ 2147483647)

原反补码问题
    计算机是存储的补码。
    正数原反补是一样的
    原码:二进制表示
    反码:除最高位,其他位依次取反
    补码:反码+1
    例如:
    5的源码:0000 0101

    -5的源码:1000 0101
    -5的反码:1111 1010
    -5的补码:1111 1011
    所以计算机存储的就是1111 1011

4、C的输出函数和输入函数:

输出函数:printf("%d\n", i);
    %d  -  int
    %ld – long int
    %lld - long long
    %hd – 短整型
    %c  - char
    %f -  float
    %lf – double
    %u – 无符号数
    %x – 十六进制输出 int 或者long int 或者short int
    %o -  八进制输出
    %s – 字符串

    注意:
        C语言中的字符串是字符数组
       //字符数组末尾一定有一个结束符“\0” 
       char str[] = "hello";
       printf("%s\n", str);

输入函数:scanf("%d", &count);
    例如:
        main(){
            printf("请输入班级人数:");
            int count;
            //取出count的内存地址,把用户输入的数据保存在这个地址上 
            scanf("%d", &count);

            printf("请输入班级名称:");
            //定义字符数组,必须指定长度
            //C的数组不检测越界 
            char name[7];
            scanf("%s", &name);

            printf("count的地址为%#x\n", &count);//取地址符
            printf("name的地址为%#x\n", &name);
            printf("班级人数为:%d,班级名称为%s\n", count, name); 
            system("pause");
        }
注意:
    C语言中,定义数组只能 char name[4]; 不能把[]写在前面,和java不一样
    C语言中数组不存在越界异常,但是我们不要越界,因为可能导致其它数据异常,
        因为越界的数据会占用其它数据的内存。

5、内存地址:

内存中所有数据都是通过地址拿到的,没有地址的内存是无法访问。

例如:
    int i;
    i = 10;
    printf("%d\n", i);
    printf("%#x\n", &i);
打印:
    10
    0x28ff1c

6、指针:

为什么要使用指针:
    可以直接访问硬件,可以操作硬件的内存,修改数据。
    可以返回一个以上的值
    int i;//申请了4个字节的内存
    i = 3;//赋值
    int* p = &i;//定义一个指针变量,指向int类型的指针,p一定存的是地址

    int** q = &p;//定义一个二级指针,q就是保存p的地址 
    printf("%d\n", i);//3
    printf("%#x\n", &i);//0x28ff18 ,i变量的地址
    printf("%#x\n", p);//0x28ff18,存的也是i变量的地址
    printf("%d\n", *p);//3
    printf("%d\n", **q);//3

    printf("%#x\n", &p);//0x28ff14 , p这个指针变量的地址
    printf("%#x\n", q);//0x28ff14, p这个指针变量的地址
注意:
    指针在没有赋值之前,是不能给指向的那个数据赋值的。因为开始定义指针是随机指向一个数据。
    有可能是指向系统关键数据,修改了就导致系统问题,所以不允许这样做
    例如:
    int* p ;
    *p=10;//这样运行会挂掉,p现在是随机指向一个数据的

C基础知识_第1张图片

7、指针的使用:

在主函数中获取子函数的变量地址
        void function(int* p){
            int i = 3;
            p = &i;
            printf("子函数打印地址%#x\n", &i);
        }
        main(){
           int* mainp;
           function(mainp);

           printf("主函数打印地址%#x\n", mainp);
           system("pause");
        }
这样是不行的,因为mainp这个变量占用一个内存,这个时候没有赋值,随机指向个数据。mainp传递给p,
    p这个时候也是和mainp指向的数据一样。p=&i,把p赋值了。这是mainp还是没有赋值,所以无效。

改造:使用二级指针
        void function(int** p){
            int i = 3;
            *p = &i;
            printf("子函数打印地址%#x\n", &i);
        }
        main(){
            int* mainp;
            function(&mainp);//传指针变量的地址

            printf("主函数打印地址%#x\n", mainp);
            printf("i的值为%d\n", *mainp);//拿到也是没有意义的,会销毁掉这个数据
            system("pause");
        }

C基础知识_第2张图片
注意:32位编译器,指针的长度是 4个字节(printf(“%d\n”,sizeof(int*));可以打印出来)

8、数组:

    int main(){
        //char c[] = "hello";
        int c[] = {1,2,3,4,5};
        printf("%#x\n", &c[0]); //0x28ff0c
        printf("%#x\n", &c[1]); //0x28ff10
        printf("%#x\n", &c[2]); //0x28ff14
        printf("%#x\n", &c[3]); //0x28ff18

        printf("%#x\n", c); //0x28ff0c  ,字符数组的地址,就是一个字符的地址

        int* p = c;
        //c+1表示位移一个单位,一个单位是几个字节根据指针类型决定 
        printf("第0个元素的值%d\n", *(p + 0));
        printf("第1个元素的值%d\n", *(p + 1));
        printf("第2个元素的值%d\n", *(p + 2));
        printf("第3个元素的值%d\n", *(p + 3)); 
        printf("两个地址的距离%d\n", (p + 3) - (p + 1)); 

        system("pause");
    }
注意:数组的内存空间是连续的

9、栈和堆

int i;
Person p;
p = new Person();

栈是先进后出的,是一段连续的内存空间。
定义的变量首先在栈内存中被分配空间(系统自动分配的),单你new 了对象,就在堆内存中分配空间。
当你的p使用完,弹栈了,堆内存的Person对象就是没有任何引用了,就是垃圾数据,会被回收器回收。

栈内存:
    内存空间是连续的
    自动分配
    大小固定
    系统自动释放
    栈上分配的内存叫静态内存
堆内存:
    程序员手动申请
        java:new
        c:malloc
    大小不固定,取决于系统虚拟内存
    程序员手动释放
        java:自动
        c:free函数
    空间不连续
    堆上分配的内存叫动态内存

C基础知识_第3张图片

10、申请内存:

    main(){
        //申请12个字节的堆内存 ,此函数返回堆内存的首地址 
        int* p = malloc(3 * sizeof(int));

        *(p + 1) = 3;
        printf("%d\n", *(p + 1));
        printf("%#x\n", p + 1);

        //释放堆内存 
        free(p);
        system("pause");
    }

11、结构体:

    void study(){
        printf("自定义函数\n");     
    }
    //结构体中不能定义函数,但是可以定义函数指针 
    struct student{
       int age;
       int height;
       char sex;

       void(*studyp)();//这个名称自己定义
    };
    int main(){
        struct student stu = {20, 190, 'f', study};
        printf("%d\n", stu.age);
        //为了方便位移运算,结构体中各个属性的长度会被自动补齐 
        printf("%d\n", sizeof(stu));

        //第一种调用方法,调用函数指针
        stu.studyp(); 

        //第二种调用方法
        struct student* stup = &stu;
        (*stup).studyp();

        //第三种调用方法
        //引用这个指针指向的结构体的属性 
        stup->studyp();//一般开发中这样写
        system("pause");
    }

12、共用体:

    main(){
        //共用体能表示这几种变量 
        union{int i; short s; char c;} un;
        //共用体同时只能赋一个值,新值会覆盖旧值
        //所以长度取决于最长的变量 
        un.i = 30;
        printf("%d\n", un.i);
        printf("%d\n", sizeof(un));

        un.s = 20;
        printf("%d\n", un.i);
        printf("%d\n", sizeof(un));

        system("pause");
    }
    打印的结果:
        30
        4
        20
        4
注意:同一时间,共用体只能存储一种数据。

13、枚举:

    enum WeekDay
    {
        Monday = 1,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
    };

    int main(void)
    {
        //int day;
        //枚举作用:规定了变量的取值范围 
        enum WeekDay day = Thursday;
        printf("%d\n",day);
        system("pause");
        return 0;
    }
打印的结果是:4

14、自定义类型:

    #include  
    #include   
    typedef int myint;
    main(){
        myint i = 3;
        printf("%d\n", i);

        system("pause");
    }
打印结果:3

只是给int起了个别名,有什么用呢?
例如:在C:\Program Files (x86)\Java\jdk1.7.0_10\include\jni.h中
    typedef unsigned char   jboolean;
    typedef unsigned short  jchar;
    typedef short           jshort;
    typedef float           jfloat;
    typedef double          jdouble;

增加代码的可阅读性。

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