//省去所有#include指令,环境为x86架构32位操作系统下。
3.解释程序的运行结果。
void func(char *a)
{
printf("%lu\n", sizeof(a));
printf("%lu\n", strlen(a));
}
int main(int argc, char *argv[])
{
char a[] = “hello world”;
func(a);
printf("%lu\n", sizeof(a));
printf("%lu\n", strlen(a));
return 0;
}
func()函数中打印输出a的大小和长度,此时的a是一个char类型的指针。所有类型的指针在32位上为4B,在64位上8B。所以输出4 11。
main()函数中也是打印输出a的大小和长度,此时的a是一个char类型的一维数组。所以输出12 11。
//由于博主在64位机上编译的,所以第一个数输出的是8。
6.阅读以下代码:
int main(int argc, char *argv[])
{
int a[3][4];
printf("%p%p%p%p%p%p\n", &a[0][0], a[0],
a, a[0]+1, a+1, a[1]);
return 0;
}
若 a[0][0]的地址为 0x00000000,求程序输出的结果:
&a[0][0]=a[0]=a,
a[0]+1=a[0][1],
a+1=a[1][0]=a[1],
所以输出3个0x00000000,0x000000004,两个0x00000010。
10.这三个指针有什么区别?
int a = 3;
const int *p1; //不能用p1修改它只想的值
int const *p2; //同上
int * const p3 = &a; //p3指针不能指向别处
如果被指物是常量,关键字和类型可互换。即:const * 常量等价于* const 常量。
扩展:
int ** const p :p为指向int指针的常量指针,p不可修改。
int const **p:p为指向int指针的常量指针,**p不可修改。
int * const *p:p为指向int指针的常量指针,*p和p都不可修改。
14.实现一个函数,该函数将字符串中的字符’‘移
到串的前部分,前面的非’‘字符后移,但不能
改变非’‘字符的先后顺序。函数返回串中’'的
数量。如:
输入串:abcde*12
输出串:*****abcde12
函数返回值为 5。
int swap(char p)
{
int len=strlen§;
int i,j,t=0;
for(i=len-1;p[i]!=’’;i–)
j=i;
for(;i>=0;i–)
if(p[i]!=’’)
p[j–]=p[i];
while(j>=0)
{
p[j–]=’’;
t++;
}
return t;
}
从串尾遍历找到最后一个*,设置两个flag指向它,依次遍历覆盖,最后补上相应个数的*。
- 下面代码会输出什么?
int main(int argc, char argv[])
{
int a = 10, b = 20, c = 30;
printf("%d %d\n", b = bc, c = c*2) ;
printf("%d\n", printf("%d ", a+b+c));
return 0;
}
printf返回参数个数,栈由后往前运算,所以输出1200 60,1270 5。
4.请解释下面代码的输出结果。
size_t q(size_t b)
{
return b;
}
size_t (*p(char *str))(size_t a)
{
printf("%s\n", str);
return q;
}
int main(int argc, char *argv[])
{
char str[] = “XiyouLinuxGroup”;
printf("%lu\n", p(str)(strlen(str)));
return 0;
}
函数指针:size_t(*p)(size_t x)。
指针函数:int *p(char *str)。
返回值为函数指针的函数:size_t (*p(char *str))(size_t a)。
第二个q是一个指向第一个q的指针。所以输出xiyoulinuxgroup ,15。
- 以下程序运行结果是什么?
int main(int argc, char *argv[])
{
int nums[5] = {2, 4, 6, 8, 10};
int *ptr = (int *)(&nums+1);
printf("%d, %d\n", *(nums+1), *(ptr-1));
return 0;
}
ptr指向nums的下一个内存地址,(nums+1)=a[1],*(ptr-1)=a[4]。所以输出4,10。
13.观察程序的运行结果,说明出现这种情况的原因。
int main(int argc, char *argv[])
{
char str[512];
int i;
for (i = 0; i < 512; ++i)
{
str[i] = -1 - i;
}
printf("%lu\n", strlen(str));
return 0;
}
-255的二进制数为100…000100000000,char是一个字节,所以为0。即数组256个元素为0,故strlen(str)=255。
- 请修改下面的 swap 函数,使得既可以交换 int 类
型的参数,也可以交换 double 类型的参数。
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
1.宏定义,
2.+参数。
1.#define swap(a,b) ((a)=(a)+(b),(b)=(a)-(b),a=(a)-(b))
2.void swap(int *a,int *b,int size)
{
char t[8];
memcpy(t,a,size);
memcpy(a,b,size);
memcpy(b,t,size);
}
4.下面是一个c语言程序从源代码到形成可执行文件的过程,请解释图中的ABCD分别表示什么,在每个阶段分别完成了什么工作?
A:编辑预处理-----读取c源程序,对其中的伪指令和特殊符号进行处理。
B:编译阶段--------通过词法、语法分析,在确认所有的指令都符合语法规则后,将其翻译成等价额汇编语言。
C:汇编过程--------把汇编代码翻译成目标机器指令。
D:链接程序--------(目标文件并不能立即被执行,须经链接文件的处理)将有关的目标文件彼此相关联。
静态链接—将连接库的代码复制到可执行程序中,是可执行程序体积变大。
动态链接—需要的代码放到一个共享对象中,共享对象映射到进程虚拟地址空间,链接程序记录可执行程序捡来要用到的代码信息,以此信息迅速定位相应的代码片段。
- 谈谈你对 main 函数的理解,可以从参数、返回值等角度分析。
int main(int argc, char argv[]){/…*/}
程序由主函数开始运行,由主函数结束,主函数可调用任何函数,任何函数都不可以调用主函数。
argc:参数的个数。argv[]:是一个字符指针数组,每一个元素指向一个字符串。argv[0]:指向程序的路径名,argv[1…]:指向第n个参数对应的字符串。
8.分析以下函数,给出f(2018)的值,推测并验证函数的作用。
int f(unsigned int num)
{
for(unsigned int i=0;num;i++)
num &= (num-1);
return i;
}
计算无符号整数的二进制数中1的个数。
13.判断以下代码是否存在问题,如果有请找出并找做适当的修改。
typedef strut a
{
char name[100];
int num;
}A;
void func(A *a)
{
a=(A *)malloc(sizeof(A));
strcpy(a->name,“xiyoulinuxgroup”);
a->num=2018;
}
int main(int argc,char *argv[])
{
A *a;
func(a);
printf("%s %d\n",a->name,a->num);
return 0;
}
改法1:
//声明结构体同题
A* func(A *a)
{
//同题
return a;
}
int main()
{
A *a;
a=func(a);
//同题
}
改法2:
//声明结构体同题
void func(A **a)
{
*a=(A *)malloc(sizeof(A));
strcpy((*a->name),"…");
(*a->num)=…;
}
int main()
{
A *a;
func(&a);
//同题
}
*第一个博客就这么多了,以后会加油的 *