【C/C++笔记】:易错难点1

1.设有定义:char *p;,以下选项中不能正确将字符串赋值给字符型指针p的语句是( )

正确答案: A B D   你的答案: 空

A   p=getchar();                    

B   scanf(“%s”,p);                  

C   char s[ ]=”china”;p=s;        

D   *p=”china”;                      

A、类型不匹配, getchar() 函数返回值是int,只能赋值给int 或者char类型,此时p为char*类型  

B、 p指针在定义的时候没有分配内存, 所以这行代码在运行的时候会报野指针错误

C、指针p指向数组s

D、 *p代表p指向内存的内容, 这里要使用p="china"才正确

       字符串常量"china"出现在一个表达式中时,"china"表达式使用的值就是这些字符所存储的地址(在常量区),而不是这些字符本身。

所以,可以把字符串赋值给指向字符的指针p,而不能把字符串赋值给一个字符数组

2.下面哪些运算符不能被重载?

正确答案: A B D   你的答案: 空

A    做用域运算符“::”

B    对象成员运算符“.”

C    指针成员运算符“->”

D    三目运算符“? :”

C++ 里面 .  ,  .*  ,   ::  ,   ?:  , siezof 不能重载.

3、给出以下定义,下列哪些操作是合法的?

正确答案: A   你的答案: B

A   p1++;

B   p1[2] = ‘w’;

C   p2[2] = ‘l’;

D   p2++;

解析:

口诀:左定值,右定向。

即 const在*的左边不能改变字符串常量的值,故B错;

const在*的右边不能改变指针的指向,故D错;

由于 “world“存储在字符常量区,不能直接修改其值,故C错;

若要修改其值,应该改为char str []= "world";

4、下列说法哪个正确()

正确答案: C   

A   不需要定义类,就能创建对象

B   对象中必须有数据域和方法

C   数据域可以是基本类型变量,也可以是一个对象

D   数据域必须是基本类型变量

5、float 类型(即 IEEE754 单精度浮点数格式)能表示的最大整数是( )。

正确答案: D   

A   2^126-2^103        B   2^127-2^104       C   2^127-2^103              D   2^128-2^104

6、下面输出结果为:

正确答案:ink

#include<stdio.h>
int main()
{
static char *s[] = {"black", "white", "pink", "violet"};
char **ptr[] = {s+3, s+2, s+1, s}, ***p;
p = ptr;
++p;
printf("%s", **p+1);
return 0;

7、若有语句:int s[3][3],(*p)[3];p=s;则对s数组元素的引用形式正确的是____

正确答案:C

A、p + 1    B、*(p+1)   C、p[1][2]  D、*(p+1)+2

首先,在这个题目中我们应该明确的是:在二维数组中,二维数组的数组名是代表首元素的地址,而二维数组的首元素是二维数组第一行的内容

所以在p中存储的地址是s第一行一维数组的地址。(在看二维数组时,我们要将其当做一维数组来看)

其次,我们知道,数组名代表的是首元素的地址,我们访问数组中的元素一般用arr[1]的形式;但是从地址的角度来看:*(arr + 1)也能访问到数组中同样的元素;所以我们可以得到:arr[1] 就等价于*(arr + 1)。(实际上在原理上确实是这样的,比较复杂,有兴趣的可以去查一下)

知道了这些知识后,我们再来看C选项:p[1][2] 就可以写为 *(*(p + 1) + 2),即为访问第二行第三个元素。

(而B选项只是访问的二维数组第二行的元素;A和D选项不符合基本的格式)

8、有如下程序段,则对函数 fun 的调用语句正确的是【多选】( )

正确答案:C D

char fun(char *);
int main()
{
char *s = "one", a[5] = {0}, (*f1)(char *) = fun, ch;
return 0;
}

A: *f1(&a);             B: f1(*s);          C: f1(&ch);             D: ch = *f1(s);要改成(*f1)(s)才正确

解析:

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

指针函数的定义为: 类型名 函数名(参数表列); 例如: int a(int x, int y);

指针函数是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且在主调函数中,函数返回值必须赋给同类型的指针变量。

函数指针: 是指向函数的指针变量,即本质是一个指针变量。

函数指针的定义为: 函数类型 (变量名)(函数形参表);例如:int (p)(int, int);

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

 

通过指针调用函数的两种形式:

1、ret = (*p)();

2、ret = p();

函数指针赋值的两种形式:

1、pf = &func;

2、pf = func;

A应改为:(*f1)(a)或f1(a)

B应改为:(*f1)(s)或f1(s)

CD,f1为函数指针

D、要正常使用f1应该使用(*f1)(s),与f1(s)效果相同。

*f1(s)中()的优先级比*高,()先与f1(s)结合,返回结果是char,*f1(s)是对返回结果

验证:

char s_char = 'a';

char* fun(char *){

    return &s_char;

};

int main()

{

    char *s = "one", a[5] = { 0 }, *(*f1)(char *) = fun, ch;

    ch = *f1(s);

    cout << ch;

    return 0;

}

//输出 a

9、下列程序的输出是()

正确答案:D

#include <stdio.h>
int main(void) {
    int a[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, *p[4], i;
    for (i = 0; i < 4; i++) p[i] = &a[i * 3];
    printf("%d\n", p[3][2]);
    return 0;
}

A: 上述程序有错误             B: 6        C: 8           D: 12

解析:

int *p[4]: p 是指针数组, 数组内包含 4 个元素, 每个元素都是 int* 类型.

p[3] = &a[9], 即第 3 个元素是指向 a[9] 的

p[3][2] = p[3]+2, p[3] 是 int* 类型, 偏移 2 个单位后指向 a[11]

9、下列程序的输出是()

正确答案:abddcccd

char* f(char *str, char ch) {
    char *it1 = str;
    char *it2 = str;
    while (*it2 != '\0') {
        while (*it2 == ch) { it2++; }
        *it1++ = *it2++;
     }
    return str;
}
void main(int argc, char *argv[]) {
    char *a = new char[10];
    strcpy(a, "abcdcccd");
    cout << f(a, 'c');
}

分析:看下面这段代码:

 while(*it2 != '\0')

 {

        while(*it2 == ch) { it2++; }

        *it1++ = *it2++;

 }

     it1的前两个字符为ab没有异议,当it2的指针指向c时执行  it2++运行后it2指向d,然后其不为c,所以it1的指针内复制为d,即此时it1为abd,

之后遇到3个c,执行 it2++,直到it2指向d时才将d赋值给it1,也就是此时it1=abdd,但是接下来it2已经为空了,也就是“\0”,所以就不执行循环了,但是it1内本身后面还有cccd,前面的四个字母只是it2覆盖成abdd

所以最终的答案是abddcccd

10、关于char*f和c_str的使用

char* func()
{
	string s = "1234";
	return s.c_str();
}

const char* c_str();
c_str()函数返回一个指向正规C字符串的指针常量, 内容与本string串相同.
这是为了与c语言兼容,在c语言中没有string类型,故必须通过string类对象的成员函数

c_str()把string 对象转换成c中的字符串样式。
注意:一定要使用strcpy()函数 等来操作方法c_str()返回的指针

比如:最好不要这样:
char* c;
string s="1234";
c = s.c_str(); //c最后指向的内容是垃圾,因为s对象被析构,其内容被处理,同时,编译器也将报错——将一个const char *赋与一个char *。

正确使用:
char c[20];
string s="1234";
strcpy(c,s.c_str());
这样才不会出错,c_str()返回的是一个临时指针,不能对其进行操作

再举个例子
c_str() 以 char* 形式传回 string 内含字符串
如果一个函数要求char*参数,可以使用c_str()方法:
string s = "Hello World!";
printf("%s", s.c_str());
//输出 "Hello World!"

10、下面正确的是:

正确答案:A

union d
{ int d1; float d2; }d;

A. 变量d与各成员的地址相同                            B. d.d1和d.d2具有相同的地址

C. 若给d.d2赋10后,d.d1中的值是10                 D. 若给d.d1赋10后,d.d2中的值是10


解析:这题思路应该是:共用体中只能存在一个值,如果给某个值赋值后,另一个值就不存在;共用一个地址;

11、以下有关C语言的说法中,错误的是( )

正确答案:D

     A: 内存泄露一般是指程序申请了一块内存,使用完后,没有及时将这块内存释放,从而导致程序占用大量内存,但又不使用不释放
    B: 可以通过malloc(size_t)函数调用申请超过该机器物理内存大小的内存块
    C: 无法通过内存释放函数free(void*)直接将某块已经使用完的内存直接还给操作系统,free函数只是将动态申请内存的使用权释放
    D: 可以通过内存分配函数malloc(size_t)直接申请物理内存

答案解析:
free释放的内存不一定直接还给操作系统,可能要到进程结束才释放。malloc不能直接申请物理内存,它申请的是虚拟内存

12、下面输出结果为:

正确结果: D

char a=101;
int sum=200;
a+=27;sum+=a;
printf("%d\n",sum);

A: 327    B: 99    C: 328    D: 72

char为有符号类型,占1个字节,也就是8位,其中最高位是符号位,取值范围为-128~127;a=101+27=128,128表示为1000 0000,作为补码放在内存中,符号位为1,在与int类型的sum进行加计算时会整型提升,高位补1,再转成原码为-128,sum=200+(-128)=72

13、假设C语言程序里使用 malloc 申请了内存,但是没有 free 掉,那么当该进程被kill之后,操作系统会( )

正确答案:D

A: 内存泄露 B: segmentation fault C: core dump D: 以上都不对

不管用户程序怎么用malloc,在进程结束的时候,用户程序开辟的内存空间都将会被回收

14、下面输出结果为

正确答案:A

#include <stdio.h>
#define a 10
void foo();
int main()
{
    printf("%d..", a);
    foo();
    printf("%d", a);
    return 0;
} 
void foo()
{
#undef a
#define a 50
}

A: 10..10   B: 10..50    C: Error    D: 0

define在预处理阶段就把main中的a全部替换为10了。另外,不管是在某个函数内,还是在函数外,define都是从定义开始直到文件结尾,所以如果把foo函数的定义放到main上面的话,则结果会是50…50

15、下面输出结果为

正确答案: B

#include <stdio.h>
typedef struct List_t
{
    struct List_t* next;
    struct List_t* prev;
    char data[0];
}list_t;
int main()
{
    printf("%d",sizeof(list_t));
    return 0;
}

A: 4byte    B: 8byte    C: 5byte    D: 9byte

解析:

题目中的char data[0]或写成char data[],即为柔性数组成员;在计算机结构体大小的时候data不占用struct的空间,只是作为一个符号地址存在。因此sizeof的值是两个指针所占字节,即4+4=8字节(默认是在32位下)

16、假设函数原型和变量说明如下,则调用合法的是( )

正确答案:C

void f(int **p);
int a[4]={1,2,3,4};
int b[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int *q[3]={b[0],b[1],b[2]};

A: f(a);    B: f(b);    C: f(q);    D: f(&a);

解析:

A选项,f(a)传参时,a会退化成指向其首元素的地址,类型是 int*,不符。

B选项,b是二维数组,传参时会退化成指向其首元素的指针,也就是b[0]的地址,b[0]的类型是int [4],故&b[0]类型是int()[4],不符。

D选项,&a是数组a的地址,其类型是int()[4],不符。

C选项,q是一个指针数组,在初始化时用b[0]、b[1]、b[2], 此时b[0]、b[1]、b[2]会退化成指向各首元素的指针(int* 类型,因此类型符合,可以用它们初始化)。q传参时,退化成指向其首元素的指针,即 int**

17、关于to_string用法:

void test()
{
    int cnt;
    cin >> cnt;
    cout << cnt + '0' << " " << to_string(cnt) << endl;
    string s1;
    s1+=cnt + '0';

    string s2;
    s2 += to_string(cnt);
    cout << s1 << " " << s2 << endl;

}

当我们输入2的时候

输入10的时候

易知to_string比+'0'更加好,尤其是转化不是单位的数字为字符时

18、下列程序会输出什么()

正确答案:14

#include<stdio.h>
#define Mul(x,y) ++x*++y
int main()
{
    int a = 1;
    int b = 2;
    int c = 3;
    printf(“%d”,Mul(a+b,b+c));
    return 0;
}

解析:

        Mul(a+b,b+c)经过宏替换变成++a+b*++b+c,需要注意宏替换的原则,是不会凭空加括号的。另外++优先级大于*,因此会先++a 和++b,然后a=2,b=3进行a+b*b+c=2+3*3+3=14

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值