经典的笔试题解析《高质量C/C++编程》

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 经典的笔试题解析《高质量C/C++编程》

对于《高质量C/C++编程》,想必这个已经是早已成名的经典书籍了!!在此,笔者借用两三个题目!!


解析下面代码:(错误示列,请勿模仿)正确的代码,在后面部分!!!


#include <stdio.h>
void getmoney(char* p)
{
  p = (char*)malloc(100);
}
void test()
{
  char* str = NULL;
  getmoney(str);
  strcpy(str, "hello world");
  printf(str);   //这个写法也可以!!
}
int main()
{
  test();
  return 0;
}

该错误代码的运行结果为:


0a2653c851af460fa595bd959398a8f1.png


该段代码的运行思路:


2d65d23f6d4748949b924e4057485923.png


解析:


1。首先在main 函数里面走到test函数,test函数里面定义了一个变量str,str里面存放的是一个空指针(NULL),通过getmoney函数的调用,将str传递过去,将str这个变量本身传递过去,而p也是个指针变量,将str里面的内容(NULL)传给变量p,即p得到的也是空指针(NULL),在getmoney函数里面,开辟了100个字节的空间,强制类型转化为:char*类型(返回类型),将这100个字节空间的起始地址放在p里面,(假设起始地址为:0x003f4056),即,此时的p,就间接指向了那100个字节空间的起始地址,但是,p是一个指针变量,给p里面放东西了,那str会发生改变吗??答案是:不会影响str!!!原因;str与p不是同一个变量(把地址放在p里面跟str没有关系)在test函数中,此时str仍为空指针!!在strcpy(str,"hello world")中,将会出现错误!!将“hello world "放在str里面,必然会涉及解引用操作!但是对于空指针,该如何进行解引用操作??故,出现了错误!!


2.对于printf(str)  这个写法没有错误!!


 (1)。printf(”hello world"); printf函数在打印的时候,传递的不是hello world ,而是传给printf的为‘h'的地址!!


(2)。char * p="hello world"  ,在这个里面:hello world 是一个字符表达式,相当于:printf(p) ,首字符h的地址放在p里面!!即,p指向’h'!


对于上述代码的错误总结:


(1)对于上述代码在:strcpy(str, "hello world") 时,程序已经崩溃!!


(2) 但是,对于malloc函数开辟的内存空间,没有free,存在内存泄漏的问题,


(3)对于getmoney函数里面,malloc函数返回值是否为空指针的判断!!


经过上面的简短分析,我们可以这样写正确的代码:



#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void getmoney(char** p)
{
  *p = (char*)malloc(100);
}
void test()
{
  char* str = NULL;
  getmoney(&str);
  strcpy(str, "hello world");
  printf(str);
  //释放
  free(str);
  str = NULL;
}
int main()
{
  test();
  return 0;
}

运行情况为:


6de278e6d6694ce5bb08e7e842b7e74b.png


具体的解析为:


在test函数内部,创建str,在str里面,刚开始存放的是NULL(空指针),通过getmoney函数将str的地址传过去!假设str的地址为:0x0012ff40(一级指针的地址,需要用二级指针来接收)即指针变量p来接收,即,p里面存放的就是0x0012ff40,即,p指向str,而*p = (char*)malloc(100);开辟了100个字节的空间放在*p里面去,即放在str里面,假设,这100个字节的空间的起始地址为:0x34ff000045,所以,将0x34ff000045,放在str里面去了,strcpy(str, "hello world");把 hello world拷贝到str所指向的空间(malloc函数开辟的100个自己的空间),最后,用完了再释放掉,然后再置为NULL(空指针)!!!


代码的运行结果为:


12c3b7f3f8814309a195c64f051d4445.png


另外一种也是正确的写法为:


#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char* getmoney(char* p)
{
  p = (char*)malloc(100);
  return p;
}
void test()
{
  char* str = NULL;
  str = getmoney(str);
  strcpy(str, "hello world");
  printf(str);
  //释放
  free(str);
  str = NULL;
}
int main()
{
  test();
  return 0;
}


上述代码的运行结果为:


34e8d716411043c08c7ffba9fbba23de.png


本文就先到此结束!!


相关文章
|
17天前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
17天前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
20天前
|
存储 机器学习/深度学习 编译器
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
【C++终极篇】C++11:编程新纪元的神秘力量揭秘
|
17天前
|
存储 算法 C++
深入浅出 C++ STL:解锁高效编程的秘密武器
C++ 标准模板库(STL)是现代 C++ 的核心部分之一,为开发者提供了丰富的预定义数据结构和算法,极大地提升了编程效率和代码的可读性。理解和掌握 STL 对于 C++ 开发者来说至关重要。以下是对 STL 的详细介绍,涵盖其基础知识、发展历史、核心组件、重要性和学习方法。
|
17天前
|
存储 安全 算法
深入理解C++模板编程:从基础到进阶
在C++编程中,模板是实现泛型编程的关键工具。模板使得代码能够适用于不同的数据类型,极大地提升了代码复用性、灵活性和可维护性。本文将深入探讨模板编程的基础知识,包括函数模板和类模板的定义、使用、以及它们的实例化和匹配规则。
|
17天前
|
安全 编译器 C语言
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
|
17天前
|
存储 程序员 C语言
【C++篇】深度解析类与对象(上)
在C++中,类和对象是面向对象编程的基础组成部分。通过类,程序员可以对现实世界的实体进行模拟和抽象。类的基本概念包括成员变量、成员函数、访问控制等。本篇博客将介绍C++类与对象的基础知识,为后续学习打下良好的基础。
|
3月前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
Java 并发编程——volatile 关键字解析
|
3月前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
3月前
|
安全 编译器 C++
C++ `noexcept` 关键字的深入解析
`noexcept` 关键字在 C++ 中用于指示函数不会抛出异常,有助于编译器优化和提高程序的可靠性。它可以减少代码大小、提高执行效率,并增强程序的稳定性和可预测性。`noexcept` 还可以影响函数重载和模板特化的决策。使用时需谨慎,确保函数确实不会抛出异常,否则可能导致程序崩溃。通过合理使用 `noexcept`,开发者可以编写出更高效、更可靠的 C++ 代码。
73 1

推荐镜像

更多