------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
黑马程序员-iOS基础-C语言基础(四)
内存剖析、数组、字符串
一、C语言内存剖析
1)进制
定义:进制是计算机的计数方式,是数值的表示形式。
进制的种类:二进制、八进制、十进制、十六进制。。。(前四种要掌握)
占位符:
%d/i 十进制带符号整数,%u不带符号
%c 字符
%p 地址
%f 小数
%o 八进制整数
%x 十六进制整数
%s 字符串
%e 以标准指数形式输出单、双精度数,小数6位
注:没有二进制数字的占位符
进制转换:
二进制转十进制
十进制转二进制
以上两种要掌握,其他不做强制要求
不同类型值的取值范围
2) 类型说明符
作用:修饰基本数据类型(一般都是int)
类型
1>short
2个字节,占位符%d
short int == short
2>long
扩充基本数据类型的存储空间
long int<=>long 内存占8个字节
占位符用%ld,数值后面一般加一个l
64位系统下
long long int == long long 也是8个字节,占位符用%lld,数值后面一般加ll
3>signed
signed int == signed
有符号
4>unsigned
unsigned int == unsigned
无符号,占位符%u
最高位作为数字计算
short/long可以和signed/unsigned组合使用
不同类型所占用的存储空间
3)位运算
1>按位与&
只有对应的两个二进位均为1时,结果位才为1,否则为0
二进制中,与1相&就保持原位,与0相&就为0
作用:检查某一位的值是1还是0
2>按位或|
只要对应的二个二进位有一个为1时,结果位就为1,否则为0
3>按位异或^
当对应的二进位相异(不相同)时,结果为1,否则为0
规律
相同整数相^的结果是0。比如5^5=0
多个整数相^的结果跟顺序无关。比如5^6^7=5^7^6
因此得出结论:a^b^a = b
4>按位取反~
对整数a的各二进位进行取反,符号位也取反(0变1,1变0)
5>左移<<
把整数a的各二进位全部左移n位,高位丢弃,低位补0。左移n位其实就是乘以2的n次方
由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性
6>右移>>
把整数a的各二进位全部右移n位,保持符号位不变。右移n位其实就是除以2的n次方
为正数时, 符号位为0,最高位补0, 为负数时,符号位为1,最高位是补0或是补1,取决于编译系统的规定
7>练习:变量值交换位运算方法
a=a^b;
b=a^b;
a=a^b;
此方法不便理解,背下即可
8>练习:写一个函数,用来输出整数在内存中的二进制形式
#include <stdio.h>
//写一个函数,用来输出整数在内存中的二进制形式
void printBinary(int number);
int main()
{
/* code */
printBinary(9);
return 0;
}
void printBinary(int number)
{
int temp=sizeof(number)<<3;
for(int i=0;i<temp;i++)
{
printf(number>>(temp-1-i) & 1 );
if((i+1)%4==0)
{
printf(" ");
}
}
printf("\n");
}
4)char类型
内存存储细节:ASCII单字节表中的数值
常见错误:
char c = A;
char c = "A";
char c = 'ABCD';
char c = '男';
在-128~127范围内,char类型可以作为整型使用
char类型占位符:%c
转义字符:
二、C语言数组
数组就是存储一组数据的数据类型, 只能存放一种类型数据, 数组里的数据叫元素
数组的定义格式: 类型 数组名[元素个数];
定义方法1:最复杂
int ages[5];
ages[0]=19;
ages[1]=19;
ages[2]=28;
ages[3]=27;
ages[4]=26;
定义方法2:定义时赋值
int ages[5]={19,19,28,27,26};
定义方法3:不全部赋值
int ages[5]={19,19};
定义方法4:只给最后几个赋值
int ages[5]={[3]=19,[4]=19};
定义方法5:无个数
int ages[]={19,19,28,27,26};
数组的操作
遍历:按顺序查看数组的每一个元素
for(int i=0;i<5;i++)
{
printf("ages[%d]=%d\n",i,ages[i]);
}
使用注意:
错误写法
1.
int ages[];
2.只能在定义数组时初始化
int ages[5];
ages={10,11,12,15};
3.变量不能作为数组的长度值,未初始化的值是不确定的
int count=5;
int ages[count];
如果在定义数组的同时进行初始化,数组元素个数必须是常量
计算数组长度
方法,用sizeof
int ages[]={13,35,24,57,84,33,12};
int count=sizeof(ages)/sizeof(int);
for(int i=0;i<count;i++)
{
printf("ages[%d]=%d\n",i,ages[i]);
}
内存存储细节
数组元素在内存的存放与基本数据类型的存储是反过来的
越在前面的元素地址越小
数组地址就是第一个元素的地址
数组名就代表数组的地址
数组和函数
数组作为函数参数可以省略元素个数
数组作为函数参数传递的是数组的地址,修改形参的值会改变数组的值
基本数据类型调用是值传递
数组当作函数参数传递时,会当作指针变量来使用,指针在64位编译器环境下,占用8个字节
练习:写一个函数,找出整型数组元素的最大值
#include <stdio.h>
//写一个函数,找出整型数组元素的最大值
int maxOfArray(int array[],int length)
{
int max=array[0];//定义一个变量存储最大值
for(int i=1;i<length;i++)
{
if(array[i]>max)//如果当前元素大于max,就用当前值覆盖max
{
max=array[i];
}
}
return max;
}
int main()
{
/* code */
int ages[]={11,23,46,767,232,1213,45,90};
int length=sizeof(ages)/sizeof(int);
int max=maxOfArray(ages,length);
printf("Max is %d\n",max);
return 0;
}
二维数组
格式:数据类型 数组名[a][b]
如:int ages[3][5]={
{123,45,43,23,8},
{34,67,9,21},
{34,67,99,12,0}
};
二维数组是一个特殊的一维数组:它的元素是一维数组
存储
存储大小
存储结构和顺序
存储地址问题
初始化
举例
int a[3][4] = {1,2,3,4,5,6};
int a[3][4] = {{},{},{}};
数组元素简单访问
int a[][5] = {3,21,31,2,32,1};
注意错误:
int a[3][4];
a[3] = {};
三、字符串
字符串定义
由多个字符组成的数据
如:char name[10]="jack";
内存存储细节:字符+\0
\0的ASCII值是0
字符串的初始化
char a[] = “123”; 和 char a [] = {'1','2','3'};的区别,可以比较大小
“123”其实是由'1'、'2'、'3'、'\0'组成
“123”的存储分布
字符串的输出”%s”,'\0'是不会输出的
\0的作用
如果用%s输出一个普通数组,将会输出其地址之后所有的信息直到第一个"\0"为止
strlen
计算字符串字符数的函数
int size=strlen(name);
头文件string.h
注意
计算长度不包含\0
计算的是字符数,不是字数。一个汉字三个字符
从传入的地址开始计算字符个数,直到\0为止
练习:写一个函数char_contains(char str[],char c),如果字符串str中包含字符c则返回数值1,否则返回数值0
代码如下:
#include <stdio.h>
#include <string.h>
//编写一个函数char_contains(char str[],char c),
//如果字符串str中包含字符c则返回数值1,否则返回数值0
int char_contains(char str[],char c)
{
int length=strlen(str);
for(int i=0;i<length;i++)
{
if(str[i]==c)
{
return 1;
}
}
return 0;
}
int main()
{
/* code */
char name[]="dfdajglajfldaf";
char letter='q';
int result=char_contains(name,letter);
printf("%d\n", result);
return 0;
}
此代码可改写为while函数,并进行精简
字符串数组
使用场合
* 一维字符数组中存放一个字符串,比如一个名字char name[20] = "mj"
* 如果要存储多个字符串,比如一个班所有学生的名字,则需要二维字符数组,char names[15][20]可以存放15个学生的姓名(假设姓名不超过20字符)
* 如果要存储两个班的学生姓名,那么可以用三维字符数组char names[2][15][20]
初始化
char names[2][10] = { {'J','a','y','\0'}, {'J','i','m','\0'} };
char names2[2][10] = { {"Jay"}, {"Jim"} };
char names3[2][10] = { "Jay", "Jim" };