嵌入式入门

C语言代码考评示例

#include<stdio.h>
typedef struct info1
 {
  char *next;           
 }INFO1;
 typedef struct info
 {
  short *next;           
 }INFO2;
 typedef struct info3
 {
 int *next;           
 }INFO3;
 typedef struct info4
 {
  double *next;           
 }INFO4;
 int main(int argc ,char* argv[])
  {
   printf("%d\n",sizeof(INFO1));           
   printf("%d\n",sizeof(INFO2));
   printf("%d\n",sizeof(INFO3));
   printf("%d\n",sizeof(INFO4));           
   return 0;          
  }

你能否得到上述输出结果的原因,试阐述之!

32位机为指针分配4个字节,每个字节8

理论上64位机为指针分配8个字节,每个字节8位,若测试的结果不对应,这可能和编译器有关。一般的编译器都是32位的编译器!所以对编译器分配的空间要视电脑的操作系统和编译器而定。

 (2)#include<stdio.h>
int main(int argc,char *argv[])
{
 char *p="hello world\n";
 printf("%d\n",sizeof(p));
 printf("%d\n",sizeof(*p)); 
 int a[10];
 int *b;
 b=&a;
 printf("%d\n",sizeof(b));
 printf("%d\n",sizeof(*b));  
 getch();   
}

请结合第(1)例子,说明该例输出结果的原理。

 printf("%d\n",sizeof(p));指向的是一个指针,32位编译器为指针分配4个字节

 printf("%d\n",sizeof(*p));指向的指针的首地址,它是一个字符,所以测试结果是1。大家要理解指针的指向问题:一个是指针有指向时,一个是指针无指针时。

(3)

#include<stdio.h>
 typedef struct info
 {
  char ch1;
  char ch2;
  int data;
  double index;
  char extra;               
  }INFO;
int main(int argc,char argv[])
{
   printf("%d\n",sizeof(INFO));
   printf("%d\n",sizeof(double));
 getch();  
 return 0;   
}

你能否不运行代码而说出该程序运行结果?能否分析出其原理?并总结出计算结构体大小的一般运算方法?

在32位机里,编译器为char分配1个字节,但是此结构体里还有其他类型的数据项,intdouble,为了对齐,要为char补上3个字节,其他的就不需要补内存空间了。

我认为测结构体的大小时,需要找到一个基础类型数据!然后若发现和其基础类型数据小的,要补够它的基础字节,使其和基础字节的字节数相同!关键是寻找基础字节。

(4)

#include<stdio.h>
 typedef struct info
 {
   char  ch1;
   char  ch2; 
   int data;
   double index;
   char extra;       
 }INFO;
 #define OFFSET (size_t)&(((INFO*)0)->extra)
int main(int argc, char *argv[])
{
  printf("%d\n",OFFSET);
  printf("%d\n",(size_t)&(((INFO*)0)->extra));
  printf("%d\n",(size_t)&(((INFO*)1)->extra));
   printf("%d\n",(size_t)&(((INFO*)3)->extra)); 
 return 0;   
}

结合例子(3),描述宏OFFSET的功能!

这个题首先要理解size_t 

它是一种整型类型,里面保存的是一个整数,就像int, long那样。这种整数用来记录一个大小(size)size_t的全称应该是size type,就是说一种用来记录大小的数据类型。通常我们用sizeof(XXX)操作,这个操作所得到的结果就是size_t类型。因为size_t类型的数据其实是保存了一个整数,所以它也可以做加减乘除,也可以转化为int并赋值给int类型的变量。经测试发现,在32位系统中size_t4字节的,而在64位系统中,size_t8字节的

类似的还有wchar_t, ptrdiff_twchar_t就是wide char type一种用来记录一个宽字符的数据类型ptrdiff_t就是pointer difference type一种用来记录两个指针之间的距离的数据类型

再理解&运算符

 按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为,否则为0。参与运算的数以补码方式出现。
例如:9&5可写算式如下: 00001001 (9的二进制补码)&00000101 (5的二进制补码) 00000001 (1的二进制补码)可见9&5=1

(((INFO*)0)->extra)

按我的理解就是一个INFO类型的指针,指向extea,得到一个数据;

Size_t得到一个结果,是一个类似int形的数据,(((INFO*)0)->extra)得到一个数据,两者进行与运算,发现在在二进制的反码在从右到左的第五位相同,所以结果为16.

(5)

#include<stdio.h>
#define SWAP(x,y)\
 {  \
    int t=x;\
     x=y;   \
    y=t; \    
       };\
int main(int argc,char *argv[])
 {
  int a=20,b=15;
  SWAP(a,b); 
   printf("a=%d,b=%d\n",a,b); 
   return 0;
 }

该段代码能正常运行吗?如果能运行,请分析输出结果,如果不能,请指出其错误,并修改之!使其完成ab变量数值的交换!

这是一个交换函数,运行之后发现它实现了ab的交换,没有定义指针变量。

在宏的末尾不需要分号,在这里用到了链接符,所以就无所谓要不要了。这让我想起了定义函数实现两个数的交换,宏不需要指针,而函数交换则需要指针。

(6)

#include<stdio.h>
int main(int argc,char *argv[])
{
  int a[5]={1,2,3,4,5};
  int* ptr=(int *)(&a+1);
    printf("%d,%d\n",*(a+1),*(ptr-1)); 
 return 0;   
}

请写出该段代码的结果,并理解该结果产生的原因!

int *ptr=(int *)(&a+1) 是指向数组a的毗邻区,ptr-1ptr指向毗邻区之后又往后移动了一个位置,所以指向a[4],*ptr-1)的结果为5

a+1指向的是数组a的首地址的下一个地址,所以*a+1)的结果是2

(7)

#include<stdio.h>
void foo(int b[][3]);
int main()
 {
  int a[3][3]={{1,2,3,},{4,5,6},{7,8,9}};
  foo(a);
  printf("%d\n",a[2][1]);   
  return 0;  
 }
 void foo(int a[][3])
 {
  ++a;  
  a[1][1]=9;   
 }

请写出代码的输出结果!

刚开始传入数组a的首地址,然后数组a的地址自加一,指向a[1][1],从他以后的数组又看做一个新数组,原数组a[1][1]相当于新数组的a[0][0],此时a[1][1]相当于原数组的a[2][1]被赋值为9原先的7被覆盖,返回main函数,输出a[2][1]所以为9了。

(8)

#include<stdio.h>
#define ADD(a,b) (a*b)
int main()
{
  printf("%d\n",ADD(3+5,6+2));        
 return 0;   
}

请写出输出结果,并总结该宏的特点是什么?

宏替换有一条重要的原则就是“后替前”,在这里进行替换后是“3+5*6+2,它在计算时仍按+-*/运算的一般规则进行运算,先计算5*6=30,然后再和32相加,所以结果为35。而不是把(3+5)整体看做a,(6+2)整体看做b。宏替换我觉得就是将替换的照抄,计算时仍按一般的运算规则进行计算。

(9)
 void test1()
 {
  char *s;
  s="hello world";    
  printf("%s\n",s);   
 }
 
 void test2()
 {
  int a=2;
  int *p;    
  p=&a;   
  printf("%d\n",*p);   
 }
 
  void test3()
 {
  int *p=2;      
  printf("%d\n",*p);   
 }

void test4()
 {
   int *p=(int *)malloc(sizeof(int));
   *p=2;
    printf("%d\n",*p);
    free(p); 

}

上述函数哪一个是错误的,为什么?

在test3()中,指针是指向一个常数的,这是错误的,而指针应该指向一块地址。正确的定义初始化方式应该和2相同。

Test4()可以这样理解,p申请了一块动态内存,此时的指针p它已经指向了一块地址,但是还未初始化,*p=2的意思就是把这块地址赋值,使用之后申请的内存又被释放了。

 

你可能感兴趣的:(嵌入式入门)