目录
- 导读
- 1. 字符数组
- 1.1 字符数组的创建
- 1.2 字符数组的初始化
- 1.3 不同初始化在内存中的不同
- 1.3.1 strlen测试
- 1.3.2 sizeof测试
- 1.3.3 差异原因
- 1.4 字符数组的使用
- 2. 数组越界
- 3. 数组作为函数参数
- 博主有话说
导读
我们在前面讲到了 int 类型的数组的创建和使用:
一维数组和二维数组的使用(int类型)
今天我们来了解字符数组的创建和使用,还会提到关于数组越界的问题和数组作为函数参数的用法。
这里还有个基于数组而制作的小游戏——三子棋,感兴趣的小伙伴可以进去看一下。
1. 字符数组
我们在剖析数据在内存中的存储中介绍到:
字符型数据是以字符的ASCII代码存储在存储单元中的,一般占一个字节。由于ASCII代码也属于整数形式,因此在C99标准中,把字符类型归纳为整型类型中。
C语言中没有字符串类型,也没有字符串变量,字符串是存放在字符型数组中的。
1.1 字符数组的创建
用来存放字符数据的数组是字符数组
一维数组:
char arr[10];//一维数组
// 定义了一个大小为10的字符数组
二维数组:
char arr[3][5];
//创建一个3行5列的二维字符数组
1.2 字符数组的初始化
数组在创建的时候如果想不指定数组的确定的大小就得初始化。数组的元素个数根据初始化的内容来确定。
char arr1[3] = {'a',98, 'c'};
char arr2[] = {'a','b','c'};
char arr3[] = "abc";
char arr[3][10] = {"hello", "world", "c"};
1.3 不同初始化在内存中的不同
但是对于下面的代码要区分,内存中如何分配。
char arr2[] = {'a','b','c'};
char arr3[] = "abc";
1.3.1 strlen测试
我们可以用strlen函数来进行测试,strlen函数是用来计算字符串的长度的,计算的是实际长度,不包括 ’ \0 ’ 在内
int main()
{
char arr2[] = { 'a','b','c' };
char arr3[] = "abc";
int len1 = strlen(arr2);
int len2 = strlen(arr3);
printf("arr2字符串长度:%d\narr3字符串长度:%d\n", len1, len2);
return 0;
}
可以看到第一个和第二个字符串长度的差异,这就是两者的区别
1.3.2 sizeof测试
int main()
{
char arr2[] = { 'a','b','c' };
char arr3[] = "abc";
int sz1 = sizeof(arr2);
int sz2 = sizeof(arr3);
printf("arr2字符串大小:%d\narr3字符串大小:%d\n", sz1, sz2);
return 0;
}
1.3.3 差异原因
arr2[] 和 arr3[] 存储的东西是相同的,也就是一组字符的集合,但是它们在内存中存储的方式不同,这也就导致了它们在使用上的一些细微差别。
- 对于arr2[]来说,它是一个字符数组,也就是一组字符的集合,每个字符都占用一个字节的空间。在内存中,它是连续存储的,因此每个字符都有自己的地址。
- 对于arr3[]来说,它是一个以null结尾的字符串,也就是一组字符的集合,每个字符仍然占用一个字节的空间。但是,在内存中,它不同于arr2[],它会在字符串的结尾处添加一个null(‘\0’)字符来表示字符串的结束。因此,在内存中,它需要额外的一个字节来存储null字符,也就是说,字符串"abc"在内存中占用4个字节的空间。
1.4 字符数组的使用
一维字符数组:
int main() {
char name[] = { 'J', 'o', 'h', 'n', '\0' }; // 注意要以 '\0' 结束
int length = sizeof(name) / sizeof(name[0]); // 计算数组长度
for (int i = 0; i < length; i++)
{
printf("%c ", name[i]);
}
return 0;
}
二维字符数组:
int main() {
// 定义二维字符数组
char arr[3][10] = { "hello", "world", "c" };
// 输出二维字符数组
for (int i = 0; i < 3; ++i) {
printf("%s\n", arr[i]);
}
return 0;
}
2. 数组越界
数组的下标是有范围限制的。
数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,
所以程序员写代码时,最好自己做越界的检查。
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i <= 10; i++)
{
printf("%d ", arr[i]);//当i等于10的时候,越界访问了
}
return 0;
}
这种问题会导致程序出现运行时错误,通常会导致程序崩溃、异常或错误的输出。
3. 数组作为函数参数
往往我们在写代码的时候,会将数组作为参数传个函数
比如:我要实现一个冒泡排序函数
判断下面代码是否能够实现排序
void bubble_sort(int arr[])
{
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
bubble_sort(arr);//是否可以正常排序?
int i = 0;
for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}
结构并没有帮助我们实现排序,我们来进入调试查看
查看两个值:
接下来进入排序函数:
调试之后可以看到bubble_sort 函数内部的sz 是1,原因就在于我们传递过去的是数组的首元素地址,bubble_sort 函数内部的sz计算的也仅仅是首元素的大小,所以正确代码应该为:
void bubble_sort(int arr[], int sz)//参数接收数组元素个数
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
博主有话说
关于更多的数组对于sizeof和strlen函数传参的问题可以看——不同的数组传参在sizeof和strlen中的不同
今天就到这里,关注博主查看更多内容