一些C语言指针的经典题目。
1.下列程序的输出结果
#include<stdio.h>
#include<stdlib.h>
intmain()
{
int i=11;
int const *p=&i; //指向常量的指针,指针指向的值不能改变,但是可以改变指针的指向。
p++; //指针指向了一个不确定的内存空间。
printf("%d\n",*p);
return 0;
}
解答:程序运行结果为一个不确定的值。
2.下列代码合法的有
intf()
{
int *a=new int(3);
return *a;
}
合法,返回的值为3.
vector<int>f1()
{
vector<int>v(3);
return v;
}
合法
int*f2()
{
int a[3]={1,2,3};
return a;
}
不合法,a是定义在函数内部的,函数结束后空间就释放了。
voidf3(int *ret)
{
int a[3]={1,2,3};
ret=a;
return;
}
不合法,指针ret最终还是被释放了。
3.下面程序的输出是
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string>
usingnamespace std;
char*f(char *str, char ch)
{
char *it1 = str;
char *it2 = str;
while(*it2 != '\0')
{
while(*it2 == ch)
{
it2++;
}
*it1++ = *it2++;
}
return str;
}
int main(int argc, char* argv[])
{
char *a = new char[10];
strcpy(a, "abcdcccd");
cout<<f(a, 'c');
return 0;
}
解答:abcdcccd
4.指针形参经典问题
#include<stdio.h>
#include<stdlib.h>
#include<string>
voidGetMemory(char * p,int num)
{
p=(char*)malloc(num);
}
intmain()
{
char*str=NULL;
GetMemory(str,100);
strcpy(str,"hello");
printf("%s\n",str);
return0;;
}
解答:程序结果出现了内存错误。参数传递是值传递,函数中为形参指针开辟了空间。单但是实际上没有为实参指针开辟空间。
解决方法:
(1)传递指针的指针
void GetMemory(char **p,int num)
{
*p=(char*)malloc(num);
}
int main()
{
char *str=NULL;
GetMemory(&str,100);
strcpy(str,"hello");
printf("%s\n",str);
return 0;;
}
(2)
char *GetMemory(char*p,int num)
{
p=(char*)malloc(num);
return p;
}
int main()
{
char *str=NULL;
str=GetMemory(str,100);
strcpy(str,"hello");
printf("%s\n",str);
return 0;;
}
Tips:
(1) 变量做实参时,传值无法改变实参,传指针和引用可以改变实参。传指针的指针或者指针的引用才能改变指针。
(2) C++中向函数中传递指针和传递指针的引用的区别:
如果是传递指针,那么会先复制该指针,在函数内部使用到的是复制后的指针,这个指针与原来的指针指向相同的地址,如果在函数内部将复制后的指针指向了另外的新的对象,那么不会影响原有的指针。所以要在函数中改变指针,必须传递指针的指针或者指针的引用。
5.返回引用
int x=0;
int &a(int &i)
{
i=-1;
return x;
}
void main()
{
int j=10;
a(j)=100;
}
结果:j=-1,x=100.
6.下面程序的输出
#include<stdio.h>
int main(void)
{
inta[5][10];
printf(“%d,%d,%d”,a,a+1,&a+1)
}
分析:
a是指int a[10]的类型,&a是指a[5][10]的类型。
指针运算的1代表的是指针类型的长度,因此a+1和&a+1中的1代表的长度分别为
4*10 和4*5*10。
假设a 的首地址为1310392,
则a+1为 1310432,
&a+1为 1310592。
7. 定义一个宏,求出给定结构中给定成员的偏移量
#define OFFSET(TYPE,MEMBER)(size_t)(&(((TYPE*)0)->MEMBER))
把0地址转化为TYPE结构的指针,然后读取该结构中MEMBER成员的指针,并且将其强制转换为size_t类型。
8.以下代码在低位优先平台的输出结果
#include<stdio.h>
int main()
{
int a[5]={1,2,3,4,5};
int *ptr1=(int *)(&a+1);
int *ptr2=(int *)((int)a+1);
printf(“%x,%x”,ptr1[-1],*ptr2);
}
&a代表的是整个数组,a代表数组的第一个元素。
(1) ptr1=(int*)(&a+1),ptr1指到了数组的末尾,
ptr1[-1]向低地址移动4个字节,为a[4]=5。
(2) ptr2=(int*)((int)a+1)
a已经强制转换成了整形,a+1已经不是指针运算了,(int*)((int)a+1)指向首地址的下一个字节。
内存低地址 内存高地址
01 00 00 00 02 00 00 00 03 00 00 00
则(*ptr2)=20 00 00 00