C语言常见问题

问题1:sizeof与strlen区别

1、sizeof()

sizeof()是一种单目操作符,是用来计算你所使用的操作数所占的空间字节大小。
可以以类型、指针、数组和函数等作为参数,返回值类型为unsigned int。

2、strlen
strlen 是一个函数,它用来计算指定字符串 str 的长度,但不包括结束字符(即 null 字符)。

#include <stdio.h>
#include <string.h>

int main()
{
	char a[] = "abc";
    int b;
    int c;
    
    printf("%d\n",sizeof(a));
    printf("%d\n",strlen(a));

	return 0;
}

输出结果

4                                                                                                               
3

问题2:main函数三个参数

1.int argc 整型变量

2.char *argv[] 字符指针的数组,通俗一点就是字符串数组,每个元素都是字符串

3.char *envp[] 字符串数组

问题3:全局变量和局部变量的区别

1.作用域不同:全局变量的作用域为整个程序,局部变量的作用域为当前语句块;

2.内存储存方式:全局变量存储在全局数据区,局部变量存储在栈上;

3.生命周期不同:全局变量的生命周期和程序一样,局部变量随着语句块的结束而结束;

4.当局部变量与全局变量同名时,优先使用局部变量。

问题4:程序的内存分配

运行程序的内存分为堆区、栈区、BSS区、数据区(初始化)、代码区。

  • 栈区(stack):由编译器自动分配与释放,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。其操作类似于数据结构中的栈。
  • 堆区(heap):一般由程序员自动分配,如果程序员没有释放,程序结束时可能有OS回收。其分配类似于链表。
  • 全局区(静态区static):存放全局变量、静态数据、常量。程序结束后由系统释放。全局区分为已初始化全局区(data)和未初始化全局区(bss)。
  • 常量区(文字常量区):存放常量字符串,程序结束后有系统释放。
  • 代码区:存放函数体(类成员函数和全局区)的二进制代码。
//main.cpp
int a=0; //全局初始化区
char *p1; //全局未初始化区
main()
{
int b;char s[] = ”abc”; //栈
char p2; //栈
char p3=123456; //123456\0 在常量区,p3 在栈上。
static int c=0//全局(静态)初始化区
p1 = (char)malloc(10);
p2 = (char)malloc(20); //分配得来得 10 和 20 字节的区域就在堆区。
strcpy(p1,123456); //123456\0 放在常量区,编译器可能会将它与 p3 所向”123456″优化成一个地方。
}

从静态存储区分配

内存在程序编译的时候已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。

在栈上创建

在执行函数时,函数内局部变量的存储单元可以在栈上创建,函数执行结束时,这些内存单元会自动被释放。
栈内存分配运算内置于处理器的指令集,效率高,但是分配的内存容量有限。

从堆上分配

动态内存分配。
程序在运行的时候使用malloc或者new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。
动态内存的生命周期有程序员决定,使用非常灵活,但如果在堆上分配了空间,既有责任回收它,否则运行的程序会出现内存泄漏,频繁的分配和释放不同大小的堆空间将会产生内存碎片。
请添加图片描述

问题5:结构体和联合体的区别

结构体中,各成员占有自己的储存空间,总大小等于各成员的大小之和。
联合体中,所有成员公用一块储存空间,其大小等于联合体中最大成员的大小。

问题6:指针函数和函数指针的区别

指针函数
指针函数是指带指针的函数,即本质是一个函数。函数返回类型是某一类型的指针

 类型标识符    *函数名(参数表)

 int *f(x,y);

函数指针
函数指针是指向函数的指针变量,即本质是一个指针变量,这个指针指向的对象是一个数组。

int (f) (int x);	/* 声明一个函数指针 */
f=func; 			/* 将func函数的首地址赋给指针f */

这个特殊的指针指向一个返回整型值的函数。
例如:

void (*fptr)();

把函数的地址赋值给函数指针,可以采用下面两种形式:

fptr=&Function;
fptr=Function;

最简单的辨别方式就是看函数名前面的指针号有没有被括号()包含,如果被包含就是函数指针,反之则是指针函数。*

问题7:指针自增自减与变量自增自减有什么区别?

指针自增自减是改变指针所指向的对象,变量自增自减是改变变量的值;

问题8:#include <stdio.h>#include "stdio.h"的区别?

<stdio.h>表示的是该文件存在编译器指定的标准头文件存放处

"stdio.h"表示的是该文件在用户当前的工作目录下

问题9:用#define实现宏并求最大值与最小值

#define MAX(X,Y) ((X)>(Y)?(X):(Y))

#define MIN(X,Y) ((X)<(Y)?(X):(Y))

三目运算符:(a ? y : z
先判断条件 a 真假,如果 a 的值为 true ,那么返回表达式 y 的计算结果;否则,计算 z 的值,返回表达式 z 的计算结果。

问题10:static与const关键字的区别

  • static关键字

(1)static 全局变量 :表示该变量是静态全局变量,在当前文件的全局内可访问。

(2)static 函数 :该函数为静态函数,只能在本文件中调用;静态函数在内存中只有一份,普通函数在内存中只有一份拷贝。

(3)static局部变量:为静态局部变量,只初始化一次,之后调用函数都是上次函数退出的值。这个局部变量在函数执行完成之后不会被释放,而是继续保留在内存中。

(4)static成员函数:表示这个函数为全类所共有,而且只能访问静态成员变量。

(5)static成员变量:表示这个成员为全类所共有。

  • const 关键字

(1)const 常量:定义时就初始化,以后不能更改。
const 形参:该形参在函数里不能改变

func(const int a)
	{
	
	};

const修饰类成员函数:该函数对成员变量只能进行只读操作

(2)修饰数组:修饰符const可以用在类型说明符前,也可以用在类型说明符后;例如:int const a[5]={1,2,3};或 const int a[5]={1,2,3};

(3)修饰常指针:const int *A; //const修饰指针指向的对象,指针可变,指针指向的对象不可变;

举例:
int const *A; //修饰指针指向的对象,指针可变,指针指向的对象不可变;
int *const A;//const修饰指针,指针不可变,指针指向的对象可变;

const int *x ---->x的地址可以输出但是数据不能输出
int const *x ---->x的地址可以输出但是数据不能输出
int *const x ---->x的地址不可以输出但是数据可以输出
const int *const x ---->x的地址和数据都不能输出
总结:左数右址 (数表示数据,指表示变量的地址 ,左右就是const在指针变量的左边或者右边)

问题11:malloc()

malloc是从堆上动态申请内存空间,malloc只有一个参数,即要分配的内存大小。malloc不能对内存初始化。

int* p;

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

malloc 函数返回的是 void * 类型,必须通过 (int *) 来将强制转换。

malloc函数在动态分配数组空间时,只会增大空间,不会减小空间,所以说如果不释放内存,可能会造成内存溢出。因为如果地址没了,内存被占了但是还无法调用,就很难受。
所以此时我们调用free();函数释放内存
一般地,对应每个malloc()调用,应该调用一次 free()函数free ()的参数是先前malloc ()返回的地址,它释放先前分配的内存。

问题12:strcpy、sprintf和memcpy的区别

char*strcpy(char *dest, const char *src);
int sprintf(char*str, const char *format, ...);
void *memcpy(void*dest, const void *src, size_t n)
  1. 复制的内容不同。
    strcpy只能复制字符串;sprintf 函数操作的对象 不限于字符串;而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。

  2. 复制的方法不同。
    strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。

  3. 用途不同。
    通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。
    sprintf主要用来实现(字符串或基本数据类型)向字符串的转换 功能。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值