【ONE·C || 代码分析题(一)】

  

总言

  分支循环、数据存储与程序结构、字符/字符串、指针相关,待补。

文章目录

  • 总言
  • 一 、分支循环
    • 循环语句
      • 题一:
      • 题二:
    • 分支语句
      • 题一:
      • 题二:
  • 二、数据存储与程序结构
    • 数据类型
      • 题一:
      • 题二:
      • 题三:
      • 题四:
      • 题五:
      • 题六:
    • 程序结构
      • 题一:
  • 三、字符、字符串相关
      • 题一:
      • 题二:
  • 四、指针相关
    • 指针初阶
      • 题一:
      • 题二:
      • 题三:
    • 指针高阶:
      • 题一:
      • 题二:
      • 题三:
      • 题四:
      • 题六:
    • sizeof、strlen与不同类型数组结合
      • 题一:
      • 题二:
      • 题三:
      • 题四:
      • 题五:

一 、分支循环

循环语句

题一:

  • 下列代码执行的结果为:
#include 
 
int main()
{
	int i = 0;
	for (i = 0; i<10; i++)
	{
		if (i = 5)
			printf("%d ", i);
	}
	return 0;
}
//死循环打印5.

  
  

题二:

  • 下列代码执行的结果为:
  • A、30
  • B、无限循环
  • C、9
  • D、2160
#include
int f(int x)
{
	return ((x > 2) ? x * f(x - 1) : 3);
}
int main()
{
	int i;
	i = f(f(2));
	printf("%d\n", i);
	return 0;
}

递归,9

  
  

分支语句

题一:

  • func(1)的结果为
int func(int a)
{
    int b;
    switch (a)
    {
        case 1: b = 30;
        case 2: b = 20;
        case 3: b = 16;
        default: b = 0;
    }
    return b;
}
//0;

  
  

题二:

  • 代码的执行结果为:
#include 
int main() {
	int x = 3;
	int y = 3;
	switch (x % 2) {
	case 1:
		switch (y)
		{
		case 0:
			printf("first");
		case 1:
			printf("second");
			break;
		default: printf("hello");
		}
	case 2:
		printf("third");
	}
	return 0;
}
//hellothird.
//此处case语句就较为复杂一些,但难度还是有待提升。

  
  

二、数据存储与程序结构

数据类型

题一:

  • 程序的执行结果为( )
  • A.300 300
    B.44 44
    C.300 44
    D.44 300
int main()
{
  unsigned char a = 200;
  unsigned char b = 100;
  unsigned char c = 0;
  c = a + b;
  printf(%d %d”, a+b,c);
  return 0;
}
200
0000 0000 0000 0000 0000 0000 1100 1000(原、反、补)
1100 1000(截断存储)

100
0110 0100(截断存储)
0000 0000 0000 0000 0000 0000 0110 0100(原、反、补)

计算,发生整值提升,无符号高位补0
a+b:
0000 0000 0000 0000 0000 0001 0010 1100300)
存入C中,截断:
0010 1100
存入C后打印,整值提升:
0000 0000 0000 0000 0000 0000 0010 110044

  
  

题二:

  • 在32位大端模式处理器上变量b等于( )
  • A.0x00
    B.0x12
    C.0x34
    D.0x1234
unsigned int a= 0x1234; 
unsigned char b=*(unsigned char *)&a;
0x表示以16进制的方式显示,一个数字(字母)代表四个二进制位。
unsigned int 无符号整型,整型在32位机器上大小为4个字节(32bit位),此处只有16位,故实际值为0X 00001234(高位0无意义,故省略)
大端模式即高数位放低地址。(数位,指一个数中每一个数字所占的位置)。
故在内存中,假设从左到右地址增高,则该数位存储方式为:00 00 12 34int类型强制转换为char类型,b中只获取一个字节,&a取的是低地址,即0X00

  
  

题三:

  • 下面代码的结果是( )
  • A.1000
    B.999
    C.255
    D.256
int main()
{
  char a[1000] = {0};
  int i=0;
  for(i=0; i<1000; i++)
  {
    a[i] = -1-i;
  }
  printf("%d",strlen(a));
  return 0;
}
预先知识:
对于char类型,其在内存中大小为一字节,即八比特位。
对于unsinged char,其能存储的数据一共有:0000 00001111 11112^8=255个。
对于singed char,其能存储的数据一共有:0000 00000111 11111000 00001111 1111同样也是255个。
但有符号char类型最高位为符号位,故其表示0-127-128-1。
(ps:有符号char型中,0000 00001111 1111所代表的数,其存储的是补码,计算时须按照正负转换为对应的原码)

该题分析:
a为char类型的数组其内能存储1000个元素。for循环使a数组内元素分别赋值为:
-1-2-3、……、-128127126125、……、3210-1-2、……
strlen函数会读取字符串函数,直到碰到“\0”(此为转义字符,指空字符)为止,strlen会返回空字符前的字符个数。
而“\0”的ascii码值恰好为0,因此输入的1000个数组元素中,strlen在读取到元素0时返回。(尽管输入的是int类型,实际对应是其ascii码)
故0之前的数为:128+127=255个。

【ONE·C || 代码分析题(一)】_第1张图片
【ONE·C || 代码分析题(一)】_第2张图片

【ONE·C || 代码分析题(一)】_第3张图片
  
  

题四:

  • 下列结果输出为:
#include 
int main()
{
	int a, b, c;
	a = 5;
	c = ++a;
	b = ++c, c++, ++a, a++;
	b += a++ + c;
	printf("a = %d b = %d c = %d\n:", a, b, c);
	return 0;
}
a=9,b=23,c=8

  
  

题五:

  • 下列结果输出为:
#include
int main()
{
	unsigned char i = 7;
	int j = 0;
	for (; i > 0; i -= 3)
	{
		++j;
	}
	printf("%d\n", j);
	return 0;
}

答案:173次(3+85+85),解析如下图。
注意事项:
1、关于无符号字符类型和有符号字符类型间的对应关系:(循环)
有符号:01、……、127-128-127、……、2-1
无符号:01、……、127128129、……、254255
2、小学的数学问题:数字间隔和数字个数(植树问题)
通常我们做减法时,a-b得到的是a、b间的间隔,算a、b个数时需要再加1
折换到此题中,数字i每变动一次,j要自增一次,即我们计算的是数字个数,不是数字间隔。但做±得到的二者间隔。

【ONE·C || 代码分析题(一)】_第4张图片

  
  

题六:

  • 下列结果输出为:
#include
int main()
{
	int a = -3;
	unsigned int b = 2;
	long c = a + b;
	printf("%ld\n", c);
	return 0;
}
-31000 0000 0000 0000 0000 0011
1111 1111 1111 1111 1111 1100
1111 1111 1111 1111 1111 1101
20000 0000 0000 0000 0000 0010
a+b:
1111 1111 1111 1111 1111 1111
C:
long:4字节
1111 1111 1111 1111 1111 1111
打印:
1000 0000 0000 0000 0000 0000
1000 0000 0000 0000 0000 0001(打印数值:-1

  
  

  
  

程序结构

题一:

  • 下面代码的结果是:
  • A.>
    B.<
    C.不输出
    D.程序有问题
#include 
int i;
int main()
{
    i--;
    if (i > sizeof(i))
    {
        printf(">\n");
    }
    else
    {
        printf("<\n");
    }
    return 0; 
}
涉及知识点:
1、局部变量与全局变量。
对局部变量而言,通常情况下,其具有自动存储期限和块作用域。若有存储类说明符static修饰,则该变量
为静态局部变量,具有静态存储期限和块作用域。
对于全局变量,其具有静态存储期限和文件作用域。

自动存储期限指内存空间在局部变量创建时为其分配的一个临时存储空间,当结束程序块时,存储空间被收
回,对应的局部变量无法保留。同理,块作用域指从局部变量声明开始,到程序块结束时(诸如函数体结尾),
这段程序文本内,可使用该局部变量。
静态存储期是指能永久保留变量直到程序结束为止的内存期限。同理得文件作用域从变量声明开始到程序结
束为止,全局变量都可被访问与修改。

未初始化赋值时,拥有静态存储期限的全局变量默认初始值为0,拥有自动存储期限的局部变量默认初始值为
随机值。

2、seizoef返回值为无符号整形。

  
  

三、字符、字符串相关

  

题一:

  • 下面代码的执行结果是( )
#include 
int main()
{
    char str1[] = "hello bit.";
    char str2[] = "hello bit.";
    const char *str3 = "hello bit.";
    const char *str4 = "hello bit.";
    if(str1 ==str2)
 printf("str1 and str2 are same\n");
    else
 printf("str1 and str2 are not same\n");
       
    if(str3 ==str4)
 printf("str3 and str4 are same\n");
    else
 printf("str3 and str4 are not same\n");
       
    return 0;
}
str1 and str2 are not same
str3 and str4 are not same
---------------------------
相关知识点:相同字符数组和字符指针在内存中是否为同一存储空间的问题:
不同指针指向同一字符串常量,相同字符串常量初始化不同数组。

  
  

题二:

  • 下面代码,若输入“labcedf2df”,其执行结果是( )
#include
int main()
{
	char a = 0, ch;
	while ((ch = getchar()) != '\n')
	{
		if (a % 2 != 0 && (ch >= 'a' && ch <= 'z'))
			ch = ch - 'a' + 'A';
		a++;
		putchar(ch);
	}
	printf("\n");
	return 0;
}
lAbCeDf2dF

  
  

四、指针相关

  

指针初阶

  

题一:

  • 下面代码的结果是:( )
#include 
int main()
{
  int arr[] = {1,2,3,4,5};
  short *p = (short*)arr;
  int i = 0;
  for(i=0; i<4; i++)
  {
    *(p+i) = 0;
  }
   
  for(i=0; i<5; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}
00345

  
  

题二:

  • 下面代码输出的结果是:( )
#include 
int main()
{
	int a = 0x11223344;
    char *pc = (char*)&a;
    *pc = 0;
    printf("%x\n", a);
    return 0;
}
0x 11223300
ps:此处涉及一个大小端存储问题,这里是以小端存储为前提。
若是大端存储下则为0x 00223344.

  
  

题三:

  • 设有定义char* p[] = { “Shanghai”,“Beijing”,“Honkong” };
  • 其结果为字符 ‘j’ 的表达式是:
char* p[] = { "Shanghai","Beijing","Honkong" };

A、*p[1]+3
B、*(p[1]+3)
C、*(p[3]+1)
D、*p[3][1]
char* p[]:指针数组
A、*p[1]+3---'B'+3='E'
B、*(p[1]+3)---'j'
C、*(p[3]+1)---越界
D、*p[3][1]---越界

  
  

指针高阶:

  

题一:

  
  

题二:

  • 下面代码的结果是:( )
int main()
{
    int a[4] = { 1, 2, 3, 4 };
    int* ptr1 = (int*)(&a + 1);
    int* ptr2 = (int*)((int)a + 1);
    printf("%x,%x", ptr1[-1], *ptr2);
    return 0;
}
4  2000000

【ONE·C || 代码分析题(一)】_第5张图片
  
  

题三:

  • 下面代码的结果是:( )
int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;
    printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}

【ONE·C || 代码分析题(一)】_第6张图片
  
  

题四:

  • 下面代码的结果是:( )
int main()
{
    char* c[] = { "ENTER","NEW","POINT","FIRST" };
    char** cp[] = { c + 3,c + 2,c + 1,c };
    char*** cpp = cp;
    printf("%s\n", **++cpp);
    printf("%s\n", *-- * ++cpp + 3);
    printf("%s\n", *cpp[-2] + 3);
    printf("%s\n", cpp[-1][-1] + 1);
    return 0;
}

【ONE·C || 代码分析题(一)】_第7张图片
【ONE·C || 代码分析题(一)】_第8张图片
【ONE·C || 代码分析题(一)】_第9张图片
【ONE·C || 代码分析题(一)】_第10张图片
【ONE·C || 代码分析题(一)】_第11张图片

  
  

题六:

  • 试解释下列指针数组、数组指针的含义:
int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];
int (*parr3[10])[5];存放数组指针的指针数组
parr3先和[]下标引用操作符结合,为数组,数组元素有10个,每个元素的类型为 int (*)[5],即数组指针。
该数组指针指向元素个数为5,元素类型为int型的数组。
  • 函数指针、函数指针数组、指向函数指针数组的指针:
void test(const char* str)
{
 printf("%s\n", str);
}
int main()
{
 //函数指针pfun
 void (*pfun)(const char*) = test;
 //函数指针的数组pfunArr
 void (*pfunArr[5])(const char* str);
 pfunArr[0] = test;
 //指向函数指针数组pfunArr的指针ppfunArr
 void (*(*ppfunArr)[5])(const char*) = &pfunArr;
 return 0;
}

  
  

sizeof、strlen与不同类型数组结合

题一:

//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));

//一维数组
int a[] = {1,2,3,4};

printf("%d\n",sizeof(a));//16,sizeof内部单独放置数组名,计算整个数组的的大小。
printf("%d\n",sizeof(a+0));//4或8,sizeof内未单独放置数组名,此时数组名表示数组首元素地址,加减地址为指针的算术运算,此处sizeof计算数组首元素a[0]的地址。
printf("%d\n",sizeof(*a));//4,sizeof内部未单独放置数组名,此处表示数组首元素地址,解引用后得数组首元素,sizeof计算数组首元素(对应类型)的大小。
printf("%d\n",sizeof(a+1));//4或8,计算地址大小。
printf("%d\n",sizeof(a[1]));//4,计算数组元素对应类型大小。
printf("%d\n",sizeof(&a));//4或8,&数组名,表示整个数组元素的地址,sizeof计算地址大小。
----------------
printf("%d\n",sizeof(*&a));//16,&a表示整个数组的地址,*&a得到整个数组,sizeof计算整个数组的大小。
//对此题的理解要格外注意,如果不再sizeof内部,单独出现数组名则表示数组首元素地址
//因此,对于 int (*p)=&a  ; *(*P+i) 类似于*&a,只不过此处没有出现sizeof,所得到的是数组首元素地址。
----------------
printf("%d\n",sizeof(&a+1));//4或8,&a表示整数数组的地址,+1跳过整个数组,得到后续内存空间的地址,sizeof计算地址大小。
printf("%d\n",sizeof(&a[0]));//4或8,sizeof计算数组首元素地址的大小。
printf("%d\n",sizeof(&a[0]+1));//4或8

  
  

题二:

//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//6,sizeof内单独放置数组名,计算整个数组的大小。
printf("%d\n", sizeof(arr+0));//4或8,sizeof内部未单独放置数组名,则此时数组名表示数组首元素的地址,sizeof计算地址的大小。
printf("%d\n", sizeof(*arr));//1,sizeof内未单独放置数组名,表示数组首元素的地址,解引用后表示数组首元素,sizeof计算数组首元素的大小。
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//4或8,&arr表示整个数组的地址,sizeof计算整个数组地址的大小。
printf("%d\n", sizeof(&arr+1));//4或8,跳过整个数组,来到数组后面的那个内存空间的地址,sizeof计算地址大小。
printf("%d\n", sizeof(&arr[0]+1));//4或8,sizoef计算arr[1]的地址大小。
printf("%d\n", strlen(arr));//随机值,arr表示数组首元素地址,数组确少‘\0’,strlen统计字符数组直至遇到‘\0’前的元素个数。
printf("%d\n", strlen(arr+0));//随机值,arr+0表示数组首元素地址,strlen统计遇到第一个‘\0’前的元素个数。
printf("%d\n", strlen(*arr));//错误,非法访问。*arr得到数组首元素,即字符‘a’,对应AScii码为97,strlen从地址编号为97处开始计数,属于非法访问。
printf("%d\n", strlen(arr[1]));//同上
printf("%d\n", strlen(&arr));//随机值,与arr同
printf("%d\n", strlen(&arr+1));//随机值,与&arr相差6字节
printf("%d\n", strlen(&arr[0]+1));//随机值,与&arr相差1字节

  
  

题三:

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//7,sizeof计算整个数组的大小。
printf("%d\n", sizeof(arr+0));//4或8,sizeof计算数组首元素地址的大小。
printf("%d\n", sizeof(*arr));//1,arr非单独放置在sizeof中,表示数组首元素地址,解引用后得到数组首元素,sizeof计算数组首元素对应类型的地址。
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//4或8,sizeof计算整个数组的地址。
printf("%d\n", sizeof(&arr+1));//4或8,sizeof计算数组后内存空间地址的大小。
printf("%d\n", sizeof(&arr[0]+1));//4或8,sizeof计算arr[1]元素地址的大小。
printf("%d\n", strlen(arr));//6,arr表示首元素地址,strlen从该地址起,统计第一次出现‘\0’前的字符个数。
printf("%d\n", strlen(arr+0));//同上
printf("%d\n", strlen(*arr));//非法范围,错误
printf("%d\n", strlen(arr[1]));//同上
printf("%d\n", strlen(&arr));//6
printf("%d\n", strlen(&arr+1));//随机值
printf("%d\n", strlen(&arr[0]+1));//5,从数组第二个元素开始统计字符个数。

  
  

题四:

char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));
printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));
char *p = "abcdef";
printf("%d\n", sizeof(p));//4或8,sizeof计算指针变量的大小。
printf("%d\n", sizeof(p+1));//4或8,指针加减整数,跳过对应类型大小的地址,此处跳过一个字节指向b,sizeof计算该地址大小。
printf("%d\n", sizeof(*p));//1,char* 型指针,解引用p得到字符串首字符‘a’,sizeof计算该字符对应类型大小。
printf("%d\n", sizeof(p[0]));//1,p[0]-->*(p+0)-->a,sizeof计算字符a对应类型的大小。
printf("%d\n", sizeof(&p));//4或8,&p得二级指针,为一级指针p的地址,sizeof计算地址的大小。
printf("%d\n", sizeof(&p+1));//4或8,&p得二级指针,为一级指针p的地址,&p+1二级指针往后访问一字节,sizeof计算地址的大小。
printf("%d\n", sizeof(&p[0]+1));//4或8,‘b’字符地址的大小。
printf("%d\n", strlen(p));//6,p表示字符串首地址,即‘a’的地址,strlen从a往后统计字符个数直至遇到'\0'
printf("%d\n", strlen(p+1));//5,p+1表示‘b’的地址,stlren从b往后统计字符个数,直到遇到'\0'
printf("%d\n", strlen(*p));//非法访问,*p得到字符'a',strlen从其ascill码对应地址开始访问
printf("%d\n", strlen(p[0]));//同上
printf("%d\n", strlen(&p));//随机值,&p表示字符指针的地址,从该地址开始统计字符总数直至遇到'\0'
printf("%d\n", strlen(&p+1));//同上
printf("%d\n", strlen(&p[0]+1));//5,从字符‘b’开始,统计字符总数,直至遇到'\0'

  
  

题五:

//二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));
//二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//48,单独数组名,在sizeof内表述整个数组的大小,即3*4*4=48
printf("%d\n",sizeof(a[0][0]));//4,一行一列元素大小,int类型,四字节
printf("%d\n",sizeof(a[0]));//16,a[0]在二维数组中表述第一行的数组名,数组名单独放在sizeof中表述整个一维数组的大小,即二维数组第一行元素整体的大小
printf("%d\n",sizeof(a[0]+1));//4或8,a[0]为二维数组第一行数组名,在sizeof中a[0]没有单独放置也没有&,故其表示数组首元素的地址,首元素地址+1,表示跳过对应类型大小,指向下一个地址
printf("%d\n",sizeof(*(a[0]+1)));//4,在sizeof中,*(a[0]+1)表示第一行第二个元素
printf("%d\n",sizeof(a+1));//4或8,sizeof中a没有单独放置也无取地址,表示二维数组首元素,即第一行地址,(a+1)则表示第二行地址
printf("%d\n",sizeof(*(a+1)));//16,解引用第二行地址,得到整个第二行
printf("%d\n",sizeof(&a[0]+1));//4或8,a[0]第一行一维数组的数组名,在sizeof中&后表示整个一维数组的地址,+1为第二行数组的地址
printf("%d\n",sizeof(*(&a[0]+1)));//16,解引用第二行地址,得到第二行
printf("%d\n",sizeof(*a));//16,二维数组数组名非单独放置,也没和&结合,在sizeof中表示二维数组数组名,即第一行元素的地址,解引用后表示第一行
printf("%d\n",sizeof(a[3]));//16,不会实际访问,只是需要知道对应类型,即int [4]

你可能感兴趣的:(#,【ONE·C】,c语言)