⭐️ 关键字深度剖析 ⭐️第六章(关键字void\return\const)

简介: 本章主要讲解:深入关键字void深入关键字return深入关键字const

void不能定义变量

  • 示例:
1. int main() 
2. { 
3. void a; 
4. return 0;
5. }
6. 在vs2013和Centos 7,gcc 4.8.5下都不能编译通过
  • 解释:

定义变量的本质:开辟空间

void作为空类型,理论上是不应该开辟空间的,即使开了空间,也仅仅作为一个占位符看待

所以无法作为正常变量使用,故不能定义变量


void修饰函数返回值和参数

void用来作为函数返回值

void show()
{ 
    printf("no return value!\n"); 
}
int main() 
{ 
    show(); 
    return 0; 
}
//如果自定义函数,或者库函数不需要返回值,那么就可以写成void


注:不能不写,否则自定义函数的默认返回值是int(不写也会引起误会)

结论:void作为函数返回值,代表不需要

用来作为"占位符",告知编译器和阅读源代码的人

void 作为函数参数


int test1() //函数默认不需要参数 
{ 
    return 1; 
}
int test2(void) //明确函数不需要参数 
{ 
    return 1; 
}
int main() 
{ 
    printf("%d\n", test1(10)); //依旧传入参数,编译器不会告警或者报错 
    printf("%d\n", test2(10)); //依旧传入参数,编译器会告警(vs)或者报错(gcc)  
    return 0; 
}

结论:如果一个函数没有参数,将参数列表设置成void

可以将错误明确提前发现同时可以告知阅读你代码的人

void *指针

void*能否定义变量?

int main() 
{ 
    void *p = NULL; //可以 
    return 0; 
}
  • 解释:

void*是指针,而只要是指针空间大小就能明确出来

void* 接受任意指针类型


int main() 
{ 
    void *p = NULL; 
    int *x = NULL; 
    double *y = NULL; 
    p = x; //虽然类型不同,但是编译器并不报错 
    p = y; //同上
    return 0; 
}

结论:void*一般是用来接受任意指针类型的(对于不知道类型的传址用来设计通用接口)

  • 示例:
void * memset ( void * ptr, int value, size_t num );//memset库函数
 int compare (const void * a, const void * b);//qsort库函数的compare函数设计

void * 定义的指针变量运算操作

结论:对于不同编译器,看待void空间大小不同,所以能否运算的结果不同

int main() 
{ 
    void *p = NULL; p++; 
    p += 1; 
    return 0; 
}

现象:vs中报错 gcc能通过

关键字-return

int test() 
{ 
    int a = 10; 
    return a; //a是函数定义的变量,具有临时性,临时变量在函数退出的时候被释放
}
int main() 
{ 
    int a = test(); 
    printf("%d\n", a); 
    return 0; 
}
  • 返回值临时变量的本质:

对于一般内置类型,寄存器eax可以充当返回值的临时空间(存储返回值)

2021082015124585.png

注意:当不接受返回值时,返回值依旧会传给寄存器eax

返回值在函数创建和销毁中具体过程:C语言内功的修炼--函数栈帧创建和销毁

关键字-const


const 修饰变量

int main()
{ 
    const int i = 10; 
    i = 20; //报错,代表变量i不可以直接被修改 
    return 0; 
}

注意:是不能直接修改,但可以通过指针来修改

  • 示例:
int main() 
{ 
    const int i = 10; 
    int *p = (int*)&i; 
    printf("before: %d\n", i); 
    *p = 20; 
    printf("after: %d\n", i);
    return 0; 
}

意义:告诉编译器(便于直接检查出来),告诉程序员不要修改

注意:const定义的变量是常变量,本质上还是变量,一般无法作为数组定义的一部分

int main() 
{ 
    const int n = 100; 
    int arr[n]; //一般编译器会报错
    return 0; 
}

注意:const只能在定义的时候直接初始化,不能二次赋值

解释:const定义时如果没有赋值,但是会随机默认化(相当于初始化赋值了)

二次赋值是删去原值再修改,编译器会报错

const char * \char const *\ char * const 三者的区别

  • const char *ptr等价于char const *ptr

const都在*左边,const修饰*,表示*ptr不能直接修改

即不能直接改变指针指向的内容,但可以直接改变指针指向

  • char *const ptr

const在*右边,const修饰ptr表示不能直接改变指针指向,但可以直接改变指针指向的内容


相关文章
|
2月前
【C初阶——基本语法】return关键字
【C初阶——基本语法】return关键字
|
4月前
|
存储 C语言
C语言学习记录——复习数据存储类别(auto、register、static、extern)
C语言学习记录——复习数据存储类别(auto、register、static、extern)
32 1
|
5月前
|
编译器 C语言 C++
从C语言到C++③(第一章_C++入门_下篇)内联函数+auto关键字(C++11)+范围for+nullptr(下)
从C语言到C++③(第一章_C++入门_下篇)内联函数+auto关键字(C++11)+范围for+nullptr
42 0
|
5月前
|
存储 安全 编译器
从C语言到C++③(第一章_C++入门_下篇)内联函数+auto关键字(C++11)+范围for+nullptr(上)
从C语言到C++③(第一章_C++入门_下篇)内联函数+auto关键字(C++11)+范围for+nullptr
40 0
|
存储 安全 编译器
【C++入门必备知识:|引用| +|auto关键字| + |范围for|】
引用不是新定义一个变量,而是给已经存在的变量取别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存区间。
121 0
|
存储 编译器 C语言
关键字深度剖析 ⭐️第一章(变量&关键字auto/register)(一)
本文主要讲解点: 初步了解关键字分类 深刻理解变量 深刻理解定义与声明 auto关键字的理解 站在存储结构角度,理解register
关键字深度剖析 ⭐️第一章(变量&关键字auto/register)(一)
⭐️ 关键字深度剖析 ⭐️第二章(多文件\数据类型&关键字extern/static)
本文主要讲解点: extern的使用 多文件的作用 static的作用 如何看待类型 变量的命令规则 sizeof 的理解
⭐️ 关键字深度剖析 ⭐️第二章(多文件\数据类型&关键字extern/static)
|
存储 C语言
⭐️ 关键字深度剖析 ⭐️第五章(深入C语言三种类型(float/bool/指针)与“零值“的比较)(续)
浮点数在内存中存储,并不想我们想的是完整存储的 在十进制转化成为二进制,是有可能有精度损失的
⭐️ 关键字深度剖析 ⭐️第五章(深入C语言三种类型(float/bool/指针)与“零值“的比较)(续)
|
存储 编译器 C语言
⭐️ 关键字深度剖析 ⭐️第五章(深入C语言三种类型(float/bool/指针)与“零值“的比较)
浮点数在内存中存储,并不想我们想的是完整存储的 在十进制转化成为二进制,是有可能有精度损失的
⭐️ 关键字深度剖析 ⭐️第五章(深入C语言三种类型(float/bool/指针)与“零值“的比较)
|
存储 C++
⭐️ 关键字深度剖析 ⭐️第三章(关键字sizeof\signed\unsigned&原反补\数据范围)(一)
本文主要讲解点 关键字sizeof的理解 关键字signed\unsigned的理解 掌握原反补概念 深刻理解数据的取值范围
⭐️ 关键字深度剖析 ⭐️第三章(关键字sizeof\signed\unsigned&原反补\数据范围)(一)