1问题:Stdio.h 的主要作用?

回答:stdio .h头文件定义了三个变量类型、一些宏和各种函数来执行输入和输出。C语言

2问题: \n \r \t什么意思?

回答:'\n' 换行, 将当前位置移到下一行开头;

\r是回车, 将当前位置移到本行开头;

\t水平制表(HT) (跳到下一个TAB位置。

3问题:||| &&&的区别?

回答:首先 &和|称为位运算符(按位进行与或),&&和||(按结果真假或0/1进行与或)称为逻辑运算符;逻辑运算符性能比较好。他检查第一个操作数的值,再根据该操作数的值进行操作,可能根本就不处理第二个操作数。使用&&和||运算符来代替&和|,性能会有一定提高。

4问题: 后缀名为.c.cpp?

回答:.c是c语言的源程序格式,.cpp是c++语言的源程序格式;C89规定,在任何执行语句之前,在块的开头声明所有局部变量。在C99以及C++中则没有这个限制,即在首次使用之前,可在块的任何位置都可以声明变量。

5问题: 不使用任何中间变量如何将a/b的值进行交换?

回答:①使用加减运算实现交换,a=a+b; b=a-b; a=a-b;(在a+b与a-b可能数据溢出)

②使用局部变量,int temp=a; a=b; b=temp;

③使用异或运算,a^=b; b^=a; a^=b;

6问题:cc++有什么不同?

回答:C是一个结构化的语言,重点在于算法和数据结构,对语言本身C是C++的子集。

C程序的设计首先考虑的是如何通过一个过程实现对输入进行运算后输出,对于C++考虑的是如何构造一个对象模型,让这个模型能够匹配对应的问题,通过获取对象的状态信息得到输出或实现过程控制。

因此,C与C++的最大区别在于,他们解决问题的思路方法是不一样的。

C实现了C++中过程化控制及其他相关功能,而在C++中相对于C还有所加强,引入了重载、内联函数、异常处理等,同时拓展了面向对象的设计内容,如类、继承、虚函数、模板等。

附:C是面向过程的、C++面向对象(在C++中一样可以写出与C一样过程化的程序,所以只能说C++具有面向对象的特性)、Java是真正面向对象化的程序。

7问题: 为什么标准头文件都有#ifndef  _xxxxxx; #define _xxxxxx          #endif?

回答:这样定义是为了避免重复定义。重复声明可以,但是重复定义是不可以的。重复声明只要名称完全相同即可。但是重复定义会出现编译错误的,即使同名也不可以。

8问题: #include<head.h>#include “head.h”的区别?

回答:尖括号< >表明这个文件是一个工程或标准的头文件,在预处理查找过程中会首先检查系统预定义的目录,如果没有找到就报错。

双引号" "表明这是一个用户自定义的头文件,查找文件的时候会先在当前文件目录中查找,如果没有找到再去系统预定义的目录中查找,如果没有找到再报错。

9问题:关于宏定义#define ARR_SIZE(a)   (sizeof(a)/sizeof(a[0]))),假设一个数组定义如下 int array[100]?

回答:如果int为4个字节,那么sizeof(array)就为400个字节,sizeof(a[0])为一个int的大小,即4个字节。两个数一除就是数组元素个数。

10问题: 关于const的使用注意点,例子如下:

#include <stadio.h>
Int main()
{
const int x=1;
int b=10;

int c=20;
const int *a1=&b;
int * const a2=&b;
const int* const a3=&b;

x=2;      //错误

a1=&&c;   //正确
*a1=1;    //错误

a2=&c;    //错误
*a2=1;    //正确

a3=&c;    //错误
*a3=1;    //错误
return 0;
}

回答:x=2;,由于x为整型常量,因此不能改变x的值。

a1=&&c;中const在int*的左侧,它修饰的是指针所指向的变量,即指针指向为常量,故a1=&&c正确; *a1=1;错误,其它的判断类似。

int * const p ;表示指针变量本身不能被修改

const int *p这表示p所指向的空间内容不可修改

11问题: const有什么作用?

回答:①定义const常量,具有不可变性,进行类型检查,消除一些隐患

           ②保护被修饰的东西,防止被意外修改,增强了程序的健壮性。

           ③为函数重载提供参考

           ④节省空间,避免不必要的内存分配

引申:什么情况下需要使用const关键字?

           1. 修饰一般常量。eg.int const x=2 或 const int x=2。

           2. 修饰常数组。eg. int const a[8] = {1,2,3,4,5,6,7,8};  const int a[8]={1,2,3,4,5,6,7,8};

           3. 修饰常对象。常对象是指对象常量。eg. class A; const A a; A const a;

             定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符const可以放在类名后面,也可以放在类名前面。

           4. 修饰常指针

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

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

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

const int *const A; //指针A和A指向的对象都不可变

12问题: static有什么作用?

回答1:1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

           2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

           3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用

回答2:在C语言中,static主要定义全局静态变量,定义局部静态变量,定义静态函数

 一、定义全局静态变量 :在全局变量前面加上关键字static,该全局变量变成了全局静态变量。

 二、定义局部静态变量:在局部静态变量前面加上关键字static,该局部变量便成了静态局部变量。其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。

三、定义静态函数:在函数的返回类型加上static关键字,函数即被定义成静态函数。静态函数有以下特点:

(1)静态函数只能在本源文件中使用

(2)在文件作用域中声明的inline函数默认为static

说明:静态函数只是一个普通的全局函数,只不过受static限制,他只能在文件所在的编译单位内使用,不能呢个在其他编译单位内使用。

在C++语言中新增了两种作用:定义静态数据成员静态函数成员

(1)定义静态数据成员。静态数据成员有如下特点:

(1)内存分配:在程序的全局数据区分配

(2)初始化和定义:静态数据成员定义时要分配空间,所以不能在类声明中定义

(3)静态成员函数。静态成员函数与类相联系,不与类的对象相联系。静态成员函数不能访问非静态数据成员。原因很简单,非静态数据成员属于特定的类实例,主要用于对静态数据成员的操作。

(4)静态成员函数和静态数据成员都没有this指针。

13问题:一个指针占用几个字节?

回答:指针即为地址,指针占几个字节跟语言无关,而是跟系统的寻址能力有关,譬如:以前是16位地址,指针即为2个字节,现在一般是32位系统,所以是4个字节,以后64位,则就占8个字节

14问题: strlensizeof有什么区别?

回答:①strlen是函数,sizeof是操作符;

           ②在计算字符串数组的长度上有区别,如

char str[20]=”0123456789”;
int a=strlen(str);
int b=sizeof(str);

这里的a计算的是以0x00结束的字符串的长度(不包括0x00结束符),这里的结果是10;

这里的b计算的则是分配的数组str[20]所占的内存空间的大小,不受里面的存储内容的改变而改变,这里的结果是20

           ③如果要计算指针指向的字符串的长度,则一定要用strlen,如

char *ss=”0123456789”;
int a=strlen(ss);  //ss指针所指向的字符串的长度,结果是10
int b=sizeof(ss);   //ss指针所占用的内存空间大小,结果是4

15问题: 关于 int a=10; int &rn=a;引用的简单性质?

回答:声明rn为a的一个引用,此时rn就是a的一个别名,对rn进行赋值其实就是对a进行赋值,rn的地址就是a的地址(引用不需要额外开辟内存单元)。注:①引用类型的变量在申明的同时必须初始化。②对于常量类型的变量,其引用也必须是常量类型的;对于非常量类型的变量,其引用可以是非常量的,也可以是常量的。但无论什么情况,都不能使用常量引用修改其引用的变量的值。

16问题: 引用和指针的区别?

回答:指针是指向一块内存地址的变量,这个变量可以指向其他地址;引用是一个变量的别名,只能是一个变量的别名。一个变量的引用可以转为指向它的指针。

1.初始化不同,引用使用时必须初始化,且只能指向一个变量,初始化不能指向其他变量;指针不一样,指针使用时不必初始化,可以指向nullptr,初始化后仍可以改变指向的地址。

2.作为函数参数传递时,引用不需要内存拷贝,所以也就不需要申请内存,因此当函数参数传递时,很多时候使用&或者const&传递参数节省内存。

3.作为函数参数传递时,如果想改变传递进函数参数的原始变量的值,引用改变后改变原始变量,而指针的值改变后并不会改变原始变量,因为它只是一份内存副本,如果想达到改变的效果,使用**。

4.引用的++ 是变量本身的运算,而指针的++,是内存地址的++。

5.如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏。

6.不要返回局部变量引用,返回对象的引用最好const变量。

7.操作符<< 和 >> =返回引用,而操作符+-/*的返回对象不能是引用。

17问题:为什么传引用比传指针安全?

回答:由于不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,因此引用很安全。

对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL,所以不安全。Const指针仍然存在空指针,并且有可能产生野指针。

18问题: 关于指针和数组

#include <iostream>
using namespace std;
int main(void){
char str1[ ] =”abc”;
char str2[ ] =”abc”;
const char str3[ ] =”abc”;
const char str4[ ] =”abc”;
const char * str5 =”abc”;
const char * str6 =”abc”;
char * str7 =”abc”;
char * str8 =”abc”;
cout<<(str1==str2)<<endl;        //返回0
cout<<(str3==str4)<<endl;        //返回0
cout<<(str5==str6)<<endl;        //返回1
cout<<(str6==str7)<<endl;        //返回1
cout<<(str7==str8)<<endl;        //返回1
return 0;
}

回答:数组str1、str2、str3和str4都是在栈中分配的。内存中的内容都为“abc”加一个/0,但是他们的位置不同,因此前两个输出的都是0;指针str5、str6、str7和str8也都是在栈中分配的,但他们都是指向”abc”字符串,其实是指向同一块数据区的内存。故后面的输出都为1.

19问题: 指针常量与常量指针的区别?

回答:常量指针,1.常量指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改;2.常量指针可以被赋值为变量的地址,之所以叫常量指针,是限制了通过这个指针修改变量的值;3.指针还可以指向别处,因为指针本身只是个变量,可以指向任意地址;

           指针常量,本质是一个常量,而用指针修饰它。指针常量的值是指针,这个值因为是常量,所以不能被赋值。1.它是个常量!2.指针所保存的地址可以改变,然而指针所指向的值却不可以改变;3.指针本身是常量,指向的地址不可以变化,但是指向的地址所对应的内容可以变化;

int const* p;   //即常量指针,const修饰的是*p,即*p的内容不可通过p改变,但p不是const,p可以修改,*p不可修改;

const int* p;   //即常量指针,同上

int* const p;   //即指针常量,const修饰的是p,p是指针,p指向的地址不能修改,p不能修改,但*p可以修改

20问题: 关于this指针的理解?

回答:当你进入一个房子后,你可以看见桌子、椅子、地板等,但是房子你是看不到全貌了。

对于一个类的实例来说,你可以看到它的成员函数、成员变量,但是实例本身呢?

this是一个指针,它时时刻刻指向你这个实例本身。

21问题:指针数组与数组指针的区别?

回答:数组指针int (*p)[n]; 指针数组定义 int *p[n];

指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身的大小决定,每一个元素都是一个指针,在32 位系统下任何类型的指针永远是占4 个字节。它是“储存指针的数组”的简称。

数组指针:首先它是一个指针,它指向一个数组。在32位系统下任何类型的指针永远是占4个字节,至于它指向的数组占多少字节,不知道,具体要看数组大小。它是“指向数组的指针”的简称。

22问题: 指针函数与函数指针?

回答:指针函数为返回指针类型的函数,函数指针是指向函数地址的指针。
         1、指针函数int *f(x,y),是指带指针的函数,即本质是一个函数,函数返回类型是某一类型的指针;函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。

float *fun();
float *p;
p = fun(a);

      2函数指针是指向函数的指针变量本质是一个指针变量。

int (*f) (int x); /*声明一个函数指针 */

f=func; /* 将func函数的首地址赋给指针f */

23问题: 数组指针和函数指针的定义?

回答:a.含有10个元素的指针数组---int *a[10];

b.数组指针--------int *a=new int[10];

c.函数指针--------void (*fn)(int, int);

d.指向的函数的指针数组----int (*fnArray[10])(int, int);

24问题:各种指针的定义--写出函数指针、函数返回指针、const指针、指向const的指针、指向constconst指针?

回答:

void(*f)(int, int), f是一个指向void max(int x, int y)类型的函数指针;
int *fn(), fn是返回int指针类型的函数;
const int *p , p是一个指向const的指针,指向一个常量;
int * const q,q是一个const指针
const int * const ptr, ptr是指向const的const指针;

25问题:什么是野指针?有什么危害?

回答:指向内存被释放的内存或者没有访问权限的内存的指针。

“野指针”的成因主要有2种:①指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针;②指针p被free或者delete之后,没有置为NULL。(指针用完后释放内存,将指针赋NULL。delete(p); p = NULL)

26问题:比较分析两个代码段的输出----动态内存的传递?

程序1:char *GetMemory()
{
char p[]=”hello word!”;
return p;
}
void Test(void){
char *str=NULL;
str=GetMemory();
printf(str);
}
程序2:char GetMemory(char *p)
{
P=(char*)malloc(100);
}
void Test(void){
char *str=NULL;
GetMemory(str);
strcpy(str,”hello word”)
printf(str);
}

回答:程序1的GetMemory()返回的是指向栈内存的指针,改指针的地址不是NULL,但是当栈退出后,内容不定,有可能会输出乱码。

        程序2的GetMemory()没有返回值,这个函数不能传递动态内存。在Test函数中,str变量的值通过参数传值的方式赋给GetMemory的局部变量p,但是TEST中的str一直为NULL,所以strcpy(str,”hello word”)会使程序崩溃,此外由于堆内存在GetMemory()执行后没有指针引用它,因此会产生内存泄漏。

27问题:编程判断字符串是否为回文?

回答:

#include <iostream>
using namespace std;
int IsRevStr(char *str)
{
    int i, len;
    int found = 1;
    
    int (str==NULL){
        return -1;
    }
    len=strlen(str);    
    for(i=0;i<len/2;i++)
    {
        if(*(str+i)!=*(str+len-i-1))
        {
            found=0;
            break;
        }
    }
    return found;
}

28问题:编写字符串反转函数strrev?

回答:直接进行元素交换

char strrev1(const char * str)
{
    int len=strlen(str);
    char* tmp=new char[len+1];
    
    strcpy(tmp,str);
    for(i=0;i<len/2;i++)
    {
        char c=tmp[i];
        tmp[i]=tmp[len-i-1];
        tmp[len-i-1]=c;
    }
    return tmp;
}
char* strrev2(const char* str)
{
    char* tmp=new char[strlen(str) +1]
    strcpy(tmp,str);
    char* ret=tmp;
    char* p=tmp+strlen(str)-1;
    while(p>tmp)
    {
        char t= *tmp;
        *tmp=*p;
        *P=T;

        --P;
        ++tmp
    }
    return ret;
}

29问题:编写实现两个数字字符串进行相加?

回答:

#include <stdio.h>
#include <stdlib.h>

char* mystrcat(char *dest, const char *src)
{
    char *ret;
    ret=dest;
    while(*dest++);
    dest--;
    while(*dest++=*src++);
    return ret;
}

30问题:关于位操作符<<与>>的使用?

回答:

#include <stdio.h>

int main(int argc, char* argv[])
{
    unsigned short int i=0;
    unsigned char ii=255;
    int j=8,p ,q ;

    p=j<<1;  //16  位左移相当于乘以2的n次方
    q=j>>1;  //4   右移相当于除以2的n次方
    i=i-1;   //65535 i大小为2个字节,大小范围为0-65535
    ii=ii+1; //0     ii的大小为1个字节,大小范围为0-255

return 0;
}