一、字符数组
#define MAX 100
#define MSG "How are you"
void test_char_array()
{
/**
* 初始化指定大小数组存储字符串
*
* 指定数组大小时,至少比字符串长度多1,为的是容纳空字符;
* 字符数组中未被使用的元素自动初始化为空字符'\0';
*/
const char str[MAX] = MSG;
/**
* 初始化自动大小数组存储字符串(编译器自动计算)
*/
const char s1[] = MSG;
/**
* 初始化指针指向字符串
*/
const char *s2 = MSG;
printf("address of string \"MSG\" : %p\n", MSG);
printf("address of str : %p\n", str);
printf("address of s1 : %p\n", s1);
printf("address of s2 : %p\n", s2);
printf("address of string \"How are you\" : %p\n", "How are you");
}
输出:
address of string "MSG" : 0x10bdfddd3
address of str : 0x10bdfdf40
address of s1 : 0x10bdfdfa4
address of s2 : 0x10bdfddd3
address of string "How are you" : 0x10bdfddd3
Tips:
* 字符数组和字符指针的区别:
* 数组名是常量,指针名是变量;
* 两者都可以用数组表示法: s1[1],s2[1]
* 两者都可以加法操作: *(s1+1),*(s2+1)
* 只有指针可以自增操作: s2++,++s2
*
* 在静态内存中:
* 都会为字符串常量开辟空间;
* 在栈内存中:
* 为数组开辟的是字符串常量长度大小的空间,并将静态内存中的字符串拷贝至数组中;
* 为指针开辟的指针类型大小的空间,并将静态内存中字符串的首地址存储在指针变量中;
*
* 初始化字符数组是把静态内存中的字符串拷贝到数组中;
* 初始化字符指针是把字符串的地址拷贝给指针;
二、字符串数组
void test_string_array()
{
/**
* 二维数组
*/
char fruit1[3][7] =
{
"Apple",
"Pear",
"Orange"
};
printf("%s\n", fruit1[0]);
/**
* 指针数组
*/
char* fruit2[3] =
{
"Apple",
"Pear",
"Orange"
};
printf("%s\n", fruit2[0]);
}
Tips:
* fruit1可以理解成矩形二维数组,每行长度相同;
* fruit2可以理解成不规则二维数组,每行长度不同;
*
* 如果要显示一系列待显示的字符串,则使用指针数组,因为它比二维数组效率高;
* 但是指针数组中的字符串常量无法更改,因为指针指向的是静态内存中的字符串,静态内存中的值无法更改;
*
* 如果要改变字符串,或者为字符串输入预留空间,则使用二维数组;
* 因为数组中存储的是静态内存中字符串的副本,可以更改副本;
三、理解字符指针
void test_char_ptr()
{
const char* msg = "Don't be a fool";
const char* copy;
copy = msg;
printf("&msg = %p, msg = %p, *msg = %s\n", &msg, msg, msg);
printf("© = %p, copy = %p, *copy = %s\n", ©, copy, copy);
}
输出:
&msg = 0x7ffee5a0a558, msg = 0x10a1f5dfd, *msg = Don't be a fool
© = 0x7ffee5a0a550, copy = 0x10a1f5dfd, *copy = Don't be a fool
Tips:
* 区分三个概念:
* 指针变量的地址:&msg,©
* 指针变量的值:msg,copy
* 指针变量指向的值:*msg,*copy