专项小练(五)
字符数组
void main()
{
char w[ ] [10]={"ABCD","EFGH","IJKL","MNOP"},k;
for (k=1;k<3;k++) printf("%s\n",w[k]);
}
操作符
main()
{int i,j,k,a=3,b=2;
i=(--a==b++)?--a:++b;
j=a++;k=b;
printf("i=%d,j=%d,k=%d\n",i,j,k);
}
考查条件表达式、赋值运算符、自增(减)运算符,the C programme-2.12指出:三目运算符优先级高于赋值运算符,低于自增(减)运算符;其中自增(减)运算符、赋值运算符按照从右向左结合规则、等号运算符及三目运算符按照从左向右的结合规则;
向条件表达式中括号内:
–a:2,b:2, 条件为真,执行–a;//b++,b:3,a:1
条件表达式简化为i =a;//即i=1;
j =a++,k=b;//a先赋值再自增,j=1,a=2,k=3;
结合规则不太理解
数组指针
在32位操作系统中,我们定义如下变量 int (*n)[10]; 请问调用函数sizeof(n)大小
考查指针数组、数组指针;“指针数组是数组,数组指针是指针”
C内核解析指针:指针数组实质是一个数组,数组内元素全部是指针变量; 数组指针实质是一个指针,该指针指向一个数组;
区分两者,若核心和星号*结合,表示核心是指针如int (*n)[10];
若核心和中括号[]结合,表示核心是数组,如 int *p[10];
若核心和小括号结合,表示核心是函数;
遇到操作符优先级问题,看优先级高低,其中()、[ ]、->优先级高于星号
故,这里sizeof(n):4
int a[2][3];
int (*p)[3]=a;
int *q=*a;
则能输出a[1][2]的值的语句
A:cout<<*(*(a+1)+2);
B:cout<<p[1][2];
C:cout<<*(q+5);
D:cout<<q[1][2];//erro
先看下二维数组是特殊的一维数组存储方式
第一行: a[0][0] a[0][1] a[0][2]
第二行: a[1][0] a[1][0] a[1][2]
转换成存储形式:
b[0] b[1] b[2]
b[3] b[4] b[5]
看下数组指针(*p)[3],每个数组元素为一个指针变量,该指针变量可指向特定地址,如基础类型变量、数组、结构体等;
A: *(a+1)=a[1]=&a[1][0];//按行形式访问为数组a[1][0]的地址;
(*(a+1)+2)即为指向a[1][2]的地址,故*(*(a+1)+2)即为a[1][2]的值;
B: int (*p)[3],p为数组指针,指向一个 int[3]数组的指针,p=&a[0];
(p+1) = &a[1],p类似数组a行指针的指针,故p[1][2]=*(*(p+1)+2);
C: int *q=*a,*q为数组a的行指针,p=&a[0][0]=a[0];
D: q[1]=*(q+1)为一个int型数据,其后再加上[2]报错;
看个数组指针测试案例
#include<stdio.h>
int main(){
int a[2][3] = {0,1,2,3,4,5};
printf("(q+5):%d\n",*(q+5));//*q为数组a的行指针
/*
//这里浪费了空间,因为(*p)[2]指向的位置没有存储有效数据,
可能出现类似野指针情况,或指向是垃圾的空间为 ;改为如下形式更为合理
int (*p)[2] = a
*/
int (*p)[3]=a;
int *q=*a;
printf("------数组元素地址----\n");
printf("a[0][0]地址:%x\t\n",a);
printf("a[1][0]地址:%x\n",&a[1][0]);
printf("a[1][2]地址:%x\n",&a[1][2]);
printf("a地址:%x\t\n",a);
printf("a+1地址:%x\t\n",(a+1));
printf("-------数组指针元素值-------\n");
printf("p[0]地址:%x\n",p[0]);
printf("p[1]地址:%x\n",p[1]);
printf("p[2]地址:%x\n",p[2]);
printf("q地址:%x\t\n",q);
printf("------数组指针元素长度-----\n");
printf("sizeof(p):%d\n",sizeof(p));//指针变量自身的长度
printf("sizeof(p[0]):%d\n",sizeof(p[0]));//指针变量指针数组空间的长度
printf("sizeof(p[1]):%d\n",sizeof(p[1]));
printf("sizeof(p[2]):%d\n",sizeof(p[2]));//指针为定义空间
/*
程序中(*p)[3] 为行指针 (*p)[0]指向a[0][0]所在的行
(*p)[1]指向a[1][0]所在的行
*/
//数组指针p中元素指向数组a中元素的指针
printf("-----数组指针元素值---------\n");
printf("*(p): %x\n",*(p));
printf("*(p+1):%x\n",*(p+1));
printf("*(p+2):%x\n",*(p+2));
printf("-------按行形式访问原数组的值 --------\n");
//按行形式访问原数组的值
printf("**(p): %d\n",**(p));
printf("**(p+1):%d\n",**(p+1));
printf("**(p+2):%d\n",**(p+2));//指向垃圾值
printf("-----按 列形式访问 --------\n");
//按 列形式访问
printf("*(*(p)+1): %d\n",*(*(p)+1));
printf("*(*(p+1)+1):%d\n",*(*(p+1)+1));
printf("*(*(p+2)+1):%d\n",*(*(p+2)+1));//指向垃圾值
return 0;
}
测试结果
(q+5):5
------数组元素地址----
a[0][0]地址:62fdf0
a[1][0]地址:62fdfc
a[1][2]地址:62fe04
a地址:62fdf0
a+1地址:62fdfc
-------数组指针元素值-------
p[0]地址:62fdf0
p[1]地址:62fdfc
p[2]地址:62fe08
q地址:62fdf0
------数组指针元素长度-----
sizeof(p):8
sizeof(p[0]):12
sizeof(p[1]):12
sizeof(p[2]):12
-----数组指针元素值---------
*(p): 62fdf0
*(p+1):62fdfc
*(p+2):62fe08
-------按行形式访问原数组的值 --------
**(p): 0
**(p+1):3
**(p+2):34
-----按 列形式访问 --------
*(*(p)+1): 1
*(*(p+1)+1):4
*(*(p+2)+1):0
使用指针数组形式访问数组元素可读性太差,且容易出错。
格式化输入
#include <stdio.h>
main()
{
int x, y;
scanf("%2d%*4s%2d",&x, &y);
printf("%d",y-x);
}
C参考文档中c99格式化输入scanf,用于指定经格式转换后的相应输入保存的位置。
/* 按下列分析:
%d :整数
%f :浮点值
%9s :最多有 9 个非空白符的字符串
%2d : 2 位的整数(数位 5 和 6 )
%f :浮点值(数位 7 、 8 、 9)
%*d :不存储于任何位置的整数
' ' :所有连续空白符
%3[0-9] :至多有 3 个十进制数字的字符串(数位 5 和 6 )
%2lc :二个宽字符,使用多字节到宽转换 */
*赋值禁止字符,跳过输入字段,不进行赋值;
%2d:2表示指定最大字段宽度,对输入数据按格式对2位整数作赋值;
字符"23456"不作赋值,故:x=12,y=78;
结构体指针
struct T{
char name[20];
int age;
int sex;
} a[5],*pa=a;
scanf("%s",a[0].name);
scanf("%d", &pa[0].age);
scanf("%d",&(pa->age));
scanf("%d", pa->age);//erro:pa->age表示结构成员,不是地址;
考查结构体数组结构体指针
The C programme指出:结构体数组
struct key{
char *word;
int count;
}x,keytab[],*y;
//x,keytab,y为标签
typedef struct {
char *word;
int count;
}simple;
//key为类型名
它声明了一个结构类型key,并定义了该类型的结构数组keytab,同时为其分配存储空间,数组keytab的每个元素都是一个结构。若未定义为结构名,编译器不会为其分配内存。
结构体指针是一个指针,它指向的这个类型的结构;
题中scanf 输入为变量的地址,而pa->age;表示结构成员,不是地址。
计数法
合法常量
1.234e04
1.234e0.4//erro,e后面的指针部分应为整数
1.234e+4
1.234e0
Cprimer指出:计数方法分科学计数和指数计数法(即e-计数法) , 其中e-计数法如1e4、-1.159e-4,前者表示10000,后者表示-0.0001159;
e后面表示指数部分;
函数指针
指针函数:函数的返回值是一个指针变量;
另C和指针指出:函数指针最常见的用法为作为参数传递给另一个函数和转换表;与其他指针一样,函数指针执行间接访问前必须初始化为指向某个函数。如下,第2个声明创建了函数指针pf,并初始化为指向函数f;
int f(int);
int (*pf)(int) = &f;
int ans;
ans = pf(25);
第二条语句对pf执行间接访问操作,把函数指针转化为一个函数名;
转换表是函数指针数组;
double add(double,double);
double sub(double,double);
double mul(double,double);
//....
double(*open_func[])(double,double) = {add,sub,mul,...};
double result;
result = open_func[oper](op1,op2);
oper_func从数组中选择正确的函数指针,而函数调用操作符将执行该函数;
数据类型转换
main()
{ char
x=040;
printf("%0\n",x<<1);
}
C primer plus指出:
字节(byte)是常用的计算机存储单位,几乎对于所有机器,1个字节均为8位,在衡量存储单位时,这是字节的标准定义。
字(word)是自然的存储单位,对于8位微机,如原始的Apple机,一个字正好有8位。使用80826处理器的早期IBM兼容机是16位机,这意味着一个字的大小为16位。基于Pentium的PC和Macintosh PowerPC中的字是32位。更强大的计算机可有64位甚至更长位数的字。
常说的32位、64位处理器指?
基础数据类型在不同处理器上所在的存储一样吗?
如int类型表示正负整数、0,其数以二进制形式存储即需要将十进制整数转成二进制形式存储,如IBM PC兼容机有16位的字,因此使用16位存储一个int值,取值范围为-32768到32767
32位、64位机器,存储一个int值,取值范围更大;
若整数特别大,可用long或long long
short int类型或简写为short,可能占用比int类型更少的存储空间,用于仅需小数值的场合以节省空间,且它是一种有符号类型;
long int类型或简写为long,可能占用比int类型更多的存储空间,用于使用大数值的场合,且是一种有符号类型;
long long int类型或简写为long long可能占用比long类型更多的存储空间,用于使用更大数值的场合,且是一种有符号的类型;
unsigned int类型或简写为unsigned类型用于使用非负值的场合,与有符号类型的表示范围不通过,如16位的unsigned int取值范围为0到65535,而带符号的int取值范围为-32768到32767,由于指示数值正负的位也被用于二进制,所以无符号可表示更大的数值;
C90中无符号类型增加了unsigned long int、unsigned short int;
C99中增加了unsigned long long int;
关键字signed可与任何有符号类型一起使用,使数据类型更加明确,如 signed short等
处理器作用?存储器作用?整型数据类型int为什么需要占32位存储空间?
整数以二进制数字存储,如整数7,占8位长的字,2^ 2, 2^1,2 ^0 (4+2+1=7)
0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
---|
浮点数表示法将一个数分为小数部分和指针部分浮点数与整数的存储方案不同,如浮点数3.14159,以浮点格式存储实数(十进制版本)
+ | 314159 | 1 |
---|---|---|
+ | 小数部分.314159 | 指数部分x10^1 |
计算机内部存储仍然使用二进制,使用2的幂而不是10的幂;
sd