C语言零碎知识点

这篇博客详细探讨了C语言中的各种核心知识点,包括不使用sizeof求int占用的字节数、struct与union的区别、左值与右值的概念、a++与++a的操作差异、堆和栈的内存管理以及#define和const定义常量的比较。此外,还讨论了#include预处理指令的用法、内存泄漏问题、内存管理方式、进程状态、关键字static的作用、位运算符的使用、printf参数运算、计算平均数的方法、两数交换技巧以及extern"C"在C++中调用C函数的必要性。博客涵盖了C语言的基础和高级概念,适合初学者和有经验的开发者参考。
摘要由CSDN通过智能技术生成

目录

1、不使用sizeof,如何求int占用的字节数

2、struct和union

3、左值与右值

4、a++与++a的区别

5、堆和栈有什么区别

6、定义常量谁更好? #define还是const?

7、#include 和#include "filename.h"有什么区别?

8、内存泄漏

9、内存管理有哪几种方式

10、进程的几种状态

11. 关键字static的作用是什么?

12. &与&& |与||

13. printf参数的运算

14. 计算平均数

 15. 两个数的交换

16. 在C++程序中调用被C编译器编译后的函数,为什么要加extern"C"?

17. C与C++的各自特点

18. 用一个宏定义求一个结构体struct里某个变量相对struct的偏移量

19. 用define声明一个常数,用以表明1年中有多少秒

20. const有什么用途?

21. 结构体中含有静态变量时,sizeof()

22. strlen

23. sizeof

24. 关键字volatile有什么含意?

25. 一个参数可以既是const又是volatile吗?一个指针可以是volatile吗?

26. 评价下面的代码片段,找出其中的错误。

27. 循环链表(约瑟夫环)

28. 堆和栈申请后系统的响应

29. 堆和栈区别的奇妙比喻

30. 下面代码有什么问题,如何修改?


1、不使用sizeof,如何求int占用的字节数

#include <stdio.h>
#define MYSIZEOF(value) (char *)(&value+1)-(char *)&value
int main()
{
    int i;
    double f;
    double *p;
    printf("%d\n", MYSIZEOF(i));
    printf("%d\n", MYSIZEOF(f));
    printf("%d\n", MYSIZEOF(q));
    return 0;
}

2、struct和union

typedef union {
    double i; 
    int k[5]; 
    char c;
}DATE;
typedef struct data {
    int cat;
    DATE cow;
    double dog;
}too;
DATE max;
printf("%d\n", sizeof(too)+sizeof(max));

假设为32位机器,int型占4个字节, double型占8个字节,char型占1个字节,而DATE是一个联合型变量,联合型变量共用空间,uion里面最大的变量类型是int[5],所以占用20个字节,它的大小是20,而由于 union中 double占了8个字节,因此 union是要8个字节对齐,所占内存空间为8的倍数。为了实现8个字节对齐,所占空间为24.而data是一个结构体变量,每个变量分开占用空间,依次为 sizeof(int)+ sizeof(DATE)+ sizeof( double)=4+24+8=36按照8字节对齐,占用空间为40,所以结果为40+24=64。

3、左值与右值

  • 左值是指可以出现在等号左边的变量或表达式,它最重要的特点就是可写(可寻址)。也就是说,它的值可以被修改,如果一个变量或表达式的值不能被修改,那么它就不能作为左值。

  • 右值是指只可以出现在等号右边的变量或表达式。它最重要的特点是可读。一般的使用场景都是把一个右值赋值给一个左值。

  • 通常,左值可以作为右值,但是右值不一定是左值。

4、a++与++a的区别

a++的具体运算过程如下

int temp = a;
a = a + 1;
return temp;

++a的具体运算过程如下

a = a + 1;
return a;

后置自增运算符需要把原来变量的值复制到一个临时的存储空间,等运算结束后才会返回这个临时变量的值。所以前置自增运算符效率比后置自增要高。

5、堆和栈有什么区别

  1. 申请方式 栈的空间由操作系统自动分配/释放,堆上的空间手动分配/释放。

  2. 申请大小的限制栈空间有限。 在Windows下,栈是向低地址扩展的数据结 构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是 一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小堆是很大的自由存储区。

    堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

  3. 申请效率 栈由系统自动分配,速度较快。但程序员是无法控制的。 堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.

6、定义常量谁更好? #define还是const?

尺有所短,寸有所长, define与 const都能定义常量,效果虽然一样,但是各有侧重。

define既可以替代常数值,又可以替代表达式,甚至是代码段,但是容易出错,而 const的引入可以增强程序的可读性,它使程序的维护与调试变得更加方便。具体而言,它们的差异主要表现在以下3个方面。

  1. define只是用来进行单纯的文本替换, define常量的生命周期止于编译期,不分配内存空间,它存在于程序的代码段,在实际程序中,它只是一个常数;而 const常量存在于程序的数据段,并在堆栈中分配了空间,const常量在程序中确确实实存在,并且可以被调用、传递

  2. const常量有数据类型,而 define常量没有数据类型。编译器可以对 const常量进行类型安全检査,如类型、语句结构等,而 define不行。

  3. 很多IDE支持调试 const定义的常量,而不支持 define定义的常量由于 const修饰的变量可以排除程序之间的不安全性因素,保护程序中的常量不被修改,而且对数据类型也会进行相应的检查,极大地提高了程序的健壮性,所以一般更加倾向于用const来定义常量类型。

7、#include <filename.h>和#include "filename.h"有什么区别?

对于#include <filename.h>,编译器先从标准库路径开始搜索filename.h,使得系统文件调用较快。而对于#include "filename.h",编译器先从用户的工作路径开始搜索filename.h,然后去寻找系统路径,使得自定义文件较快。

8、内存泄漏

在堆上分配的内存,如果不再使用了,就应该及时释放,以便后面其他地方可以重用。而在C语言中,内存管理器不会自动回收不再使用的内存。如果忘了释放不再使用的内存,这些内存就不能被重用了,这就造成了内存泄漏。

9、内存管理有哪几种方式

常见的内存管理方式有块式管理、页式管理、段式管理和段页式管理。最常用的是段页式管理

  1. 块式管理:把主存分为一大块一大块的,当所需的程序片断不在主存时就分配一块主存空间,把程序片断载入主存,就算所需的程序片段只有几个字节,也只能把这一块分配给它。 这样会造成很大的浪费,平均浪费了50%的内存空间,但是易于管理。

  2. 页式管理:用户程序的地址空间被划分成若干个固定大小的区域,这个区域被称为页”,相应地,内存空间也被划分为若干个物理块,页和块的大小相等。可将用户程序的任一页放在内存的任一 块中, 从而实现了离散分配。这种方式的优点是页的大小是固定的,因此便于管理;缺点是页长与程序的逻辑大小没有任何关系。这就导致在某个时刻一个程序可能只有一部分在主存中,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值