c初探:数据类型、数组、内存布局、指针

windows命令行 (可以不用搭理这里,在Linux玩就行)

Windows C/C++编译器: https://sourceforge.net/projects/mingw/files/

配置环境变量 PATH: ${MinGW安装目录}/MinGW/bin

c与c++

C语言是一门通用计算机编程语言,广泛应用于底层开发。

c语句是面向过程的语言,c++ 是面向对象的语言,C++对c进行扩展。

c是c++ 的子集,c++ 是c的超集,所以大部c语言程序都可以不加修改的拿到c++下使用。

1、基本数据类型

1.**signed**----有符号,可修饰char、int。Int是默认有符号的。
2.**unsigned**-----无符号,修饰int 、char
整型 字节 取值范围 占位
int 4 -2,147,483,648 到 2,147,483,647 %d
unsigned int 4 0 到 4,294,967,295 %u
short 2 -32,768 到 32,767 %hd
unsigned short 2 0 到 65,535 %hu
long 4 -2,147,483,648 到 2,147,483,647 %ld
unsigned long 4 0 到 4,294,967,295 %lu
char 1 -128 到 127 %c
unsigned char 1 0 到 255 %c

为了得到某个类型或某个变量在特定平台上的准确大小,使用 sizeof 运算符。

表达式 sizeof(type) 得到对象或类型的存储字节大小。

long int 其实就是长整型 = long 可以省去int

在标准中,规定 int至少和short一样长,long至少和int一样长。

为什么会存在long?

long和int在早期16位电脑时候 int 2字节,long 4字节,而计算机发展到现在,一般32、64下,long和int一样。和java类比的话,java的long就是 long long 8字节

格式化还有:

8进制 %o

16进制 小写: %x 大写:%X

(0x)+16进制前面 %#x

浮点型 字节 精度 占位
float 4 6位小数 %f
double 8 15位小数 %lf
long double 8 19位小数 %Lf

C99标准以前,C语言里面是没有bool,C++ 里面才有,

C99标准里面定义了bool类型,需要引入头文件stdbool.h

bool类型有只有两个值:true =1 、false=0。

因此实际上bool就是一个int

所以在c/c++中 if 遵循一个规则, 非0为true,非空为true;

NULL 其实也就是被define为了 0

2、格式化

include <stdio.h>

printf、sprintf等

sprintf:

​ 将格式化的数据写入第一个参数

char str[100];
sprintf(str, "img/png_%d.png", 1);
printf("%s", str); //使用 0 补到3个字符
sprintf(str, "img/png_%03d.png", 1);
printf("%s", str);

关于include的“<>”和“""”的却别

  • "" 指的是相对路径

  • <> 查找系统的,以及我们给它定义的目录

输出控制符

常用的输出控制符主要有以下几个:

控制符 说明 示例
%d 按十进制整型数据的实际长度输出 printf("%d",123);输出123
%ld 输出长整型数据。
%md m 为指定的输出字段的宽度。如果数据的位数小于 m,则左端补以空格,若大于 m,则按实际位数输出。
%u 输出无符号整型(unsigned)。输出无符号整型时也可以用 %d,这时是将无符号转换成有符号数,然后输出。但编程的时候最好不要这么写,因为这样要进行一次转换,使 CPU 多做一次无用功。 printf("%u",123);输出123
%c 字符型。可以把输入的数字按照ASCII码相应转换为对应的字符 printf("%c\n",64)输出A
%p 以16进制形式输出指针 printf("%010p","lvlv");输出:0x004007e6
%f 用来输出实数,包括单精度和双精度,以小数形式输出。不指定字段宽度,由系统自动指定,整数部分全部输出,小数部分输出 6 位,超过 6 位的四舍五入。 printf("%.9f %.9lf",0.000000123,0.000000123);输出0.000000123 0.000000123。注意指定精度,否则printf默认精确到小数点后六位
%.mf 输出实数时小数点后保留 m 位,注意 m 前面有个点。
%o 以八进制整数形式输出,这个就用得很少了,了解一下就行了。 printf("0%o",123);输出0173
%s 用来输出字符串。用 %s 输出字符串同前面直接输出字符串是一样的。但是此时要先定义字符数组或字符指针存储或指向字符串,这个稍后再讲。 printf("%s","测试test");输出:测试test
%x(或 %X 或 %#x 或 %#X) 以十六进制形式输出整数,这个很重要。 printf("0x%x 0x%X",123,123);输出0x7b 0x7B
%e(%E) 科学计数法,使用指数(Exponent)表示浮点数,此处”e”的大小写代表在输出时“e”的大小写 printf("%e %E",0.000000123,0.000000123);输出1.230000e-07 1.230000E-07

%x、%X、%#x、%#X 的区别

一定要掌握 %x(或 %X 或 %#x 或 %#X),因为调试的时候经常要将内存中的二进制代码全部输出,然后用十六进制显示出来。下面写一个程序看看它们四个有什么区别:

# include <stdio.h>
int main(void)
{
int i = 47;
printf("%x\n", i);
printf("%X\n", i);
printf("%#x\n", i);
printf("%#X\n", i);
return 0;
}
在 VC++ 6.0 中的输出结果:
2f
2F
0x2f
0X2F

从输出结果可以看出:如果是小写的x,输出的字母就是小写的;如果是大写的X,输出的字母就是大写的;如果加一个#,就以标准的十六进制形式输出。

最好是加一个#,否则如果输出的十六进制数正好没有字母的话会误认为是一个十进制数呢!总之,不加#容易造成误解。但是如果输出0x2f0x2F,那么人家一看就知道是十六进制。而且%#x%#X中,笔者觉得大写的比较好,因为大写是绝对标准的十六进制写法。

3、数组与内存布局

数组 : 连续的内存

//java
int[] a //c
//必须声明时候确定大小
int a[10]
//或者 直接初始化
int a[] = {1,2,3} //大小
printf("%d",sizeof(a)/sizeof(int));

栈内存限制 linux:ulimit -a 查看

但是直接分配这么大不行,因为堆栈可能保存参数,返回地址等等信息

动态内存申请

malloc

没有初始化内存的内容,一般调用函数memset来初始化这部分的内存空间.

使用malloc申请了内存后,有可能这块内存是复用之前释放掉的,里面还可能会有数据,所以,使用memset来清空数据之前的数据,并初始化自己的数据

int k = 1*1024*1024;
//在堆中动态申请内存
int *j = (int *)malloc(k);
//将j指向的内存初始化为0,长度为k
memset(j,0,k); //内存释放
free(j);
j = NULL;//j = 0;

calloc

申请内存并将初始化内存数据为NULL.

int *pn = (int*)calloc(10, sizeof(int));

//申请内存并将内存初始化为null即为0
int *p = (int*)calloc(10, sizeof(int));//申请40个字节的长度 //上面一句话相当于下面两句话 int *p = (int*)malloc(sizeof(int)*10);
memset(p,0, sizeof(int)*10); //内存释放
free(p);
p = NULL;

realloc

​ 对malloc申请的内存进行大小的调整.

char *a = (char*)malloc(10);
realloc(a,20);//对a进行扩容到20

特别的:

alloca

在栈申请内存,因此无需释放.

int *p = (int *)alloca(sizeof(int) * 10);

物理内存

物理内存指通过物理内存条而获得的内存空间

虚拟内存

一种内存管理技术

电脑中所运行的程序均需经由内存执行,若执行的程序占用内存很大,则会导致内存消耗殆尽。

虚拟内存技术还会匀出一部分硬盘空间来充当内存使用。

代码段:

存放程序执行代码(cpu要执行的指令)

栈是向低地址扩展数据结构

堆是向高地址扩展数据结构

进程分配内存主要由两个系统调用完成:brk和mmap

  1. brk是将_edata(指带堆位置的指针)往高地址推;
  2. mmap 找一块空闲的虚拟内存。

通过glibc (C标准库)中提供的malloc函数完成内存申请

malloc小于128k的内存,使用brk分配内存,将_edata往高地址推,大于128k则使用mmap

音视频学习 (一) C 语言入门

C 语言教程-RUNOOB.COM

C++ 教程-RUNOOB.COM

C/C++ 开发神器 CLion 使用入门

Window10上CLion极简配置教程

c初探:数据类型、数组、内存布局、指针的更多相关文章

  1. PC逆向之代码还原技术,第一讲基本数据类型在内存中的表现形式.浮点,指针寻址公式

    目录 代码还原技术 一丶简介代码还原 二丶代码还原中的数据类型表现形式 1.整数类型 2.无符号整数 3.有符号整数 4.浮点数数据类型 5.浮点编码 4.Double类型解析. 三丶浮点汇编 1.浮 ...

  2. 重磅硬核 | 一文聊透对象在 JVM 中的内存布局,以及内存对齐和压缩指针的原理及应用

    欢迎关注公众号:bin的技术小屋 大家好,我是bin,又到了每周我们见面的时刻了,我的公众号在1月10号那天发布了第一篇文章<从内核角度看IO模型的演变>,在这篇文章中我们通过图解的方式以 ...

  3. new对象数组时的内存布局

    #include <iostream> #include <limits> using namespace std; #define SAFE_DELETE(x) \ { \ ...

  4. C++ 虚函数和多重继承的内存布局初探

    C++ 对象的内存布局 一切以事实说话: 代码: 1: #include <stdio.h> 2:  3: class A { 4: public: 5: int a; 6: int b; ...

  5. 内存的堆分配和栈分配 & 字符数组,字符指针,Sizeof总结

    堆和栈的区别 一个由C/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.2.堆区(heap ...

  6. 关于Class对象、类加载机制、虚拟机运行时的内存布局的全面解析和推测

    简介: 本文是对Java的类加载机制,Class对象,反射原理等相关概念的理解.验证和Java虚拟机中内存布局的一些推测.本文重点讲述了如何理解Class对象以及Class对象的作用. 欢迎探讨,如有 ...

  7. Java对象的创建、内存布局和访问定位

    在Java运行时数据区中,我们知道了虚拟机内存的概况,本文介绍虚拟机内存中的数据的其它细节,如对象如何创建.如何布局以及如何访问. 基于实用的原则,这里以HotSpot虚拟机和常用的内存区域Java堆 ...

  8. 关于Class对象、类加载机制、虚拟机运行时内存布局的全面解析和推测

    简介: 本文是对Java的类加载机制,Class对象,反射原理等相关概念的理解.验证和Java虚拟机中内存布局的一些推测.本文重点讲述了如何理解Class对象以及Class对象的作用. 欢迎探讨,如有 ...

  9. 大杂烩 -- Java内存布局【图】以及java各种存储区【详解】

    基础大杂烩 -- 目录 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 一.Java内存布局浅谈 1. 总述 我们知道,线 ...

  10. Java对象创建的过程及对象的内存布局与访问定位

    这里以HotSpot为例,且所说的对象指普通的Java对象,不包括数组和Class对象等. 1.对象创建的过程 1.类加载.解析.初始化:虚拟机遇到new时先检查此指令的参数是否能在常量池中找到类的符 ...

随机推荐

  1. DBGRIDEH 底部多列 发现

    1.设置底部行数 2.点击footers 单独对每一行进行设置 3.单独对这两行 进行设置 5.看下辅助 所以用的时候可以这样用:WeiTopTradeShow.FieldColumns['top_x ...

  2. 【MFC学习二】CFileDialog导出文件

    用CFileDialog导出文件,用户可指定文件名后缀等,感觉操作上比上文的 BROWSEINFO 更加人性化. //将数据项写入CSV文件 int PutCSVItemLine(FILE *file ...

  3. MySQL的执行流程和执行顺序

    MySQL执行过程以及顺序 前言:MySQL在我们的开发中基本每天都要面对的,作为开发中的数据的来源,MySQL承担者存储数据和读写数据的职责.因为学习和了解MySQL是至关重要的,那么当我们在客户端 ...

  4. Javascript操作对象数组实现增删改查

    1.介绍 最近帮朋友弄一个简单的针对json数组的增删改成页面,正好涉及到了js去操作对象数组实现增删改查功能.我估计很多朋友应该也会遇到这类操作,所以记录一下以便分享. 2.数据准备 这里我就以学生 ...

  5. NamedTuple技巧用法

    PS: 第一眼看到这个代码的时候,就联想到了go中的构造函数,虽然知道go中的构造函数其实就类比于python中的构造函数__init__,但是不得不说,这个太像了 在日常编码中,我们经常需要写一些返 ...

  6. 格式化占位符%r和!r

    # 作用 都是格式化原形输出,!r用于format格式化,%r用于%格式化 # 示例 a = '123' b = 'hello, {!r}'.format(a) b = 'hello, %r' % ( ...

  7. 用random.simple来解决从0-99这100个数中随机取10个不重复的数

    语法: random.simple(list,k) 返回以长度为k的新列表,新列表存放list所产生k个随机不重复的元素 import random print(random.simple(range ...

  8. 【Azure 事件中心】在Windows系统中使用 kafka-consumer-groups.bat 查看Event Hub中kafka的consumer groups信息

    问题描述 使用 Apache Flink 连接支持 Apache Kafka的Azure Event Hub后,由于消费端的Consumer Group是动态创建,在门户页面和Service Bus ...

  9. php7中的三元运算符的区别

    <?php $tmparr = ['cover'=>'http://img.immomo.com.cn']; echo isset($tmparr['cover'])."\n&q ...

  10. Codeforces Round 729 (Div. 2)B. Plus and Multiply(构造、数学)

    题面 链接 B. Plus and Multiply 题意 给定\(n,a,b\) 可以进行的操作 \(*a\) \(+b\) 最开始的数是1 问能否经过上面的两种操作将1变为n 题解 这题的关键是能 ...