C++笔试题合集-第一阶段

news2024/10/7 1:47:52

2024年9月25日23:46:07 今天你努力了吗?
一、解释代码
char * const * (*next)();
(*next) next是一个指针
const 和指针之间的关系(指向常量的指针,以及指针常量)
(*next)() next是一个函数指针
char * const  是一个指针 ,常量指针
char * const *(*next)() 
next 是一个函数指针,只想一个没有参数的函数,并且该函数的返回值是一个指针,该指针指向一个类型为char的常量指针。

二、函数指针数组
解释char *(*c[10])(int **p)
char *pt[10]; pt 是数组,数组是由10个char * 指针所组成;
char (*pt)[10];pt 是指针,指向一个由20个char元素组成的数组;
c[10] c是数组,
*c[10] c 是一个指针数组
char * (*c[10])(int **p)c数组中每一个元素都是函数指针,其指向的函数的返回值为char * ,参数为一个指向指针的指针;

三、字符串常量
char *s= "AAA";
printf("%s",s);
s[0]='B';
//s = 'B';
printf("%s",s);
1.字符串常量 "AAA" 实际上是一个 const char * 类型的指针。这意味着它指向的内存是只读的,不应该被修改。
2.当你执行 s[0] = 'B'; 时,编译器通常会发出警告,提示你不应该修改字符串常量。在某些编译器中,这可能会导致编译错误。

四、访问指定内存地址
嵌入式系统经常具有要求程序员去访问某特定的内存位置,要求读取地址的里面的内容或者想该地址写入新值,特别是在嵌入式处理器开发中操作寄存器时这种用法会经常出现。例如在某工程中,要求设置一绝对内存地址为0x40040800的位置,将改地址里面的内容设置为整型值0x3456。编写代码完成这一任务。
方法一:
int * pt;
pt = (unsigned long *)0x40020800;
*pt = 0x3456;
方法二:
#define ADDR (*(volatile unsigned long *)0x40020800)
ADDR = 0x3456;

五、#define对比typedef
typeddef在C语言中频繁用以生命一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;
以上两种情况的意图都是要定义dPS 和 tPS作为一个指向结构s指针。那种方法更好呢?
dPS p1;----------------->struct s * p1;
tPS p2;
dPS p1,p2;------------------>struct s *p1, p2;
p1是结构体指针,p2是结构体s的对象。
tPS p3,p4;------------------>p3,p4都是结构体指针。
所以,typedef优于#define

2024年9月26日22:20:40 今天你努力了吗?
六、函数返回局部变量地址的问题
下面代码是否有问题,如果有问题,那么那么编译运行后的结果是什么,并说明问题的原因,并修改。
#include <stdio.h>
char * get_str();
int main(void){
    char * p = get_str();
    printf("%s\n",p);
    return 0;
}
char * get_str(void){
    char str[]= {"abcd"};
    return str;
}
在 get_str() 函数中返回了一个指向局部变量 str 的指针。这意味着当 get_str() 函数执行完毕后,str 所占用的栈内存会被回收,之后对这个指针的使用将是未定义的行为,可能导致程序崩溃或产生垃圾数据。
方法一:动态分配内存
char * str = malloc(5 * sizeof(char));(包括'\0')
方法二:传递参数

七、无符号整数和有符号整数的相加
下面所示的代码运行的结果是什么?
#include <stdio.h>
int main(void){
    unsigned int a = 6;
    int b = -20;
    (a+b > 6) ? puts(" >6 ") : puts(" <= 6");
    return 0;
}
运行结果为>6。也就是说条件表达式被判断为真。
问题:自动类型转换。a+b会自动转换。b转换为无符号类型b。
数字在电脑中是以补码的形式存储的。
当你把一个有符号整数(int b)和一个无符号整数(unsigned int a)进行加法操作时,编译器会将较小的类型转换为较大的类型。在这个例子中,b 会被转换成 unsigned int 类型,这意味着 -20 会被解释为其对应的无符号整数值。
当 -20 被转换为 unsigned int 时,它实际上变成了一个非常大的正数。这是因为无符号整数的表示范围是从 0 到 UINT_MAX,而负数的二进制补码形式在转换到无符号整数时不会改变。对于 int 类型,如果 -20 的补码形式转换到 unsigned int,结果将是 UINT_MAX - 20 + 1(假设 int 和 unsigned int 的位宽相同)。
因此,(a + b) 实际上是一个很大的数(因为 -20 转换成了一个大的正值),再加上 6 后肯定大于 6。所以,表达式 (a + b > 6) 总是为真。

八、大小端模式以及代码判别
什么是大端模式,什么是小端模式,编写并测试。
大端模式:数据高位,存储在低地址中
小端模式:数据高位,存放在高地址中
#include <stdio.h>
int main(void){
    union test {
        unsigned int n;
        char arr[4];
    };
    union test t;
    t.n = 0x12345678;
    cout << "arr[0]"<< t.arr[0] << endl;    
    cout << "arr[1]"<< t.arr[1] << endl;    
    cout << "arr[2]"<< t.arr[2] << endl;    
    cout << "arr[3]"<< t.arr[3] << endl;    
    return 0;
}

九、显示无符号int类型的最大值和最小值
评价下面代码:
unsigned int zero = 0;
unsigned int compzero = 0xffff;
该代码默认当前系统为16位。是错误的。
unsigned int min = 0;
unsigned int max = ~0;

十、逻辑与运算符,按位与运算符
考虑下面代码,其作用是在数组中查找一个特定的元素:
i = 0;
while(i < arrsize && arr[i] != x)
    i++;
假如无意中,我们用位操作运算符&代替了上面的逻辑运算符&&,如下所示:
i = 0;
while(i < arrsize & arr[i] != x)
    i++;
则当前的语句是否还能实现上面的元素查找功能?
可以实现。
原因:
逻辑运算符两侧的运算结果都是真或假。并且数组越界后的内容是可读的。

2024年9月29日00:52:55 今天你努力了吗?
十一、printf的返回值
下面这个程序的输出结果是什么?
#include <stdio.h>
int main()
{
    int i = 43;
    printf("%d\n",printf("%d",printf("%d",i)));
    return 0;
}
输出结果:4321
原因:printf的返回值是输出打印的字符的个数。

十二、#运算符 利用宏参数创建字符串
举例说明,通过#运算符,利用宏参数创建字符串。
#include <stdio.h>
#define SQUARE(X) (printf(""#x" square is : %d\n",(x) * (x)))
int main()
{
    SQUARE(2+4);
    return 0;
}

十三、##运算符,预处理符号粘合剂
#include <stdio.h>
#define XNAME(n)  x##n
int main()
{
    int XNAME(1) = 10;
    printf("%d\n",x1);
    return 0;
}


十四、结构体中用字符数组还是字符指针
阅读下面代码,看这段代码是否有问题,如果有问题请指出问题。
#include <stdio.h>
#include <string.h>
struct std
{
    unsigned int id;
    char * name;
    unsigned int age;
}per;
int main()
{
    per.id = 0001;
    strcpy(per.name,"Micheal Jackson");
    per.age = 20;
    printf("%s\n",per.name);
    return 0;
}
问题:结构体 std 中的成员 name 是一个指向 char 类型的指针。在使用前需要正确分配内存,否则会导致未定义行为(Undefined Behavior)。
可以这样修改char name[50]; // 使用固定大小的数组来存储名字

十五、内存越界
阅读下面代码、看这段代码是否有问题,如果有请指出问题
char * p1 = "ABCABC";
char * p2 = (char *)malloc(strlen(p1));
strcpy(p2,p1);
分配给 p2 的内存没有被释放。虽然在这个简短的示例中,内存泄漏可能不会立即引起问题,但在较大的程序中,累积的内存泄漏可能会导致性能下降或其他问题。
strlen:不包含“\0”
strcpy:拷贝时,包含\0;
如果要打p2所指向的内容时,可能会造成错误。

十六、free和delete怎样处理指针。
C和C++中,free()和delete是如何操作指向动态开辟内存的指针的?
free释放指针指向的内存空间,指针本身还在。
delete也是一样。

十七、字符数组和字符指针定义字符串的区别。
字符数组是一种静态的数据结构,它在声明时就确定了大小,并且在声明时分配内存。一旦分配,就不能改变大小。字符数组非常适合用于存储已知长度的字符串。
字符指针是一个指向字符的指针,它可以指向一个字符数组、一个动态分配的字符串或者一个字符串常量。

十八、编程算法之哨兵思想
哨兵算法是一种常用的编程技术,主要用于简化循环中的边界条件处理。它通过引入一个特殊的“哨兵”元素来避免复杂的边界条件检查,从而简化代码并提高效率。

十九、一条Linux源码分析
在Linux内核代码中有如下定义:
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
请解释这条语句的含义
(TYPE *)0这部分创建了一个指向类型 TYPE 的指针,并将其设置为 0(即空指针)。
(TYPE *)0->MEMBER使用指针成员运算符 -> 访问 TYPE 类型结构体的成员 MEMBER。
&(TYPE *)0->MEMBER去春member成员的地址
(size_t) &(TYPE *)0->MEMBER最终,取地址运算符的结果被转换为 size_t 类型,得到一个表示偏移量的无符号整数。
size_t = int
总结,该宏的作用就是求出MEMBER成员变量在TYPE中的偏移量。

二十、查看如下代码,写出程序运行的结果:
#include <stdio.h>
#define offsetof(TYPE , MEMBER) (size_t) & ((TYPE *)0)->MEMBER)
typedef struct s{
     union{
         int a;
         char str[10];
     };
     struct s* next;
}S;
int main(){
    printf("%d\n",offsetof(S,next));
    return 0;
}
运行结果:10(受操作系统位数影响),也就是union所占的大小。

二一、const指针与指向const的指针
#include <stdio.h>
int main()
{
    const int i = 10;
    char arr[i] = {1,2,3,4,5,6,7,8,9,10};
    printf("i = %d\n",i);
    return 0;
}
const 修饰的变量本质上还是一个变量,并不是一个真正的常量。

二二、fork函数
下面这段代码int main(){fork()||fork();}共创建几个进程?
三个进程,父进程,子进程和孙子进程

二三、按指针——引用——值传递参数
下面这段代码的输出结果为:
#include <stdio.h>
void change(int *a, int &b ,int c )
{
    c = *a;
    b = 30;
    *a = 20;
}
int main()
{
    int a = 10,b = 20,c = 30;
    change(&a,b,c);
    return 0;
}
20 30 30

二四、调用几次构造函数?
若MyClass 为一个类,执行"MyClass a[4], *p[5];语句时会自动调用该类构造函数的次数是?
4次

二五、统计二进制中1的个数
求下面函数的返回值
int func(int x)
{
    int countx = 0;
    while(x)
    {
        coutx++;
        x = x&(x-1);
    }
    return countx;
}
x&(x-1)
x-1:将二进制数从右往左数,遇到的第一个1变成0,右边的所有0变成1,左边的所有数保持不报。
x&(x-1) 从右往左数,遇到的第一个1变成0,左边的数不变,右边的数全部为0;

二六、判断一个数是不是2的n次方
编写代码,判断一个数是不是2的n次方
#define ISPOWER_OF_TWO ((x&(x-1))== 0)

二七、double&operator[](int i)和double operator[](int i) const的区别
有一个名为Student的类,该类中有两个[]运算符重载函数的声明,如下所示:
double & operator[](int i);
double operator[](int i) const;
这两个运算符重载函数的定义如下所示:
double &Student::operator[](int i)
{
    return scores[i];
}
double Student::operator[](int i) const
{
    return scores[i];
}

二八、自定义字符串拷贝函数
仿照字符串库函数strcpy,自己编写一个字符串拷贝函数,不允许使用C库函数,要求两个参数,第一个参数是要拷贝的目的地址,第二个参数是拷贝字符串的来源。
char * mystrcpy(char * dest,const char * src){
    if(dest == nullptr || src == nullptr)
        return nullptr;
    if(dest == src)
        return dest;
    while(*dest++ = * src++);
}
char * mystrcpy(char * dest,const char * src){
    char * pt = dest;
    int delta = dest - src;

    if(dest == nullptr || src == nullptr)
        return nullptr;
    if(dest == src)
        return dest;
    while(*(src + delta) = *src++);
}

二九、变量置位和清零操作
给定一个整形变量a,写两端代码,第一个设置a的bit3,第二个清除a的bit3。
a = a | (1<<3)
a = a & ~(1<<3)

三十、sizeof运算符中的表达式
请说明下面代码的运算结果:
#include <stdio.h>
int main()
{
    int i;
    i = 10;
    printf("%d\n",i);
    printf("%ld\n",sizeof(i++));
    printf("%d\n",i);
    return 0;
}
10
4
10
原因:sizeof不是函数,是运算符!sizeof(i++),不会计算i++,而是直接运算sizeof(int);

三一、指针+整数
请说明下面代码的运行结果:
unsigned char *p1;
unsigned long *p2;
p1 = (unsigned char *)0x801000;
p2 = (unsigned long *)0x801000;
请问
p1 + 5 = ?
p2 + 5 = ?
指针+1 :地址+sizeof(指向数据的类型)

三二、volatile关键字
下面的函数有什么错误:
int square(volatile int *pt){
    return (*pt) * (*pt);
}
防止编译器进行优化,确保每次获取都是最新的值,则保留 volatile 是正确的做法。

三三、C++中空类占用内存的大小
定义一个空的类,里面没有任何成员变量和成员函数,对该类求sizeof,得到的结果是多少?
结果:1.编译器给空类分配了一个隐藏的字节。

三四、如果a是个数组,则a和&a之间的区别。
指出下面代码的输出,并解释为什么。
#include <stdio.h>
int main()
{
    int a[5] = {1,2,3,4,5};
    int *pt = (int *)(&a + 1 );
    printf("%d,%d\n",*(a+1),*(pt -1));
    return 0;
}
a:数组名,表示数组中第一个元素的地址
&a:整个数组在内存中的起始地址
a+1 != &a+1
输出结果:2 5

三五、不使用第三个变量的情况下交换两个变量的值
a,b;
方法一:
a = a+b;
b = a-b;
a = a-b;

三六、运算符优先级
下面程序输出结果是什么?
#include <iostream>
using namespace std;
void max_out(int val1,int val2);
int main()
{
    int i = 10,j = 20;
    cout << "The larger of " << i << "and" << j << "is";
    max_out(i,j);
    cout << endl;
    return 0;
}
void max_out(int val1,int val2)
{
    cout << (val1 >val2)? val1:val2;
}
输出结果:0;
原因(val1 > val2)判断结果为假,0;
然后被cout输出。

三七、那种指针类型占用的内存空间大?
字符指针,浮点数指针,以及函数指针这三种类型的变量,哪个占用的内存最大,为什么?
答:大小是一样大的。

三八、交换8位整数的高4位和低4位
编写一个C函数将一个8为的整数高4位和低4位互换。例如,输入0X2C则将其改为0XC2;
void convert(unsigned int *pt)
{
    unsigned int temp = *pt &0x0f;//低四位
    *pt &= oxf0;//高四位
    *pt = (temp << 4) | (*pt >>4);
}

三九、又一道和大小端模式有关的代码
阅读如下代码后,以下说法正确的是:
#include <stdio.h>
int main()
{
    char aChar;
    int aInt;
    aInt = aChar = -120;
    printf("%d\n",aInt);
    return 0;
}
结果:可能输出-120,因为不知道是大端模式还是小端模式。

四十、一级指针和二级指针
假如有如下定义:
char *str[4] = {"ABCD","EFGH","IJKL","MNOP"};
如何定义一个指针指向str?
一级指针:int *pt;
pt指针指向的地址里面存放的是int类型的数据
二级指针:int **pt;
pt指针指向的地址里面存放的是一个指向整形变量的地址。
char **pt = str;

char *pt[] = char **pt;

2024年9月30日22:36:41 今天你努力了吗?
四一、数组X复制n个字节到数组y的最简单方式
如果从数组x复制50个字节到数组y,最简单的方式是什么?
memcpy(y,x,50);

四二、将数字字符串转换为整数
为下面这个函数原型编写函数定义:
int ascii_to_integer(char *string);
这个字符串必须包含一个或多个数字,函数应该把这些数字字符转换为整数并返回这个整数,如何字符串参数包含了任何非数字字符,函数就返回0;
{
    int value = 0;
    while(*string >= '0' && *string <= '9'){
        value *= 10;
        value += *string - '0';
        string++;
    }
    if(*string != '\0')
        return 0;
}

四三、百钱买百鸡
公鸡一只5钱,母鸡一只3钱,小鸡三只1钱。一共花了100钱,问公鸡,母鸡,小鸡各多少只?
#include <stdio.h>
int main(void)
{
    int x,y,z;
    int t;
    for(t = 0;t<4;t++){
        x = 4*t;
        y = 25-7*t;
        z = 75+3*t;
        printf("cock = %d,hen = %d, chicken = %d\n",x,y,z);
    }
    return 0;
}

四四、指针取值和自增加运算符
如何理解下述表达式的含义?
*pt++,*++pt,(*pt)++,*(pt++)
整型数组 int arr[5] = {1, 2, 3, 4, 5}; 并且有一个指向数组第一个元素的指针 int *pt = &arr[0];。
*pt++
这个表达式意味着先解引用指针 pt,然后 pt 自身递增。这意味着 pt 指向的地址将会改变。
*++pt
这个表达式意味着先递增 pt,然后解引用新的 pt。
(*pt)++
这个表达式意味着先解引用 pt,然后递增解引用后的值。
*(pt++)
这个表达式等同于 *pt++,意味着先解引用 pt,然后 pt 自身递增。

四五、typede定义函数指针类型
请问如下语句是什么意思
typedef int (*funcptr)();
funcptr 函数指针类型。
typedef 关键字用于定义一个新的类型名,给已存在的数据类型起一个别名。
int (*funcptr)(); 定义了一个名为 funcptr 的类型,这个类型是指向一个返回 int 类型值的函数的指针,而且这个函数不接受任何参数。

四六、C和C++中const关键字的区别
为什么不能在初始化和数组维度中使用const值?例如:const int n = 5;
int a[n];
数组的大小必须是一个常量表达式(constant expression)。这意味着数组的尺寸必须在编译时就能确定其值。由于 const 变量在运行时才能被初始化,所以它不是常量表达式的一部分。因此,在旧版的C++中,代码是非法的.

四七、浮点数四舍五入取整
如何对一个浮点数,进行四舍五入的方式取整?
int(x+0.5);

四八、字符数组和字符指针的区别
下面这段程序的输出结果是?
char str1[]= "abc";
char str2[] = "abc";
const char str3[] = "abc";
cosnt char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout << (str1 == str2) <<endl;
cout << (str3 == str4) <<endl;
cout << (str5 == str6) <<endl;
cout << (str7 == str8) <<endl;
输出:
0
0
1
1

四九、类中共有成员函数是否一定要通过类的对象调用
否,例如构造函数可以直接调用
对于静态成员函数来说,情况有所不同。静态成员函数不属于任何一个特定的对象实例,而是属于整个类。静态成员函数不能访问类的非静态成员变量或非静态成员函数,因为它没有 this 指针。静态成员函数可以被类名直接调用,而不需要创建类的对象实例。

五十、一道函数指针题
一个函数如下所示,简单分析下这个函数并指出这个函数的功能。
void call_each(void(**a)(void),int size)
{
    int n = size;
    while(--n >= 0){
        void(*p)(void) = *a++;
        if(p)
            (*p)();
    }
}
void(**a)(void) 是一个指向函数指针数组的指针。数组中的每个元素都是一个指向不带参数的 void 类型返回值的函数的指针。
int size 是一个整型参数,表示函数指针数组的大小,即有多少个函数指针需要被调用。
void(*p)(void) = *a++;:从指针 a 指向的位置取出一个函数指针赋值给 p,然后将 a 指向下一个元素。
if (p):检查 p 是否为非空指针。如果 p 不是 nullptr(即有效的函数指针),则执行下一步。
(*p)();:调用由 p 指向的函数。

总的来说,这个函数提供了一种机制来依次执行一组预先准备好的函数,适用于需要按顺序执行一系列操作的情况。

五一、入栈出栈的顺序
在一个栈的输入顺序为12345,下面南哥不可能是栈的输出顺序?
54132

五二、C++临时变量
假如有如下C++函数:
void bar(string &s);
为什么下面的调用是错误的?
bar("Hello World");
在C++中,函数bar(string &s);声明了一个引用类型的参数s,这意味着函数期望一个字符串变量的引用。当你尝试使用bar("Hello World");来调用这个函数时,实际上是传递了一个字符串字面值(即常量字符数组)给函数。

字符串字面值(如 "Hello World")在C++中会被转换为const char*类型,也就是指向字符数组的常量指针。然而,当你试图将其作为引用类型参数传递给函数时,编译器不允许将常量地址赋值给非常量引用。也就是说,你不能创建一个非常量引用并初始化它为常量或非常量对象的临时实例。

因此,编译器会报错,因为你在尝试将一个不可修改的字符串字面值绑定到一个可以修改的对象的引用上。

五三、任意进制的整数转换为十进制
编写一段代码,将任意一个n进制整数X转换为十进制。
#include <iostream>
#include <string>
#include <cmath>

// 函数原型声明
int n_base_to_decimal(const std::string& num, int base);

int main() {
    std::string num;
    int base;

    std::cout << "请输入n进制数: ";
    std::cin >> num;

    std::cout << "请输入基数(2-" << (int)'Z' - (int)'A' + 10 << "): ";
    std::cin >> base;

    if (base < 2 || base > 36) {
        std::cout << "基数必须在2到36之间。" << std::endl;
        return 1;
    }

    int decimalNum = n_base_to_decimal(num, base);
    std::cout << "转换后的十进制数为: " << decimalNum << std::endl;

    return 0;
}

// 将n进制数转换为十进制数
int n_base_to_decimal(const std::string& num, int base) {
    int decimalValue = 0;
    int power = 0; // 用于计算当前位的权重

    for (auto it = num.rbegin(); it != num.rend(); ++it) { // 从最低有效位开始
        int digit = isdigit(*it) ? *it - '0' : toupper(*it) - 'A' + 10;
        if (digit >= base) {
            throw std::invalid_argument("输入的数字包含不属于指定基数的数字!");
        }
        decimalValue += digit * static_cast<int>(pow(base, power));
        ++power;
    }

    return decimalValue;
}

五四、一道Lambda函数
编写一个lambda,捕获它所在的函数的int,并接受一个int参数,lambda应该返回捕获的int和int参数的和。
int a =10;
auto sum = [&](int b){cout << a+b<<endl;};
sum(20);

五五、结构体内存对齐
struct Example {
    char a;      // 1 byte
    int b;       // 4 bytes, aligned to 4 bytes
    double c;    // 8 bytes, aligned to 8 bytes
};a之后会有3个字节的填充(padding),以确保b的起始地址是4的倍数;而b之后也会有4个字节的填充,以确保c的起始地址是8的倍数。这些填充不会被使用,但它们的存在是为了满足对齐要求。

五六、结构体内存对齐
想要控制结构体的对齐方式,可以使用pragma指令来设置全局的对齐策略。
#pragma pack(push)
#pragma pack(1) // 设置对齐为1字节

struct PackedExample {
    char a;      // 无填充
    int b;       // 无填充
    double c;    // 无填充
};

#pragma pack(pop) // 恢复之前的对齐设置

五七、向前声明和不完全类型
在C++中,当一个类或结构体的完整定义不在当前作用域内可用时,我们可以通过“前向声明”来告诉编译器该类型的存在。前向声明仅提供类型名称的信息,而不包含任何成员信息,这被称为“不完全类型”。
前向声明主要用于避免头文件之间的相互依赖导致的循环包含问题,也可以用来节省编译时间,因为完整的类型定义可能相当庞大。

五八、初始化vector对象的六种方法
#include <vector>
#include <iostream>
#include <array>

int main() {
    // 1. 默认构造函数初始化
    std::vector<int> vec1; // 默认构造函数创建空vector
    
    // 2. 初始化列表构造函数
    std::vector<int> vec2 = {1, 2, 3}; // 使用初始化列表
    
    // 3. 构造函数和迭代器
    std::array<int, 3> arr = {1, 2, 3};
    std::vector<int> vec3(arr.begin(), arr.end()); // 使用迭代器范围
    
    // 4. 通过赋值操作符或成员函数
    std::vector<int> vec4;
    vec4 = {1, 2, 3}; // 使用赋值操作符
    
    std::vector<int> vec5;
    vec5.assign({1, 2, 3}.begin(), {1, 2, 3}.end()); // 使用成员函数assign()
    
    // 5. 使用std::initializer_list构造函数
    std::vector<int> vec6({1, 2, 3}); // 使用std::initializer_list
    
    // 6. 使用reserve和emplace_back
    std::vector<int> vec7;
    vec7.reserve(3); // 预留3个元素的空间
    vec7.emplace_back(1);
    vec7.emplace_back(2);
    vec7.emplace_back(3);
    return 0;
}

五九、递归显示vector对象
#include <iostream>
#include <vector>

// 递归函数,用于显示vector中的元素
void displayVectorRecursively(const std::vector<int>& vec, size_t index = 0) {
    // 基本情况:当索引等于vector的大小时,停止递归
    if (index == vec.size()) {
        return;
    }
    
    // 显示当前索引处的元素
    std::cout << vec[index] << " ";
    
    // 递归调用,处理下一个元素
    displayVectorRecursively(vec, index + 1);
}

int main() {
    // 创建一个vector并填充一些数据
    std::vector<int> vec = {1, 2, 3, 4, 5};
    
    // 调用递归函数来显示vector的内容
    displayVectorRecursively(vec);
    
    // 换行
    std::cout << std::endl;
    
    return 0;
}

六十、内存分配
查看下面代码,是否有问题?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void GetMemory(char*p);
int main(void)
{
    char *str = NULL;
    GetMemory(str);
    strcpy(str,"hello world");
    printf("%s\n",str);
}
在main函数中,char *str = NULL;声明了一个指向char的指针,并将其初始化为NULL。
然后调用GetMemory(str);,理论上应该在这个函数中为str分配内存。然而,GetMemory函数的具体实现未给出,我们无法确定它是否正确分配了内存。
如果GetMemory没有为str分配内存,那么strcpy(str, "hello world");这一行就会尝试将字符串复制到一个未分配的内存区域,这会导致未定义行为(Undefined Behavior),可能包括程序崩溃。

六一、指针的引用
void GetMemory(char * &p);
int main(void)
{
    char * str = NULL;
    GetMemory(str);
    strcpy(str,"hello world");
    cout << str << endl;
}
void GetMemory(char * & p)
{
    p = (char *)malloc(100);
}

六二、如何在类声明中定义常量
//1
enum{size = 10};
//2
static const int size = 10;
//3
publlic:
构造函数(const int size = 10){};

六三、(int &)a的输出结果
float a = 10;
cout <<(int &) a << endl;
浮点数在内存中是如何存储的,将存储的数用用整数来表示出来。

六四、假定A是一个类,执行语句A a,b(3),*pt;
将调用几次构造函数?
2次。

六五、编写左值函数,功能任意,并用完整的代码测试这个左值函数。
左值(lvalue)指的是可以出现在赋值语句左侧的值,例如变量。左值函数通常是指函数返回一个左值引用,这样可以返回一个可修改的对象。
#include <iostream>

// 左值函数:交换两个整数变量的值
void swapValues(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 10;
    int y = 20;

    std::cout << "Before swapping: x = " << x << ", y = " << y << std::endl;

    // 调用左值函数
    swapValues(x, y);

    std::cout << "After swapping: x = " << x << ", y = " << y << std::endl;

    return 0;
}

六六、cout输出字符型指针
下面代码运行结果是什么?
const char * ptr = "hello world";
cout << ptr << endl;
std::cout << ptr << std::endl; 这一行将通过 std::cout 输出指针 ptr 指向的字符串内容。
std::endl 用于输出一个换行符,并刷新输出流。

六七、野指针引发的错误
下面这段代码有什么错误?
swap(int * p1,int *p2)
{
    int *p;
    *p = *p1;
    *p1 = *p2;
    *p2 = *p;
}
void swap(int * p1, int * p2)
{
    int *p;
    *p = *p1;  // 错误:p未初始化,不能解引用
    *p1 = *p2; // 错误:此时*p已被赋予了一个未知值,p1和p2的值被破坏
    *p2 = *p;  // 错误:此时*p已被赋予了一个未知值,p2的值被破坏
}

六八、引用的数组和数组的引用
引用的数组:
这是一个数组的引用,可以用来替代原数组的名字。
语法:type (&arrayRef)[size] = array;
例如:int (&arrRef)[5] = arr;
数组的引用:
这是一个数组元素的引用,可以用来替代数组中的单个元素的名字。
语法:type& elementRef = array[index];
例如:int& ref1 = arr[0];

六九、C风格字符串的安全漏洞
void test(char *str1)
{
    char string[10];
    if(strlen(str1) <=10)
        strcpy(string,str1);
}
数组 string 的大小为 10,但是它实际上只能容纳最多 9 个字符加上一个终止符 \0。这是因为 C 字符串是以 \0 作为终止符的。
因此,strlen(str1) <= 10 的条件不足以防止缓冲区溢出。

如果 str1 的长度大于 9 但小于等于 10,那么 strcpy(string, str1) 仍然会导致缓冲区溢出,因为 str1 的最后一个字符将覆盖 string 数组的终止符位置。

七十、又一道有关sizeof的笔试题
假设在64位的操作系统下,一个int类型占用四个字节,则:
1)int arr[10] = {0,1,2,3,4,5,6,7,8,9};
int * pt = arr;
那么:
sizeof(arr)是多少?40
sizeof(pt)是多少?8
2)void func(int array[])
{
    printf("size of array = %d\n",sizeof(array));
}
8

七一、编写一段C代码,查看一个文件的大小
FILE *fp;
lont int size = 0;
fopen("1.mp4","r");
fseek(fp,0,SEEK_END);
size = ftell(fp);
fclose(fp);

七二、逗号表达式
下面语句的运行结果是
int main(void)
{
    int x = 10,y = 3,z;
    printf("%d\n",z = (x%y,x/y));
    return 0;
}
 逗号表达式的一般形式:
 (表达式1,表达式2,表达式3...,表达式n) ->整个表达式的值为表达式n

 七三、输出字符指针
 下面程序输出的结果是:
 void main()
 {
     char * x = "abcd";
     x+= 2;
     cout << x;
 }
cd

七四、基类派生类构造函数和析构函数调用顺序。
构造函数的调用顺序如下:

基类构造函数:
如果派生类有基类,并且派生类的构造函数没有显式调用基类的构造函数,则默认调用基类的默认构造函数。
如果派生类的构造函数显式调用了基类的构造函数,则按照成员初始化列表中的顺序依次调用。
成员对象构造函数:
如果派生类中有成员对象,则按照成员初始化列表中的顺序依次调用成员对象的构造函数。
派生类构造函数体:
成员初始化列表中的构造完成后,进入派生类构造函数的函数体。
析构函数的调用顺序
析构函数的调用顺序则相反:

七五、浮点数与位操作
下面表达式,哪个是合法的?已知double m = 3.2;int n = 3;
!m *= n
(m+n)|n
m = 5,n = 3.1 m+n
m<<2
第三个是正确的

七六、new 运算符
假定p是具有int**类型的指针变量,则给p赋值的正确语句为:
p = new int;
p = new int[10];
p = new int *;
p = new int **;
int **p,p是指向指针的指针
第三个正确

七七、 有关构造函数的一道题
有如下程序:
class Name{
    char name[20];
    public:
    Name(){
    strcpy(name,"");
        cout << "r";
    }
    Name(const char *fname){
        strcpy(name,fname);
        sout << "r";
    }
}
int main(void)
{
    Name name[3] = {Name("rike"),Nmae("jack")};
    return 0;
}
七八、又符号数和无符号数
下面程序的输出结果是:
int main(void)
{
    char x = 0xff;
    printf("%d\n",x--);
    return 0;
}
-1;


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2193364.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【d60】【Java】【力扣】509. 斐波那契数

思路 要做的问题&#xff1a;求F&#xff08;n&#xff09;, F&#xff08;n&#xff09;就等于F(n-1)F(n-2)&#xff0c;要把这个F(n-1)F(n-2)当作常量&#xff0c;已经得到的值&#xff0c; 结束条件&#xff1a;如果是第1 第2 个数字的时候&#xff0c;没有n-1和n-2,所以…

系统设计,如何设计一个秒杀功能

需要解决的问题 瞬时流量的承接防止超卖预防黑产避免对正常服务的影响兜底方法 前端设计 利用 CDN 缓存静态资源&#xff0c;减轻服务器的压力在前端随机限流按钮防抖&#xff0c;防止用户重复点击 后端设计 Nginx 做统一接入&#xff0c;进行负载均衡与限流用 sentinel 等…

Kron Reduction消去法如何操作,矩阵推导过程

三阶矩阵消去单节点 在电力系统中,母线上的电流注入始终为0,这样的节点可以通过一定的方法消除。以三节点为例,假设注入节点3的电流为0,则: [ I 1 I 2 I 3 ] = [ I 1 I 2 0 ] = [ Y 11 Y 12 Y 13 Y 21 Y 22 Y 23 Y 31 Y 32 Y 33 ] [ V 1 V 2 V 3 ] \left[\begin{array}{…

交叉熵的数学推导和手撕代码

交叉熵的数学推导和手撕代码 数学推导手撕代码 数学推导 手撕代码 import torch import torch.nn.functional as F# 二元交叉熵损失函数 def binary_cross_entropy(predictions, targets):# predictions应为sigmoid函数的输出&#xff0c;即概率值# targets应为0或1的二进制标…

一个值得关注的3D生成新算法:速度和图像生成平齐,能生成合理的展开贴图和高质量mesh

今天跟大家介绍的GIMDiffusion是一种新的Text-to-3D模型&#xff0c;利用几何图像&#xff08;Geometry Images&#xff09;来高效地表示3D形状&#xff0c;避免了复杂的3D架构。通过结合现有的Text-to-Image模型如Stable Diffusion的2D先验知识&#xff0c;GIMDiffusion能够在…

系统架构设计师论文《论NoSQL数据库技术及其应用》精选试读

论文真题 随着互联网web2.0网站的兴起&#xff0c;传统关系数据库在应对web2.0 网站&#xff0c;特别是超大规模和高并发的web2.0纯动态SNS网站上已经显得力不从心&#xff0c;暴露了很多难以克服的问题&#xff0c;而非关系型的数据库则由于其本身的特点得到了非常迅速的发展…

LeetCode讲解篇之139. 单词拆分

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们使用一个数组记录字符串s在[0, i)区间能否使用wordDict组成 我们使用左右指针遍历字符串s的子串&#xff0c;左指针 j 为子串的左端点下标&#xff0c;右指针 i 为右端点下标的下一个 遍历过程中如果字符串s…

利士策分享,哀牢山:网红打卡地背后的探险风险

利士策分享&#xff0c;哀牢山&#xff1a;网红打卡地背后的探险风险 最近&#xff0c;云南的哀牢山因其独特的自然风光和神秘探险氛围而迅速走红网络。许多游客&#xff0c;特别是户外探险爱好者&#xff0c;纷纷涌入这片神秘的山脉&#xff0c;想要亲身体验那份原始与野性的…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-06

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-06 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-06目录1. A LLM-Powered Automatic Grading Framework with Human-Level Guidelines Optimization摘要&#xff1a;研究背景&…

MATLAB智能优化算法-学习笔记(4)——灰狼优化算法求解旅行商问题【过程+代码】

灰狼优化算法(Grey Wolf Optimizer, GWO)是一种基于灰狼社会行为的元启发式算法,主要模拟灰狼群体的捕猎行为(包括围攻、追捕、搜寻猎物等过程)。多旅行商问题(Multi-Traveling Salesman Problem, mTSP)是旅行商问题(TSP)的扩展,它涉及多个旅行商(车辆)从一个起点城…

超好用的element的el-pagination分页组件二次封装-附源码及讲解

前言&#xff1a;在很多后台管理系统开发时总会有很多分页组件的使用&#xff0c;如果我们每次都用elementui官网的el-pagination去写的话&#xff0c;调整所有分页的样式就会很麻烦&#xff0c;而且页面内容也会很累赘繁琐。 讲解一个我经常使用的二次封装el-pagination组件&…

产品经理产出的原型设计 - 需求文档应该怎么制作?

需求文档&#xff0c;产品经理最终产出的文档&#xff0c;也是产品设计最终的表述形式。本次分享呢&#xff0c;就是介绍如何写好一份需求文档。 所有元件均可复用&#xff0c;可作为管理端原型设计模板&#xff0c;按照实际项目需求进行功能拓展。有需要的话可分享源文件。 …

免费版U盘数据恢复软件大揭秘,拯救你的重要数据

我们的生活和工作越来越离不开各种存储设备&#xff0c;其中优盘因其小巧便携、方便使用的特点&#xff0c;成为了我们存储和传输数据的重要工具之一。为了防止你像我一样会遇到数据丢失抓狂的情况&#xff0c;我分享几款u盘数据恢复软件免费版工具来即时补救。 1.福昕U盘数据…

DDR6 或将出炉 (含 LPDDR6, CAMM)

前记:目前DDR6 尚未问世,文中较多信息是“据说”,笔者也无法考证,请大家后期以JEDEC官方为准。 很多朋友可能还没用上DDR5,但不好意思的是,DDR6 可能马上就要出现了。 三星和海力士较早开始DDR6 的设计,预计2025年商业化。 DDR6 速度 来源: 半导体观察 DDR6的速度…

VL53L4CD液位监测(2)----液位检测

VL53L4CD液位监测.2--液位检测 概述视频教学样品申请完整代码下载硬件准备STSW-IMG039容器特性包含必要的头文件变量定义测距函数 Ranging()液位误差补偿函数 Liquidlevelmeasureerrorcomponsate()数据轮询函数 get_data_by_polling()演示 概述 液位检测在工业自动化、环境监测…

[git] github管理项目之环境依赖管理

导出依赖到 requirements.txt pip install pipreqs pipreqs . --encodingutf8 --force但是直接使用pip安装不了torch&#xff0c;需要添加源&#xff01;&#xff01; pip install -r requirements.txt -f https://download.pytorch.org/whl/torch_stable.htmlpython 项目中 …

使用树莓派搭建音乐服务器

目录 引言一、搭建Navidrome二、服务穿透三、音流配置 引言 本人手机存储空间128G&#xff0c;网易云音乐6个G&#xff0c;本就不富裕的空间更是雪上加霜&#xff0c;而且重点是&#xff0c;我根本没有听几首歌&#xff0c;清除缓存后&#xff0c;整个软件都还是占用了5个G左右…

5 个PPT设计技巧,让你的开题答辩脱颖而出!

AIPaperGPT&#xff0c;论文写作神器~ https://www.aipapergpt.com/ 开题答辩是论文写作的第一道关键关卡&#xff0c;开题报告不仅展示了你的研究计划和方向&#xff0c;还要让评审老师理解你的研究背景和目的。一个设计精良的开题答辩PPT&#xff0c;不仅可以帮助你更好地陈…

LeetCode Hot100 | Day1 | 二叉树:二叉树的直径

LeetCode Hot100 | Day1 | 二叉树&#xff1a;二叉树的直径 主要学习内容&#xff1a; 二叉树深度求法 深度的 leftright1 得到的是从根结点到叶子结点的节点数量 543.二叉树的直径 [543. 二叉树的直径 - 力扣&#xff08;LeetCode&#xff09;](https://leetcode.cn/prob…

二分查找算法——山脉数组的峰顶索引&寻找峰值

1.题目解析 题目来源&#xff1a;852.山脉数组的峰顶索引 测试用例 题目来源&#xff1a;162.寻找峰值 测试用例 2.算法原理 山脉数组的峰顶索引 根据二段性将山脉数组分为两段&#xff1a;上升段与下降段 1.当mid指针落入上升段&#xff0c;说明峰值在mid指针后&#xff0c;要…