• C语言-第4课


    第4课 - goto,void,extern,sizeof分析

    国嵌课程笔记

    4.1 goto

    高手潜规则:禁用goto

    项目经验:程序质量与goto的出现次数成反比

    最后的判决:将goto打入冷宫

    我们分析如下的程序:

    #include <stdio.h>

    void func(int n)

    {

        int* p = NULL;

        if(  n < 0 )

        {

            goto STATUS;

        }

        p = malloc(sizeof(int) * n);

    STATUS:

        p[0] = n;    

    }

    int main()

    {  

        f(1);

        f(-1);   

        return 0;

    }

    我们运行该程序,若是n小于0,就会跳过堆内存的分配,而此时的p是空指针,给空指针赋值,就会出现程序的崩溃。当n是大于0的情况下,就会执行很好。也就是说goto命令破坏了,程序的顺序执行。

    4.2 void

    1. void修饰函数返回值和参数。

    如果函数没有返回值,那么应该将其声明为void型;如果函数没有参数,应该声明其参数为voidviod修饰函数返回值和参数仅为了表示无。

    1. 不存在void变量

    c语言没有定义void究竟是多大内存的别名,没有void的标尺,无法在内存中剪裁出void对应的变量。

    1. void指针的意义

    (1) c语言规定只有相同类型的指针才可以相互赋值

    (2) void*指针作为左值用于“接收”任意类型的指针

    (3) void*指针作为右值给其它指针时需要强制类型转换

    int* pI = (int*)malloc(sizeof(int));  //malloc返回值是void的指针

    char* pC = (char*)malloc(sizeof(char));

    void* p = NULL;

    int* pni = NULL;

    char* pnc = NULL;

    p = pI;   // ok

    pbi = p;  // oops!

    p = pC; // ok

    pnc = p; // oops!

    (4)手把手教学--实现memset函数    

     

    #include<stdio.h>

    void* memset(void* p, char v, int size)

    {

    void* ret = p;

    char* dest = (char*)p;

    int i = 0;

    for(i=0;i<size;i++)

    {

    dest[i] = v;

    }

    return ret;

    }

    int main()

    {

    int a[5] = {1,2,3,4,5};

    int i = 0;

    for(i=0; i<5; i++)

    {

    printf("%d ",a[i]);

    }

    memset(a, 0, sizeof(a));

    for(i=0; i<5; i++)

    {

    printf("%d ",a[i]);

    }

    return 0;

    }

    运行结果:

    1

    2

    3

    4

    5

    0

    0

    0

    0

    0

    void*可以传递任意类型的地址值,无论是数还是数组

    4.3 extern

    l extern用于声明外部定义的变量和函数

    l extern用于“告诉”编译器用C方式编译

    C++编译器和一些变种C编译器默认会按“自己”的方式编译函数和变量,通过extern关键可以命令编译器“以标准C方式进行编译”。例如:

    extern “C”

    {

    int f(int a,int b)

    {

    return a + b;

    }

    }

    例程:

    // test.c

    #include <stdio.h>

    /*

    extern "C"

    {

        int add(int a, int b)

        {

            return a + b;

        }

    }

    */

    extern int g;

    extern int get_min(int a, int b);

    int main()

    {  

    printf("%d ",g);

    printf("%d ",get_min(1, 5));

        return 0;

    }

    // test2.c

    int g = 100;

    int get_min(int a, int b)

    {

        return (a < b) ? a : b;

    }

    4.4 sizeof证明

    l sizeof是编译器的内置指示符,不是函数

    l sizeof用于“计算”相应实体所占的内存大小

    l sizeof的值在编译期间就已经确定

    例程:

    #include <stdio.h>

    int main()

    {  

        int a;

        printf("%d ", sizeof(a));

        printf("%d ", sizeof a);

        printf("%d ", sizeof(int));

        return 0;

    }

    运行结果:

    4

    4

    4

  • 相关阅读:
    C# Activator.CreateInstance 动态创建类的实例(二)
    C# Activator.CreateInstance 动态创建类的实例(一)
    C#中Activator.CreateInstance()方法用法分析
    C#实现插件的“动态替换”
    Windows Mobile X图标如何销毁窗体而非隐藏
    Windows Mobile 6开发环境搭建
    Mac系统下配置JDK及MAVEN环境变量配置
    通过 mklink 命令创建目录链接实现文件转移
    SQL SERVER 存储过程示例
    BNU 34990 Justice String (hash+二分求LCP)
  • 原文地址:https://www.cnblogs.com/free-1122/p/9693267.html
Copyright © 2020-2023  润新知