变量的声明和定义有什么区别
变量的定义是为变量分配地址和存储空间,变量的声明不分配地址。
一个变量可以在多个地方声明,但是只在一个地方定义
加入extern
修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。
说明:很多时候一个变量,只是声明不分配内存空间,直到具体使用时才初始化,分配内存空间,如外部变量
int main() {
extern int A;
// 这是声明不是定义,声明A是一个外部变量
// 注意:声明外部变量时可以把变量类型去掉,如:extern A;
}
int A; // 定义,定义了A为整形的外部变量
简述#ifdef、#else、#endif和#ifndef的作用
利用#ifdef
、#endif
将某程序功能模块包括进去,以向特定用户提供该功能
在不需要时用户可轻易将其屏蔽。
#ifdef __MATH__
#include "math.c"
#endif
在子程序前加上标记,以便于追踪和调试。
#ifdef DEBUG
printf ("In debugging......!");
#endif
应对硬件的限制。由于一些具体应用环境的硬件不一样,限于条件,本地缺乏这种设备,只能绕过硬件,直接写出预期结果。
注意:虽然不用条件编译命令而直接用
if
语句也能达到要求,但那样做目标程序长(因为所有语句都编译),运行时间长因为在程序运行时间对if
语句进行测试)。而采用条件编译,可以减少被编译的语句,从而减少目标程序的长度,减少运行时间
写出int/bool/float/指针变量与“零值”比较的if语句
// int与零值比较
if (n == 0)
if (n != 0)
// bool与零值比较
if (flag) // 表示flag为真
if (!flag) // 表示flag为假
// float与零值比较
const float EPSINON = 0.00001;
if ((x >= -EPSINON) && (x <= EPSINON)) //其中EPSINON是允许的误差(即精度)
// 指针变量与零值比较
if (p == NULL)
if (p != NULL)
结构体可以直接赋值吗
声明时可以直接初始化,同一结构体的不同对象之间也可以直接赋值,但是当结构体中含有指针成员时一定要小心。
注意:当有多个指针指向同一段内存时,某个指针释放这段内存可能会导致其他指针的非法操作,因此在释放前一定要确保其他指针不再使用这段内存空间
sizeof 和strlen 的区别
sizeof
是一个操作符,strlen
是库函数。sizeof
的参数可以是数据的类型,也可以是变量,而strlen
只能以结尾为'\0'
的字符串作参数。- 编译器在编译时就计算出了
sizeof
的结果,而strlen
函数必须在运行时才能计算出来。并且sizeof
计算的是数据类型占内存的大小,而strlen
计算的是字符串实际的长度。 - 数组做
sizeof
的参数不退化,传递给strlen
就退化为指针了
int main() {
char str[6] = "hello";
cout << sizeof(str) << endl; // 输出数组大小:6
cout << strlen(str) << endl; // 输出字符串长度:5
return 0;
}
C 语言的关键字 static 和 C++ 的关键字 static 有什么区别
在C
中static
用来修饰局部静态变量和外部静态变量、函数。而C++
中除了上述功能外,还用来定义类的成员变量和函数,即静态成员和静态成员函数
注意:编程时,static
的记忆性和全局性的特点可以让在不同时期调用的函数进行通信,而C++
的静态成员则可以在多个对象实例间进行通信
C 语言的 malloc 和 C++ 中的 new 有什么区别
new
和delete
是操作符,可以重载,只能在C++
中使用malloc
和free
是函数,可以覆盖,C/C++
中都可以使用new
可以调用对象的构造函数,对应的delete
调用相应的析构函数malloc
仅仅分配内存,free
仅仅回收内存,并不执行构造和析构函数new
和delete
返回的是某种数据类型指针,malloc
和free
返回的是void
指针
注意:malloc
申请的内存空间要用free
释放,而new
申请的内存空间要用delete
释放,不要混用
size_t
size_t
是cstddef
头文件定义的一种与机器实现有关的无符号整数类型,他的空间足够大,能够表示任意数的大小
extern “C”
之所以C++支持函数重载,是因为C++在函数编译阶段对函数名进行再次命名,生成一个函数的签名,这个签名不仅包含函数名,还包含函数的参数列表,所以只要参数列表不同,就可以实现函数的重载
而C语言不支持函数重载,所以函数的签名仅包含函数名信息
假设一个函数display声明在myfun.h头文件中,定义在mufun.c文件中,然后要再main.cpp文件中使用
// myfun.h
void display();
// myfun.c
#include <stdio.h>
#include "myfun.h"
void display() {
printf("hello");
}
// main.cpp
#include <iostream>
#include "myfun.h"
using namespace std;
int main() {
display();
return 0;
}
预处理的时候会将头文件的内容拷贝到myfun.c和main.cpp文件中,编译时,由于myfun.c是用C语言编译的,编译后的函数签名仅跟函数名有关,而main.cpp是用C++编译的,函数签名与函数名和参数列表有关,这样,当调用display时,由于函数签名不同,就找不到display函数的定义了
所以我们应该让display函数在main.cpp中使用C语言的编译方式,只要在myfun.h中使用extern “C”来修饰display就可以了
#ifdef __cplusplus
extern "C" void display();
#else
void display();
#endif
这样在拷贝到main.cpp文件时,会选择extern “C”修饰的display函数,而在拷贝到myfun.c时,会选择不带extern “C”修饰的display函数,保证都可以按C语言的标准来处理