char在内存中开辟了12字节空间?

ImAmelie 2014-08-10 06:20:37

#pragma pack(show)//显示8
#include <stdio.h>
int main()
{
char a, b, c, d, e, f;
printf("%p\n%p\n%p\n%p\n%p\n%p\n", &a, &b, &c, &d, &e, &f);
printf("%d\n", &e - &f);//显示12
printf("%d\n", &d - &e);//显示12
printf("%d\n", &c - &d);//显示12
printf("%d\n", &b - &c);//显示12
printf("%d\n", &a - &b);//显示12
return 0;
}

char是1字节的数据类型 怎么会显示12字节呢?
...全文
482 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2014-08-12
  • 打赏
  • 举报
回复
在你的编程生涯中,迟早是要了解编译器支持的命令行选项及其作用的。
jmppok 2014-08-12
  • 打赏
  • 举报
回复
引用 1 楼 lisong694767315 的回复:
GCC下的结果:

0x7fff884b1b1f
0x7fff884b1b1e
0x7fff884b1b1d
0x7fff884b1b1c
0x7fff884b1b1b
0x7fff884b1b1a
1
1
1
1
1
gcc是正解,VC中加入了很多微软的东西,所以经常会得出和C++标准不同的结果
malone1 2014-08-12
  • 打赏
  • 举报
回复
8字节对齐?
日知己所无 2014-08-12
  • 打赏
  • 举报
回复

VC编译的时候,分为Debug模式和Release模式
楼主应该是在Debug模式下编译、运行的

在Debug模式下:
char本身占用了1个字节,char和char之间被VC用0xcc填充了内存【参考贴图】

使用0xcc来填充内存,是由于int 3【读作3号中断】的机器码是0xcc
而int 3是使CPU中断到调试器,以供调试者对执行现场进行各种分析用的专门用来支持调试用的指令【由Intel定义的CPU指令】
也就是说,如果在Debug模式下,发生了内存访问错误,比如用指针错误的访问了不该访问的内存,会立即弹出Debug信息,感兴趣的话可以参考下面的链接自己试试

参考:
http://blog.sina.com.cn/s/blog_495c65790100dpgv.html
http://book.51cto.com/art/200812/100663.htm

为什么填充了11个0xcc,造成两个变量的地址之间的差是12呢?
这里应该涉及到了内存对齐(Memory Alignment)【比较肯定】和桩边界(Boundary)【根据经验推测的】

内存对齐网上的资料很多,可以直接参考,一般的认识是为了提高内存访问速度,编译器会把变量优化到1、2、4、8、16这些首地址上,楼主自己写的代码里面有pragma pack指令,估计对这方面应该有一定的了解。

桩边界(Boundary)其实是VC用0xcc填充内存的一个引申
因为如果简单的用【a,填充,b,填充】,而不加桩的话,有些内存访问的问题会被隐蔽掉

为了更好的暴露问题,应该是【桩,a,填充,桩,b,填充,桩】这种方式填充的,VC为了省事儿把桩和填充都用0xcc填充了
有些工具【当然也可以是自己写的程序】把桩设置为特殊的数据,比如0,在程序执行完之前,检查一下所有桩是否都是0,来判断是否有内存访问错误【VB/VC或者JAVA/VC多语言互相操作时,有时会有这种特殊的检验的需求】

参考:
http://wenku.baidu.com/link?url=8tmdsd8KrebV3t1hkoT7KIl5qIhR_Xk0zv5kXSHepU3TASVTkV58-A3018z3vKyUvOFgnAm_Dlw7DVjwA5pRVqkToa4Sy60ALvelM0aPswO
http://blog.csdn.net/flyfish1986/article/details/5488240

如果在Release模式下,就不存在这些问题了
但是变量的定义顺序、使用顺序,和实际编译器为其分配内存的顺序是不完全相同的;语言本身也不对此做出任何保证

在我机器上Release版的运行结果如下:
0031FA76
0031FA78
0031FA79
0031FA7A
0031FA7B
0031FA77
4
-1
-1
-1
-2

之所以是负数,估计是因为内存端序的问题
这里如果不考虑顺序的话,所有的char形变量都是1个字节1个字节的连续排在内存中的

另外,原来的值是两个变量的地址之间的距离,而不是变量本身占用的空间
正确的计算char形变量占用内存大小的方法如下:
printf("%d\n", sizeof(a));
输出的结果应该是楼主期待的1

如果哪里说的不太准确,希望高手们给出提示。
赵4老师 2014-08-11
  • 打赏
  • 举报
回复
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
shiguojie19892 2014-08-11
  • 打赏
  • 举报
回复
引用 12 楼 zjq9931 的回复:
[quote=引用 楼主 u013491662 的回复:]

#pragma pack(show)//显示8
#include <stdio.h>
int main()
{
	char a, b, c, d, e, f;
	printf("%p\n%p\n%p\n%p\n%p\n%p\n", &a, &b, &c, &d, &e, &f);
	printf("%d\n", &e - &f);//显示12
	printf("%d\n", &d - &e);//显示12
	printf("%d\n", &c - &d);//显示12
	printf("%d\n", &b - &c);//显示12
	printf("%d\n", &a - &b);//显示12
	return 0;
}
char是1字节的数据类型 怎么会显示12字节呢?
编译器的问题。[/quote] 这样定义他们直接买的内存不一定是连续的。
Saleayas 2014-08-11
  • 打赏
  • 举报
回复
VC++ 编译器的调试版本的每一个变量的前后,都添加了边界。 这样就可以知道是否越界了。
  • 打赏
  • 举报
回复
引用 楼主 u013491662 的回复:

#pragma pack(show)//显示8
#include <stdio.h>
int main()
{
	char a, b, c, d, e, f;
	printf("%p\n%p\n%p\n%p\n%p\n%p\n", &a, &b, &c, &d, &e, &f);
	printf("%d\n", &e - &f);//显示12
	printf("%d\n", &d - &e);//显示12
	printf("%d\n", &c - &d);//显示12
	printf("%d\n", &b - &c);//显示12
	printf("%d\n", &a - &b);//显示12
	return 0;
}
char是1字节的数据类型 怎么会显示12字节呢?
编译器的问题。
难题 2014-08-11
  • 打赏
  • 举报
回复
VS会在变量大小后多加一点空间,你要看具体的要用GCC来看
action_tmp 2014-08-10
  • 打赏
  • 举报
回复
我来旁观学习
  • 打赏
  • 举报
回复
查看类型和变量占用的字节数用sizeof()函数吧,如sizeof(int)、sizeof(char)、 sizeof(a)(a为变量)……
我看你有戏 2014-08-10
  • 打赏
  • 举报
回复
引用 楼主 u013491662 的回复:

#pragma pack(show)//显示8
#include <stdio.h>
int main()
{
	char a, b, c, d, e, f;
	printf("%p\n%p\n%p\n%p\n%p\n%p\n", &a, &b, &c, &d, &e, &f);
	printf("%d\n", &e - &f);//显示12
	printf("%d\n", &d - &e);//显示12
	printf("%d\n", &c - &d);//显示12
	printf("%d\n", &b - &c);//显示12
	printf("%d\n", &a - &b);//显示12
	return 0;
}
char是1字节的数据类型 怎么会显示12字节呢?
这样定义是a,b,c... 在内存中的数据存储位置不确定的啊 只能确定的是, a是第一个先进栈
cyd54454 2014-08-10
  • 打赏
  • 举报
回复
char是几个字节,和两个char之间相隔几个字节,不要混为一谈呀。为什么要研究这种问题...
max_min_ 2014-08-10
  • 打赏
  • 举报
回复
这个和操作系统编译环境都有影响吧! 没必要研究这个。。
辰岡墨竹 2014-08-10
  • 打赏
  • 举报
回复
pragma pack只对结构体、联合以及类成员等声明级别的有效,对于定义不起作用。 所以char还是按默认的CPU地址对齐方式压栈,另外你的可能是Debug版本,有额外插入的调试用字节。
707wk 2014-08-10
  • 打赏
  • 举报
回复
引用 3 楼 lovesmiles 的回复:
试下数组看看,你这样属于函数栈数据,变量之间的地址取决于编译器。并不能从这个地址差里看出char的大小。
+1,你应该定义为str[5]
勤奋的小游侠 2014-08-10
  • 打赏
  • 举报
回复
试下数组看看,你这样属于函数栈数据,变量之间的地址取决于编译器。并不能从这个地址差里看出char的大小。
ImAmelie 2014-08-10
  • 打赏
  • 举报
回复
我用的是VS2013 win8.1 64bit 不知道是怎么回事 希望有人解答
神奕 2014-08-10
  • 打赏
  • 举报
回复
GCC下的结果:

0x7fff884b1b1f
0x7fff884b1b1e
0x7fff884b1b1d
0x7fff884b1b1c
0x7fff884b1b1b
0x7fff884b1b1a
1
1
1
1
1

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧