快捷搜索: 王者荣耀 脱发

老生常谈:char*,char[],strncat,strcpy

写项目的时候又被最基础的 char* , char[] , strncat , strcpy卡了一会,太久没碰老是搞混,索性在这里做个笔记:

char* ,const char*,const char* const

const char* str1 = "abc";
	// char* str1="abc";
	// 有些编译器允许上面这样子写
	const char* const str3 = "abc";
	// str3 = "def";  错误!!!str3指针不可改变指向!!
	printf_s("st1:%p    str3:%p
", str1, str3);
	// st1:012E8B30    str3:012E8B30
const char* str1 = "abc";

在这句里,“abc”,做了3件事:

  1. 申请了内存(全局变量区)
  2. 在字符串尾部添加了’/0’(sizeof(“abc”)因此是4,strlen(“abc”)是3,strlen不统计’/0’)
  3. 返回了字符串的地址,返回类型是const char*,这里赋值给了str1

所以,const char* str1=“abc” 这句话是正确的(编译器不同,有时需加上const关键字,因为数组名退化为的是常量指针)。 如果想限定str1指向,const char* const str3 = “abc” 这样写。 而正因为“abc”申请区域是常量存储区,很清楚看到printf_s(“st1:%p str3:%p ”, str1, str3);的地址是一样的。

分配区域是常量存储区!!!

char*,char[]

const char* str1 = "abcdef";
	cout << strlen(str1)<<endl;      // 6
	cout << sizeof(str1) << endl;    // 4
	char str2[7] = "abcdef";
	cout << strlen(str2)<<endl;      // 6 
	cout << sizeof(str2) << endl;    // 7

	printf_s("st1:%p    str2:%p
", str1, str2);
	// st1:00F48BD0    str2:00BEFA3C

主要注意的就是,“abcdef”是一个常量,

char str2[10] = "abcdef";

“abcdef”先会在常量存储区存下来,然后会因为要赋值给str2,会在栈中开辟一段内存,内存大小为7个节点(char数组后会自动加一个’’),然后又有一个"abc"被保存在栈中。 因此str1和str2地址是不一样的。

strncat(),strcpy()

strncat()主要功能是在字符串的结尾追加n个字符。 strcpy是一种C的标准库函数,strcpy把**含有’’*的字符串复制到另一个地址空间,返回值的类型为char。

结合以上:char*,char[]的特性:

char *str1="abcd";
	// const char*str1="abcd; 等价
	char str2[20] = "1234";

	strncat(str1, str2, 4);

像是某些版本VS或者DEV这样子是不会报错,但是是不可行的:首先,str1指向的"abcd"的地址是在常量存储区的,在栈存储的仅仅是指向该区的地址,是无法对str1指向的常量区("abcd"的地址)进行修改。

char *str1="abcd";
	char str2[] = "1234";

	strncat(str2, str1, 4);
	printf("%s
", str2);

这样子反过来就可以了。 strcpy()同理。

经验分享 程序员 微信小程序 职场和发展