c语言学习笔记_数据格式_int与char的存储方式小节

本文通过修改《Learn C the Hard Way》中的示例代码,探讨了GCC编译器下C语言中int与char类型变量的存储差异,以及对未正确终止字符串的处理方式。实验展示了GCC如何初始化未指定的内存区域,并解释了不同编译环境下字符串行为的差异。
摘要由CSDN通过智能技术生成

有时候错误的代码会让我们更深刻的理解一门编程语言,所以在Learn c the hard way一书中,作者不停的让我们把正确的代码破坏掉,发挥我们的好奇心与想象力,去发觉c语言的一些特性。

为了弄清弄清c中int与char型变量存储的异同和gcc对无‘\0'字符数组的的反应,修改了Learn c the hard way书中的ex8

代码如下

#include <stdio.h>

int main(int argc,char *argv[])
{
	int areas[] = {10, 12, 13, 14, 20};
	char name [] = "Zed";
	char full_name[] = {
		'Z', 'e', 'd',
		' ', 'A', '.', ' ',
		'S', 'h', 'a', 'w'
	};
	unsigned int interg[2];
	interg[0] = '\0' * 0x01000000 + 'A'*0x00010000 + 'B' * 0x00000100 + 'C' * 0x00000001;
	unsigned int inter = interg[0];

	// WARNING: On some system you may have to change the
	// %ld in this code to a %u since it will use unsignt ints
	printf("The size of an int: %ld\n",sizeof(int));
	printf("The siez of areas (int[]):%ld\n",
			sizeof(areas));
	printf("The number of ints in areas: %ld\n",
			sizeof(areas)/sizeof(int));
	printf("The first area is %d, the 2nd %d.\n",
			areas[0],areas[10]);
	printf("The size of a char: %ld\n",sizeof(char));
	printf("The size of name (char[]): %ld\n",
			sizeof(name)/sizeof(char));

	printf("The size of full_name (char[]): %ld\n",
			sizeof(full_name));
	printf("The number of chars: %ld\n",
			sizeof(full_name) / sizeof(char));
	// !!!其中full_name未设置null结尾
	printf("name=\"%s\" and full_name=\"%s\"\n",
			name, full_name);

	// test 证明了gcc把未初始化的地方初始为0
	printf("the char after the full_name(shuold be error):%c\n",full_name[12]);

	// 用 int 存储字符串
	printf("interg=%X\n", interg);
	printf("inter=\"%s\"\n", &inter);
	printf("interg=\"%s\"\n", interg);
	return 0;
}

重点在于

	char full_name[] = {
		'Z', 'e', 'd',
		' ', 'A', '.', ' ',
		'S', 'h', 'a', 'w'
	};
	unsigned int interg[2];
	interg[0] = '\0' * 0x01000000 + 'A'*0x00010000 + 'B' * 0x00000100 + 'C' * 0x00000001;
	unsigned int inter = interg[0];

可以看到full_name字符串初始化的时候是没有null结尾的,如果的vc中编译并以字符串形式输出的话会跟上乱码

interg的数组第一个元素中我分别在四个字节中放入了‘\0'(即0)、'A'、'B'、’C',第二个元素未初始化。

inter中放的是同样的数字。

输出如下:

The size of an int: 4
The siez of areas (int[]):20
The number of ints in areas: 5
The first area is 10, the 2nd -1493946707.
The size of a char: 1
The size of name (char[]): 4
The size of full_name (char[]): 11
The number of chars: 11
name="Zed" and full_name="Zed A. Shaw"
the char after the full_name(shuold be error):
interg=6EB11E70
inter="CBA"
interg="CBA"

可以看到以字符串输出的full_name并没有因为无null结尾而输出乱码或错误,在chinaunix论坛上了解到可能是因为gcc将字符串存储区全部初始化为零:

从编译器角度上说, 引用非NULL-Terminal的字符串的动作只能听天由命, 乱不乱码和编译器,OS,运行时机有关。
可能的原因:
VC的DEBUG模式下, 会用xcd(或xcc)来填充未知空间(或待引用空间),做为越界访问的一种检测手段。
出于安全原因, Linux会将未知空间(指Malloc或是程序空间)清, 这个正好起了结束符的使用, 这就是你看到的gcc下引用非null-terminal字串不会乱码的原因。(原帖地址http://bbs.chinaunix.net/thread-4075429-1-1.html)

PS:对于数组的初始化,可以只初始化一个元素,就可以使其他元素为零(Learn c the hard way);

inter以字符串输出的结果是按我赋值的倒序输出的,这个是因为小端的数据存储造成的。

???????????????????????????????

??不过对于interg按十六进制输出的结果不太明白。。。。待解。

???????????????????????????????

这里有一篇说明如何利用这个特性如何判断cpu大端与小端http://www.hztarena.org/Html/soft/201212/1760.html

人家这才是专业的啊。。。。。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值