数组在内存中
数组存放在内存中的栈上,编译时确定数组的大小,运行时才给其分配内存
数组在内存中连续存放,且由低地址向高地址方向存储数据,栈上的两个变量之间有两个哨位兵(占4字节)进行保护,可以防止数组越界
#include <stdio.h>
int main()
{
int arr[5] = { 12,23,34,45,56 }; //定义一个数组,有5个元素,每个元素都是int型,下标从零到四
printf(" %d %d %d %d %d\n", &arr[0], &arr[1], &arr[2], &arr[3], &arr[4]); //打印各元素的地址
return 0;
}
结果:13629376 13629376 13629380 13629384 13629388 13629392
验证可知,数组在内存中连续存放,每个元素数据类型相同
数组名
像const修饰的变量值不可以改变,也就是说这种变量不能被赋新值,那么他不能做左值,数组名代表数组首元素的首地址,注意不是数组的首地址.即arr等价于&arr[0]
#include <stdio.h>
int main()
{
int arr[5] = { 12,23,34,45,56 }; //定义一个数组,有5个元素,每个元素都是int型,下标从零到四
printf("%d %d\n",arr, &arr[0]); //arr等价于&arr[0]
return 0;
}
结果:17824420 17824420
数组名不能作为左值!数组占据的内存是一个整体,我们只能访问数组的某个元素而不能把数组当成一个整体进行访问,所以我们可以把数组元素当做左值而不能把数组名作为左值。
数组名还有两种情况代表整个数组:
(1)sizeof(arr); //整个数组的字节大小
(2)&arr+1; //数组最后一个元素的后面
字符,字符串
在C语言中,字符是按其所对应的ASCII码来存储的,一个字符占一个字节
字符常量由单引号括起来;字符串常量由双引号括起来 字符常量只能是单个字符;字符串常量则可以含一个或多个字符
字符串最后有隐藏的‘\0’,’\0’是字符串结束的标志
字符串处理函数:
puts 和gets
用于字符串的输入和输出,但由于有printf和scanf,这两个函数并不常用
strcat
strcat(字符数组1,字符数组2) 把两个字符数组中的字符串连接起来
把字符串2接到字符串1的后面,结果放在字符数组1中,调用这个函数得到字符数组1的地址
字符数组1 必须足够大,保证字符数组2 连接进来之后不会溢出
连接前两个字符串最后都有’\0’,连接后,第一个的’\0’会取消,保留第二个字符串后的’\0’.
#include <stdio.h>
#include <string.h>
int main()
{
char str1[30] = { "hello" };
char str2[] = { "world" };
printf("%s\n", strcat(str1, str2));
}
helloworld
strcpy和strncpy字符串复制函数
strcpy(字符数组1,字符串2) strncpy(字符数组1,字符串2)
数组名不能做左值,字符数组名也是数组名,不能把一个字符串直接赋给一个字符数组,也不能将一个字符数组直接赋给另一个字符数组,必须用复制函数进行复制
把字符串2复制到字符数组1中, n表示要复制几个字符
与连接的区别是复制时会覆盖字符数组1 中原有的字符,这也要求字符数组1 足够长
复制时,被覆盖掉的是复制的字符串2 长度的部分,之后的字符仍然保持字符数组1 中原有的
#include <stdio.h>
#include <string.h>
int main()
{
char str1[30] = { "hello" };
char str2[] = { "world" };
printf("%s\n", strcpy(str1, str2));
}
strcmp字符串比较函数
strcmp(字符串1,字符串2)
将两个字符串从左到右逐个字符相比较,直到遇到不同的字符或’\0’为止
若所有字符相同,则认为两个字符串相等
若出现不同字符,则以第一对不相同的字符的比较结果为准
在英语字典中,位置在后面的大,小写字母比大写字母大
两个字符串不能直接进行比较
如
if (str1 < str2)
printf("yes\n");
只能
if (strcmp(str1, str2) > 0)
printf("yes");
相等时 返回0 字符串1>字符串2 返回正整数 字符串1<字符串2 返回负整数
strlen
侧字符串的长度
strlen(字符数组)
函数的值为字符串中的实际长度,不包括’\0’。
strlwr(字符串)转换为小写
strupr(字符串)转换为大写
数组作为函数参数
用数组元素做实参时,向形参变量传递的是数组元素的值,而用数组名做函数实参时,向形参传递的是数组首元素的地址
int max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
int arr[3],m;
printf("input 3 number:\n");
for (int i = 0; i < 3; i++)
{
scanf("%d", &arr[i]);
printf("\n");
m = arr[0];
for (int i = 1; i < 3; i++)
{
if (max(arr[i], m) > m)
{
m = arr[i];
}
}
}
printf("%d\n", m);
}
float average(float aver[10])
{
float sum = 0;
for (int i = 0; i < 10; i++)
{
sum += aver[i];
}
return sum / 10;
}
int main()
{
printf("input 10 grade:\n");
float arr[10];
for (int i = 0; i < 10; i++)
{
scanf("%f", &arr[i]);
}
printf("\n");
float aver = average(arr);
printf("平均成绩为:%f\n", aver);
}
局部变量和全局变量
一个源文件有一个或多个函数组成,函数内定义的变量是局部变量,函数之外的变量是全局变量
全局变量可以为本文件中其他函数所公用,他的有效范围从定义变量的位置开始到本文件结束
变量的存储方式
静态存储方式和动态存储方式
静 程序运行期间由系统分配固定的存储空间的方式
动 程序运行期间根据需要进行动态的分配存储空间的方式
c 语言的存储类别 自动的auto 静态的statis 寄存器的 register 外部的extern
静态的 函数调用后变量的值不消失而继续保留原值,其占用的存储单元不释放
内部函数和外部函数
内部 static 是函数的作用域只局限与所在文件
外部 extern 可以为其他文件调用
szieof 和strlen
两个都用来测试长度,区别我们进行简单的测试
int main()
{
char arr[100] = {" abcdefg" };
printf("%d\n", sizeof(arr));
printf("%d\n", strlen(arr));
}
100
8
不难看出sizeof测出的是数据(或类型)占据的内存单元大小,而strlen测量的是字符串的实际长度
另外,sizeof是运算符而strlen是函数
strlen计算时不算‘\0’