1.下面程序段运行结果为()
int a[3][3] = {9,8,7,6,5,4,3,2,1},*p = a[1] + 1;
printf("%d\n",p-*a);
解析:
二维数组与指针的关系:
*a = *(a+0)+0,可以指二维数组a的首地址,也可以指第0行元素的首地址,也可以指第0行第0列这个元素的地址,也就是9这个元素在内存里的地址。
*(a+1) ,指第1行元素的首地址,等价于 *(a+1)+0,也就是第1行第0列元素的地址。
a[1],指第1行元素的首地址,等价于*(a+1)+0,也可以指第1行第0个元素的地址。
a[1]+1,也就等价于*(a+1)+1,指代的是第1行第1列元素的地址。
综上所述:p - *a为两个5和9两个元素的地址差,答案为4。
如果我们打印p的值发现为8191488,打印*a的值,发现为8191472。差为16,但如果输出p - *a的值,为4。这是因为这里是按字节编址的,在打印地址的时候,我们才看到了其对应的地址,相差为16个字节,一个int型变量占4个字节,正好对应4个。打印地址差的时候,输出的是4个sizeof(int)这么大的地址空间。所以这个答案输出的是4,而不是16。
2.下面说法正确的是()
A.
char *p = "ABCD"; printf("%c",*p+=1);的结果为B
B.
char p[]="ABCD"; printf("%c",*p++);的结果为A
C.
char p[]="ABCD"; printf("%c",*s++);的结果为B
D.
char *p="ABCD"; printf("%c",*p++);的结果为A
解析:
1.字符指针和字符数组的区别和联系
字符指针和字符数组变量均储存在栈里;其对应的字符串,作为常量储存在常量区。
区别:
字符指针定义的字符串不能直接进行字符串内容的修改,而字符数组可以直接对字符串的内容进行修改
字符指针不能将对应的字符串从常量区拷贝到栈里进行修改;而字符数组可以将字符串的内容从常量区拷贝到栈内进行修改。
例如:
char *p = "ABCD";
printf("%c",*p+=1);
这种写法是错误的,因为它企图更改字符指针所指向的字符串的内容。
char p[] = "ABCD";
printf("%c",*p+=1);
这种写法是正确的,因为我们可以修改字符数组对应的内容。他会输出A的ascii码+1对应的字符B。
字符指针可以直接使用这一指针来对指针进行指针的+,-等操作;不能直接使用以字符数组数组名为地址的指针进行指针的+,-操作。
例如:
char* p = "ABCD";
printf("%c",*(p+=1));
这将输出B,因为可以直接对字符指针p进行+,-等操作。
取出的是与A这个字符相邻的后一个字符,也就是B的地址,然后取其中的内容进行输出,为B。
char p[] = "ABCD";
printf("%c",*(p+=1));
这个会报错,因为不可以直接拿字符数组的名称p,将p这个指针进行+,-操作。这是不行的。
但是怎么做就可以了呢?
char p[] = "ABCD";
char *s = p;
printf("%c",*(s+1));
这样就可以了,取一个字符指针s指向字符数组p的首地址。然后修改s指针就可以了。
我们看一下如下的代码:
char p[] = "ABCD";
char *s = p;
printf("%d\n",s);
printf("%d",p);
输出均为8191507,证明s和p的值相同,这是因为它们都指向了‘A’这个元素的地址。
char p[] = "ABCD";
char *s = p;
printf("%d\n",&s);
printf("%d",&p);
return 0;
输出为:
8191504
8191515
我们可以看到,虽然s和p的值相同,但是它们并非为同一块存储空间,因为它们的类型不同,一个是字符指针,一个是字符数组,是不一样的,只是它们的值相同,仅此而已。(当然,s和p所对应的两块存储空间都位于栈内)。
这里值得注意的是,极容易被迷惑的一点是,*(p+1)这不算对p这个指针进行了+,-操作。
2.*和++的运算
*和++的运算优先级相同,但是遵循右结合。
也就是说:
*w++; //右结合,相当于*(w++)
++*w; //右结合,相当于++(*w)
*p++和 *(p++)的辨析:
这两个比较特殊,有一个压倒一切的原则,++运算符要整个表达式运算完了才运算。
所以说 *p++和 *(p++)都是一样的:先提取p指向的对象值,然后再对p做++运算,指向下一个存储单元的对象。
所以再回到这道题目:
A选项中,*的优先级高于+=,企图对字符指针所指向的字符串直接进行内容的修改,这是不对的,会报错。
B选项中,p++企图直接对字符数组名p的指针进行+,-操作,错误,会报错。
C选项中,s为一个字符指针,s++先输出s的值,为A,然后再对s指针加1,由于是字符指针,可以移动。不会报错,但输出的是A,选项说是B,所以C也错误。
D选项中,*p++,先输出p指向的字符的值,再对p指针后移一个存储单元,故输出A,不会报错,所以D选项正确。