C语言-字符数组-字符串数组-‘\0‘-sizeof-strlen()-printf()

1.字符数组和字符串数组

字符串数组:字符串数组是字符数组的特殊表达方式,其本质还是一个字符数组。

如char mychar[]="hello",字符串数组中存放的也是一个个的字符,对于字符串数组,在系统中的存储为:'h' ,'e' ,' l', 'l', 'o', '\0' ,其中,'\0'作为字符串结束的标志,最后一个结束标识符‘\0’是系统自动添加的

如char mychar[5]="hello",初始化分配了五个存储空间,系统没有空间在最后加上\0,在内存中就是按照'h' ,'e' ,' l', 'l', 'o'存储的。

(参考https://blog.csdn.net/sjtu_huang/article/details/6533140?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-12.essearch_pc_relevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-12.essearch_pc_relevant

2.关于strlen()函数与sizeof 在字符数组与字符串数组上的使用

明确两点即可:

strlen()是函数,其参数是指针,当字符串数组与字符数组名作为参数时,数组名退化为指针,不再是一个指针常量。strlen()的取值为索引到\0前的字符数。

sizeof不是一个函数,完全是按照字符数组/字符串数组在内存中存储时占用的字节数大小来确定的。

printf()函数与strlen()函数一样,都是以索引到\0作为结束的标志进行结果的输出。

3.对于字符数组/字符串数组,为什么使用strlen()有时结果不对呢,实际大小要不要考虑\0呢?详见下面的注释,列举了几种不同的初始化情况。关键是看,数组在内存中是怎么存储的。

#include <stdio.h>
#include <string.h>

int main(void)
{
	// '\0'是字符(字符串)数组结束的标志。
	//===============================字符数组=======================================
	char mychar1[] = { 'c', ' ', 'b', 'd', 'd', '\0', '\0' };//strlen的结果是索引到\0前面的字符数,strlen是一个函数,其参数是数组转化的指针。

	printf("sizeof mychar1 is %d\n", sizeof(mychar1));// sizeof mychar1 is 7
	printf("strlen of mychar1 is %d\n", strlen(mychar1)); // strlen of mychar1 is 5
	printf("mychar1 is %s\n", mychar1);//c bdd


	char mychar2[] = { 'c', ' ', 'b', 'd'};//这种数据既没有明确大小,mychar2[],也没有给出\0结束标志,用strlen()将会得到错误数据,不能使用strlen()。
	printf("\n");
	printf("sizeof mychar2 is %d\n", sizeof(mychar2));//sizeof mychar2 is 4,sizeof并不是一个函数,其实在输入完数组之后就确定了sizeof的值。
	printf("strlen of mychar2 is %d\n", strlen(mychar2));// strlen of mychar2 is 17,错误结果,因为没有检测到字符的结束标志,
	//而且也没有对字符数组进行初始化,下面逐个输出,看一下这“17”个字符都是什么
	for (int i = 0; i <= strlen(mychar2); i++)
	{
		printf("%c\n", mychar2[i]); //c bd????????c bdd,乱码,

	}
		
	/*可以看出对于这种既没有字符数组结束标志,也没有初始化明确指出字符数组大小的字符数组来说,用strlen()来获取字符数组长的的话是错误的。
	 因为strlen是一个函数,参数是数组名表示的指针,以检索到\0前的字符数作为输出结果,
	 这个数组没有初始化,系统不知道具体大小,也无法给“未初始化”的元素填充为\0,所以用strlen()的时候,系统找不到\0在哪里,也许是为了能保证前面
	 初始化数据的准确性,所以系统向后索引到一定字符数后才停止,但是这也会出现一些乱码。这种情况下使用strlen是错误的。
	*/
	printf("mychar2 is %s\n", mychar2);//c bd烫烫烫烫c bdd,乱码,printf()函数也是按照\0来索引的。




	char mychar3[5] = { 'h', ' ', 't' };//在内存中实际上是'h', ' ', 't' ,'\0' ,'\0' 
	printf("\n");
	printf("sizeof mychar3 is %d\n", sizeof(mychar3));//sizeof is 5,对sizeof来说,\0也要计算进去,因为按照定义就是开辟了5个字节来存储字符,未初始化的系统置为\0。
	printf("strlen of mychar3 is %d\n", strlen(mychar3));//strlen is 3
	printf("mychar3 is %s\n", mychar3);//h t


	char mychar4[4] = { 'c', ' ', 'b', 'd' };//在内存中是'c', ' ', 'b', 'd' 
	printf("\n");//不能使用strlen()函数,计算结果是错误的
	printf("sizeof mychar4 is %d\n", sizeof(mychar4));//sizeof is 4
	printf("strlen of mychar4 is %d\n", strlen(mychar4));//strlen is 15 。strlen结果不准确,因为没有\0索引结束的标志。
	printf("mychar4 is %s\n", mychar4);//c bd烫烫烫烫h t

	
	//char mychar5[4] = { 'c', ' ', 'b', 'd', '\0' };//错误,超出定义的数组大小


	//====================字符串数组=========================
	char mystr1[5] = "hell";//在内存中是'h','e','l','l','\0',系统自动给未初始化的置为\0
	printf("\n");
	printf("sizeof mystr1 is %d\n", sizeof(mystr1));//sizeof mystr1 is 5
	printf("strlen of mystr1 is %d\n", strlen(mystr1));//strlen is 4
	printf("mystr1 is %s\n", mystr1);//hell

	char mystr2[5] = "hello";//在内存中是'h','e','l','l','o',已经全部占满初始化分配的空间,系统不会因为是字符串就自动加上\0
	printf("\n");
	printf("sizeof mystr2 is %d\n", sizeof(mystr2));// sizeof is 5
	printf("strlen of mystr2 is %d\n", strlen(mystr2));//strlen is 20,错误,因为按照初始化定义的来看,没有结束索引的\0
	printf("mystr2 is %s\n", mystr2);//hello烫烫烫烫烫蘦ell,乱码,因为printf()函数也是按照\0索引来输出的,全占满初始化空间但是没有给\0
	printf("mystr2 is %c\n", mystr2);//输出是?,因为mystr2作为printf()函数参数时,退化为指针,输出的是用mystr2地址的ASCII码,在实际应用中没什么意义。

	char mystr3[] = "hello";//对于没有初始化大小的字符串,系统也不知道大小,会在最后自动加上一个\0
	printf("\n");           //在内存中是'h','e','l','l','o','\0'系统在最后自动添加'\0'
	printf("sizeof mystr3 is %d\n", sizeof(mystr3));// sizeof is 6
	printf("strlen of mystr3 is %d\n", strlen(mystr3));//strlen is 5
	printf("mystr3 is %s", mystr3);//hello

	//char mystr3[5] = "hellou";//错误,超出数组大小

	return 0;
}

对于字符串数组来说,如果还有没初始化的空间,系统会置为\0,对于字符串数组来说,如果有空间,系统会”好心地“ 加上一个\0,但是如果没有空间,系统也爱莫能助,比如char a[5]="hello"。

字符串数组常用的初始化方式就是char a[ ]="hello",不指明大小,让系统自动在最后加上一个\0。

对于字符数组来说,系统没有那么热心哈,如果没有规定数组大小,系统是不会在最后给添加\0的,因为系统也不知道哪里是这个数组的结束,初始化了几个字符,系统就认为这个字符数组就是这么大、但是字符串数组就不一样了,有'' 双引号 "作为一个范围的确定!

从上面来看,注意定义字符(串)数组时,给出合适的空间大小,具体要看其在内存中是什么方式存储的,来确定strlen()和sizeof能否有正确的结果。 

//=============20210907后记========又犯错误了=============sizeof不是函数不是函数不是函数!数组名作为参数的时候不视为指针不视为指针不视为指针!!!!!========================================================================

下面看代码!咋就记不住呢,sizeof不是函数不是函数不是函数!

下面看代码!!!!

#include<stdio.h>

void Array(int arr[],int size)
{
	int i = 0;
	for ( i = 0; i < size; i++)
	{
		arr[i] = i;

		//printf("%d\n", arr[i]);
	}

	printf("sizr of arr[size] in Arr(int*) is %d\n", sizeof(arr));
	//注意,sizeof不是函数,当数组名作为其参数的时候,虽然数组名无论是否作为函数参数数组名都是一个指针常量,
	//但是sizeof不是函数!!!sizeof(数组名),得到的是整个数组所占字节的大小,这时虽然数组名仍然是一个指针常量,
	//但是sizeof(数组名)的值确实实际数组的大小,而不是一个指针的大小,这也是数组名只有作为函数参数才退化为指针的一个表现吧。

}

int main(int argc, char* argv[])
{
	int c[] = { 1, 2, 3 };
	int* d = c;
	printf("size of c[] is %d\n", sizeof(c));
	//此情况下数组名是函数main(int,char*)的参数,因此sizeof(c)的大小是4!
	printf("size of d is %d\n", sizeof(d));
	*(c + 1) = 3;
	
	//int s[4] = { 0 };

	Array(c,3);
	return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小哇123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值