C语言进阶知识点(持续跟新)

2023-10-27

还是有点儿进阶的知识点,

1.大段、小段内存模型

        int val = 0x12345678;
	int *p1 = &val;
	char *p2 = (char *)p1;
	printf("%x\n",*p2);
	p2++;
	printf("%x\n",*p2);

	short *p3 = &val;
	printf("%x\n",*p3);
	p3 ++;
	printf("%x\n",*p3);
    return 0;

运行结果:

78
56
5678

1234

结论:

(1)X86是小段(little endian),首先存储高位数值,然后依次向下存储。(与人类的思维不一样啊,反正记住,与读的顺序相反(读的意思是,我们从嘴巴读出来):先读的,后存储)

(2)再次印证了指针类型的重要性(不只是指针类型,在这里我还要说一句,其实在计算机内存中并不存在所谓的数据类型,比如char,int等的。这个类型在代码中的作用就是让编译器知道每次应该从那个地址起始读取多少位的数据,赋值给相应的变量

2  结构体大小和位域结构体大小的计算

http://www.cnblogs.com/leezhm/archive/2011/07/19/2110864.html

(1)结构体大小计算:

  a、结构体中的第一个成员的首地址也即是结构体变量的首地址。
  b、结构体中的每一个成员的首地址相对于结构体的首地址的偏移量(offset)是该成员数据类型大小的整数倍。
  c、结构体的总大小是对齐模数(对齐模数等于#pragma pack(n)所指定的n与结构体中最大数据类型的成员大小的最小值)的整数倍。

struct
   {
        char a;
        int b;
        short c;
        char d;
    }dataAlign;
     
    struct
    {
        char a;
        char d;
        short c;
        int b;
       
   }dataAlign2;

第一个结果大小是12,第二个是8;

(2)位域的大小计算:

满足上面结构体计算的三个法则,除此之外,还要满足:

  d、如果相邻位域类型相同,并且它俩位域宽度之和小于它的数据类型大小,则后面的字段紧邻前面的字段存储。
  e、如果相邻位域类型相同,但是它俩位域宽度之和大于它的数据类型大小,则后面的字段将从新的存储单元开始,其偏移量为其类型的整数倍。
  f、如果相邻位域类型不同,在VC中是不采取压缩方式,但是GCC会采取压缩方式。

struct
  {
      char a:4;
      int b:6;
    }bitChar2;
struct
 {
    char a:3;
    char b:3;
    char c:7;
    double d;
    int e:4;
    int f:30;
  }bitChar;

第一个大小为8,第二个大小为24

3.常量字符串位于静态存储区

一道面试题引发的:

char* GetString1()
{
   char p[] = "Hello World";
   return p;
}
char* GetString2()
{
   char *p = "Hello World";
   return p;
}
int _tmain(int argc, _TCHAR* argv[])
{
   printf("GetString1 returns: %s. /n", GetString1());
   printf("GetString2 returns: %s. /n", GetString2());
   return 0;
}

答案:输出两行,第一行GetString1 returns: 后面跟的是一串随机的内容,而第二行GetString2 returns: Hello World.两个函数的区别在于GetString1中是一个数组,而GetString2中是一个指针。

当运行到GetString1时,p是一个数组,会开辟一块内存,并拷贝"Hello World"初始化该数组。接着返回数组的首地址并退出该函数。由于p是GetString1内的一个局部变量,当运行到这个函数外面的时候,这个数组的内存会被释放掉。因此在_tmain函数里再去访问这个数组的内容时,结果是随机的。

当运行到GetString2时,p是一个指针,它指向的是字符串常量区的一个常量字符串。该常量字符串是一个全局的,并不会因为退出函数GetString2而被释放掉。因此在_tmain中仍然根据GetString2返回的地址得到字符串"Hello World"。

有关更多的内容见:

1:http://hi.baidu.com/%D0%C7%BB%F0%D3%C4%C0%B6/blog/item/410174384e529ffbb211c71c.html:常量字符串为什么在静态存储区?

2:http://blog.csdn.net/hackbuteer1/article/details/6706562:char str[]和char *str的区别

4. (int&)a和(int)a的区别

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
	float a = 1.0f;
	cout << (int)a << endl;
	cout << (int&)a << endl;
	cout << boolalpha << ( (int)a == (int&)a ) << endl; // 输出什么?
	float b = 0.0f;
	cout << (int)b << endl;
	cout << (int&)b << endl;
	cout << boolalpha << ( (int)b == (int&)b ) << endl; // 输出什么? 
}

(int&)a == static_cast <int&>(a)
(int)&a == reinterpret_cast <int>(&a);

(int&)a 不经过转换, 直接得到a在内存单元的值,并将其转换成整数输出。
(int)a a在内存中的值转换成int类型


float类型在内存中存储的形式是 ,符号位 指数 尾数
由754标准:阶码采用增码(该数补码的反符号),尾数采用原码
所以1.0f 在内存中的形式为
0011 1111 1000 0000 0000 0000 0000 0000
所以输出的是 0x3f800000

0 在内存中的的存储形式
0000 0000 0000 0000 0000 0000 0000 0000

所以输出的是0x00000000

所以前面一个是false,后面一个是true





















本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言进阶知识点(持续跟新) 的相关文章

随机推荐

  • 寻找数列(构造+拓扑)

    寻找一个有n个整数的数列 满足下列条件 其中任意连续p个数之和是正数 其中任意连续q个数之和是负数 若无法找到 则输出 No 否则输出一个数值最小的数列 输入 n p q 输出 n个整数 样例 输入 5 4 3 输出 2 2 5 2 2 设
  • 通过BAT脚本批量修改文件名

    通过BAT脚本批量修改文件名 一 生成命名文件名列表 二 在excel中对应的行输入修改后的文件名 在这里插入图片描述 https img blog csdnimg cn 20201012102112886 png x oss proces
  • 这几天心里颇不宁静,采的不是信号,而是寂寞

    原文来自微信公众号 工程师看海 这几天心里颇不宁静 今晚在院子里坐着乘凉 忽然想起往日一同攻坚的战友 在这满月的光里 该是另一番样子吧 我们制定的uV级别信号的采集方案 从原理到模拟环境测试 一切都OK 然而真正到现场采集信号时却发现 压根
  • python获取时间日期列表集合

    python获取时间日期列表集合 以前过去以后未来 安装datedays pip install datedays import datedays if name main print 测试时间 datedays getnow print
  • python-获取当前目录/上级目录/上上级目录...

    获取文件 在其他人使用你的代码时 常常因为目录层级的问题为无法运行程序 所以在引起其他模块文件时 尽量采取绝对路径的方式导 python官方建议尽量的使用绝对目录 而不是相对目录 获取当前文件的绝对路径 os path abspath fi
  • 公式微分后,为什么是偏导的相加

    二郎在研究一个公式中 会涉及分析变量对最终结果产生影响时 注 最终结果 这里确实是最后需要获得的结果 数学公式一定要和物理对应 输入放在一边 输出放在一边 否则都放在一边 就全成自变量了 变量对最终结果影响 既然涉及了分析 那么我们就先说为
  • c++中分文件编写

    c 中分文件编写 本文内容来自某视频教程 分文件格式编写格式 h中写类的成员函数声明 cpp中写成员函数实现 代码案例 所有代码写在一个文件中 如下是一段没有分文件编写的代码 即将所有代码写在一个源文件中 如图所示 以下代码实现了利用全局函
  • nginx转发wss

    做了一个tp6 swoole的项目 没找到swoole开启ssl的资料 想起以前做过转发可以实现 就新建了一个站 然后转发到swoole的端口 也能实现wss的访问 下面是配置文件 upstream wss server 127 0 0 1
  • ERP、SCM、CRM的区别和联系?

    ERP 企业资源计划 SCM 供应链管理系统 CRM 客户关系管理 是当前企业信息系统三大热门话题 无论是ERP SCM 还是CRM其根本目标都在于提高企业管理水平 提高企业核心竞争力 本文怡海软件将分别从其含义 区别 联系 集成方面进行简
  • Unity Scroll View踩坑记录

    Unity要想实现游戏中的背包滑动效果 最简单的方法就是使用ScrollView这个组件 这个组件可以实现拖动滑动的效果 如上图所示 我希望将这些Item实现背包的排版效果 第一步 现将所有的Item移到Content下 此时我们会发现部分
  • Java集合——Java8之HashMap

    一 前言 在分析jdk1 8后的HashMap源码时 发现网上好多分析都是基于之前的jdk 而Java8的HashMap对之前做了较大的优化 其中最重要的一个优化就是桶中的元素不再唯一按照链表组合 也可以使用红黑树进行存储 总之 目标只有一
  • Python爬取某短视频热点

    随着短视频的大火 不仅可以给人们带来娱乐 还有热点新闻时事以及各种知识 刷短视频也逐渐成为了日常生活的一部分 本 文以一个简单的小例子 简述如何通过Pyhton依托Selenium来爬取短视频 仅供学习分享使用 如有不足之处 还请指正 涉及
  • pyspark环境安装历史难题终于解决

    path JAVA HOME里面的D JAVA 1 jdk1 8 0 152 bin一定要全并且对应上 踩坑记录 已解决 报错 WARN ProcfsMetricsGetter Exception when trying to comput
  • 基于Java的OA系统的设计与实现

    源码及论文下载 http www byamd xyz tag java 摘 要 学习和研究办公自动化中涉及到的知识和技术是实现办公自动化系统的前提条件 通过学习研究 掌握了其中的关键技术之后 结合自身的理解 对其做出了相应的表述 同时也成功
  • 【第03例】IPD体系进阶

    目录 前言 专栏目录 具体内容 IPD 相关专栏推荐 专栏列表 作者简介 前言 今天继续来讲讲 IPD 中涉及的几个评审点 ADCP 是英文 Av
  • 彻底理解coookie、session、token

    一 发展史 1 很久很久以前 web基本上就是文档的浏览而已 既然是浏览 作为服务器 不需要记录谁在某一段时间里都浏览了什么文档 每次请求都是一个新的HTTP协议 就是请求加响应 尤其是我不用记住是谁刚刚发了HTTP请求 每个请求对我来说都
  • Linux下的Oracle连接

    1 进入Oracle su oracle 2 开启监听器 oracle localhost root lsnrctl status oracle localhost root lsnrctl start oracle localhost r
  • 微信小程序自定义 tab-bar(基于 wepy)

    背景 微信小程序提供的原生 tab bar 功能简单 样式单一 无法满足业务需求 项目中使用的是 wepy 1 x 框架 实现原理与原生类似 方案 一 使用组件 在每个Tab页引入 修改全局配置 app wpy export default
  • CloudCompare--安装和简单的使用方法

    CloudCompare 安装和简单的使用方法 CloudCompare工具是一个非常好的处理点云数据的开源工具 有个不错的框架 很多公司对该工具进行二次开发以满足公司需要 第一次使用CloudCompare感觉非常好用 有兴趣的可以多了解
  • C语言进阶知识点(持续跟新)

    还是有点儿进阶的知识点 1 大段 小段内存模型 int val 0x12345678 int p1 val char p2 char p1 printf x n p2 p2 printf x n p2 short p3 val printf