C语言笔试题_1

在C语言中,scanf 是用于从标准输入读取数据的函数。你提供的 scanf 格式化字符串 "%c%*c%c" 有一些特殊的用法,下面是对其的详细解释。

语句解析

scanf("%c%*c%c", &a, &b);
  • %c: 读取一个字符,并将其存储在变量 a 中。
  • %*c: 读取一个字符,但不将其存储(丢弃)。其中,* 表示“抑制存储”,即读取的字符不会存入任何变量。
  • %c: 读取另一个字符,并将其存储在变量 b 中。

举例说明

假设你输入 "A B"(A、空格、B),scanf 的行为将如下:

  1. 读取A:第一个 %c 读取第一个字符 'A',并将其存储在 a 中。
  2. 忽略空格%*c 读取下一个字符,这里是空格 ' ',但是由于有 *,这个字符被丢弃,不会存储在任何变量中。
  3. 读取B:最后一个 %c 读取字符 'B',并将其存储在 b 中。

总结

所以,scanf("%c%*c%c", &a, &b); 的功能是:

  • 从输入中读取两个字符,中间可以有任意字符(包括空格、换行符等),这个中间的字符会被忽略掉。

假设输入为 "A B",则:

  • a 将存储 'A'
  • b 将存储 'B'
  • 中间的空格将被忽略,不存储在任何变量中。

这个代码片段使用 scanfgetchar 读取用户输入的两个字符。让我们详细分析这段代码的行为:

scanf("%c", &a);
getchar();
scanf("%c", &b);

代码解析

  1. scanf("%c", &a);

    • 这个语句读取一个字符并将其存储在变量 a 中。%c 读取单个字符,包括空白字符(如空格、换行符等)。
  2. getchar();

    • getchar() 从标准输入读取下一个字符并丢弃它。这个字符通常是用户输入第一个字符后按下的 Enter(换行符 \n
  3. scanf("%c", &b);

    • 再次使用 %c 读取一个字符并将其存储在变量 b 中。

举例说明

假设用户输入 "A" 并按下 Enter,然后再输入 "B" 并按下 Enter

  • 第一次scanf
    • 用户输入的 "A"scanf 读取并存储在 a 中。
    • 按下 Enter 后,输入缓冲区中实际上有两个字符:'A''\n'
  • getchar()
    • getchar() 读取并丢弃缓冲区中的下一个字符,即 '\n',这防止它影响后续的 scanf
  • 第二次scanf
    • 现在缓冲区是空的,程序等待用户再次输入字符。
    • 用户输入 "B" 并按下 Enterscanf 读取 "B" 并存储在 b 中。

总结

这个代码片段的作用是读取两个字符,中间通过 getchar() 清除掉第一个输入后遗留的换行符,以确保第二次 scanf 读取到的是用户真正输入的下一个字符,而不是之前输入后的换行符。

这样可以避免直接使用两次 scanf("%c", &a); scanf("%c", &b); 可能导致第二次 scanf 读取到的是上一次输入后的换行符,而不是新的用户输入字符。

  1. 在这里插入图片描述
  2. 1.不能做 switch( ) 的参数类型是__实型(浮点型);______?
  3. 在这里插入图片描述
  4. 2.答案:D。解析:do…While语句会先执行循环体一次才会判断语句,进入do后,i自增为1,1>0,继续循环,陷入循环,程序执行一会,数据溢出正整数极限,变成负数,停止循环后,数据是一个非常大的负数,选项没结果。

  5. 1.打印九九乘法表


#include <stdio.h>
int main(int argc, const char *argv[])
{
	int i,j;
	for( i=1; i<=9; i++ )
	{
		for( j=1; j<=i; j++ )
{
			printf("%d * %d = %-2d   ", j, i, i * j);
}
		putchar(10);
	}
	return 0;
}
2.打印出所有的“水仙花”数。所谓“水仙花”数是指一个3位数,其各个位数字立方和等于该数本身。
#include <stdio.h>
int main(int argc, const char *argv[])
{
    	int  i,a,b,c;
        for( i=100; i<1000; i++ )
        {
            a = i/100;
b = (i/10)%10;
c = i%10;
            if ( i==(a*a*a + b*b*b*b + c*c*c) )
{
printf("%d\n", i);
}
        }
        return 0;
}
  1. 在这里插入图片描述
 int main(int argc, const char *argv[])
{
	#if 0
while(1);  、判断条件一直成立
#endif

#if 0
do{}while(1); 
#endif

#if 0
for(;1;);
#endif

#if 0
tip: 
goto tip;
#endif
	return 0;
}
32位和64位环境在基本数据类型的表示和处理上存在一些差异,尤其是关于数据类型的大小(即占用的内存空间)。以下是主要的区别:

### 1. **整型类型 (`int`, `long`, `long long`)**

- **`int` 类型**- 在大多数编译器和操作系统中,无论是32位还是64位系统,`int` 类型的大小通常为 **4字节(32位)**- 因此,`int` 类型在32位和64位系统上的大小通常是相同的,表示范围也一致(-2^312^31-1)。

- **`long` 类型**- **32位系统**:`long` 通常为 **4字节(32位)**,与 `int` 类型相同。
  - **64位系统**:`long` 在某些平台(例如Unix/Linux上的GCC编译器)上通常为 **8字节(64位)**,但在Windows上,`long` 仍然是 **4字节(32位)**- **`long long` 类型**-32位和64位系统中,`long long` 通常为 **8字节(64位)**,以确保可以表示更大的整数范围(-2^632^63-1)。

### 2. **指针类型**

- **指针大小**- **32位系统**:指针大小为 **4字节(32位)**,因此能够寻址的最大内存空间为4GB。
  - **64位系统**:指针大小为 **8字节(64位)**,可以寻址的内存空间非常庞大,理论上最大可以达到16EB(ExaBytes)。

指针大小的变化是32位和64位系统的主要区别之一,因为它直接影响程序的内存寻址能力和处理方式。

### 3. **浮点类型 (`float`, `double`, `long double`)**

- **`float` 类型**-32位和64位系统中,`float` 通常都是 **4字节(32位)**,精度和范围相同(大约7位有效数字)。

- **`double` 类型**-32位和64位系统中,`double` 通常都是 **8字节(64位)**,精度和范围相同(大约15位有效数字)。

- **`long double` 类型**- `long double` 的大小和精度在不同系统上可能会有所不同。
    - **32位系统**:通常为 **8字节**(与 `double` 相同),但在某些系统上可能为 **12字节****16字节**- **64位系统**:通常为 **16字节(128位)**,提供更高的精度和更大的表示范围。

### 4. **`size_t` 类型**

- **`size_t`** 是一个无符号整数类型,通常用于表示对象的大小或内存块的大小。
  - **32位系统**:`size_t` 通常为 **4字节(32位)**- **64位系统**:`size_t` 通常为 **8字节(64位)**,与指针大小一致。

### 5. **`time_t` 类型**

- **`time_t`** 用于表示时间值,通常是自Unix纪元(197011日)以来的秒数。
  - **32位系统**:`time_t` 通常为 **4字节(32位)**,这会导致 "2038年问题",即在2038年之后时间值将溢出。
  - **64位系统**:`time_t` 通常为 **8字节(64位)**,可以表示更大范围的时间值,避免了2038年问题。

### 总结

- **整型****浮点型** 数据类型的大小在32位和64位系统之间通常是相同的,除非特定类型如 `long` 和 `long double` 在不同系统上有所不同。
- **指针类型**64位系统上变为64位(8字节),这是最大的区别之一,影响到内存寻址和数据结构的布局。
- **`size_t`****`time_t`** 这些与系统架构密切相关的类型在64位系统上通常变得更大,以处理更大的内存和时间范围。

这些差异在编写跨平台代码时需要特别注意,尤其是在处理指针、内存管理、以及涉及类型大小的代码时。

若已定义 char s[10]; 则在下面表达式中不表示s[1]的地址的是 。
A.s+1
B.s++
C.&s[0]+1
D.&s[1]

2.答案:B。数组名字是整个数组的首地址,是常量,不允许被改变,++运算符会改变运算对象的值。

  1. 隐式转换总结

在C语言中,隐式转换(implicit conversion)是指编译器在表达式中自动将一种数据类型转换为另一种数据类型的过程,而无需显式地在代码中指定转换操作。隐式转换通常在不同数据类型的混合运算、函数参数传递、赋值操作中发生。

以下是几个隐式转换的常见示例:

1. 整型提升

当一个小于 int 类型的整数(如 charshort)参与运算时,会被提升为 int 类型。这种转换称为整型提升。

#include <stdio.h>

int main() {
    char a = 10;
    char b = 20;

    // 'a' 和 'b' 都是 'char' 类型,但在运算时会被提升为 'int'
    int sum = a + b;

    printf("Sum: %d\n", sum);  // 输出: Sum: 30
    return 0;
}

2. 算术转换

在算术运算中,如果操作数的类型不同,较低类型的操作数会被隐式转换为较高类型。通常的转换顺序为:char -> short -> int -> unsigned int -> long -> unsigned long -> float -> double -> long double

#include <stdio.h>

int main() {
    int a = 5;
    float b = 4.5;

    // 'a' 是 'int' 类型,'b' 是 'float' 类型
    // 在混合运算时,'a' 将被隐式转换为 'float'
    float result = a + b;

    printf("Result: %.2f\n", result);  // 输出: Result: 9.50
    return 0;
}

3. 赋值转换

在赋值操作中,如果赋值的值和目标变量的类型不同,值将被隐式转换为目标变量的类型。

#include <stdio.h>

int main() {
    float f = 3.14;
    int i;

    // 'f' 是 'float' 类型,'i' 是 'int' 类型
    // 在赋值时,'f' 的值会被隐式转换为 'int'
    i = f;

    printf("i: %d\n", i);  // 输出: i: 3
    return 0;
}

4. 函数调用中的隐式转换

当函数参数的类型与传递给函数的实参类型不同时,实参会被隐式转换为函数参数的类型。

#include <stdio.h>

void printDouble(double x) {
    printf("Value: %.2f\n", x);
}

int main() {
    int a = 10;

    // 'a' 是 'int' 类型,但 'printDouble' 函数期望一个 'double' 类型的参数
    // 因此 'a' 会被隐式转换为 'double'
    printDouble(a);  // 输出: Value: 10.00
    return 0;
}

5. 无符号和有符号类型之间的转换

当有符号类型和无符号类型一起使用时,有符号类型通常会被隐式转换为无符号类型。

#include <stdio.h>

int main() {
    unsigned int u = 10;
    int i = -20;

    // 'i' 是有符号类型,但在比较时会被隐式转换为无符号类型
    if (i < u) {
        printf("i is less than u\n");
    } else {
        printf("i is not less than u\n");
    }

    return 0;
}

在这个示例中,由于 i 是有符号类型,u 是无符号类型,在比较时,i 被隐式转换为无符号类型,这可能导致意想不到的结果(例如,i 变成一个大正数)。

总结

隐式转换在C语言中是非常常见的,理解其工作原理对于避免错误和意外行为非常重要。在许多情况下,编译器会根据上下文自动执行这些转换,但在某些情况下,程序员可能希望通过显式类型转换(cast)来明确地控制这种行为。

以下叙述中正确的是()

A
字符串常量"Hello"会被隐含处理成一个无名字符型数组,它有5个元素
B
不能用字符串常量对字符数组名进行整体赋值操作
C
char str[7] = “string!”; 在语法上是合法的,运行也是安全的
D
char *str; str = “Hello”;与char str[]; str = “Hello”;效果是一样的
正确答案:B
你的答案:D
官方解析:【解析】字符串中的字符依次存储在内存中一块连续的区域内,并且把空字符 ’ \0’ 自动附加到字符串的尾部作为字符串的结束标志。故字符个数为 n 的字符串在内存中应占( n+1 )个字节。选项 A 中有 6 个元素,其中包含结尾字符, C 选项中字符串常量包含 8 个字符,所以不能赋值在 str[7] 中, D 选项后者赋值错误。
知识点:C++、C语言

在这里插入图片描述

强制类型转换的运算优先级比乘除高
4.
下面叙述错误的是()

1
2
3
4
char acX[]=“abc”;
char acY[]={‘a’,‘b’,‘c’};
char *szX=“abc”;
char *szY=“abc”;
A
acX与acY的内容可以修改
B
szX与szY指向同一个地址
C
acX占用的内存空间比acY占用的大
D
szX的内容修改后,szY的内容也会被更改
正确答案:D
你的答案:B
参考答案:答案是D acX , acY 是2个数组,属于变量,一般存在栈区,可以修改, szX , szY 是2个指针指向常量区,常量区的东西不能被修改,所以D是错误的
知识点:C语言
题友讨论(51)
推荐最新楼层
在这里输入你的观点吧
头像
喂我信号不好

京东_算法开发工程师

A acX和acY都是数组,当然可以修改 B 因为"abc"是常量字符串,当它被多次使用时,编译器并不愿意再多分配出额外的内存空间存放多个"abc",而是重复使用这一个"abc",所以,scX和scY指针会指向同一个地址。 C 因为acX是字符串数组,字符串的尾部有一个结束符’\0’,所以acX有四个元素,内存空间比acY大 D 字符指针指向的是常量字符串,常量字符串不能修改
49
送花
回复
发布于 2017-10-19 16:26
头像
喂我信号不好

回复
朱小冲

首先哦,指针一般来说是局部变量,局部变量是在栈上的,当然也可以创建全局的指针,但是一般我们是不创建全局变量的。其次呢,你可能理解的混了,我们一般用指针接收malloc或new这些动态分配出来的空间的地址,即指针指向堆空间,而不是说指针在堆里。最后呢,常量区是存放常量字符串和其他类型的常量的,指针变量是不可能在常量区的

这段代码中存在一个潜在的错误,可能导致程序崩溃或行为异常。让我们详细分析一下:

代码解释

char szMsisdn[MAX_LEN_MSISDN-1];
szMsisdn[sizeof(szMsisdn)] = '\0';
  1. char szMsisdn[MAX_LEN_MSISDN-1];:

    • 定义了一个字符数组 szMsisdn,长度为 MAX_LEN_MSISDN-1。这意味着数组的索引范围是 0MAX_LEN_MSISDN-2,即数组总共可以存储 MAX_LEN_MSISDN-1 个字符。
  2. szMsisdn[sizeof(szMsisdn)] = '\0';:

    • 这里使用 sizeof(szMsisdn) 作为数组索引来访问 szMsisdnsizeof(szMsisdn) 返回的是数组的大小,即 MAX_LEN_MSISDN-1,这也是数组的长度。

问题所在

数组的索引范围是从 0MAX_LEN_MSISDN-2,但代码试图访问 szMsisdn[MAX_LEN_MSISDN-1]。由于 C 语言中的数组索引是从 0 开始的,szMsisdn[MAX_LEN_MSISDN-1] 实际上超出了数组的范围。这会导致越界访问,并且修改了内存中不属于该数组的内容,这可能引发未定义行为,包括程序崩溃或意外的内存破坏。

正确的做法

如果你希望在数组的最后一个有效位置设置字符串终止符 \0,应将其索引设置为 sizeof(szMsisdn) - 1 或者 MAX_LEN_MSISDN-2

修改后的代码:

char szMsisdn[MAX_LEN_MSISDN-1];
szMsisdn[sizeof(szMsisdn) - 1] = '\0';

char szMsisdn[MAX_LEN_MSISDN-1];
szMsisdn[MAX_LEN_MSISDN-2] = '\0';

总结

  • 原代码szMsisdn[sizeof(szMsisdn)] = '\0'; 试图访问数组越界的内存地址,这会导致未定义行为。
  • 修正后的代码szMsisdn[sizeof(szMsisdn) - 1] = '\0'; 这是正确的方式,将字符串的终止符 \0 放在数组的最后一个位置。

始终要确保数组索引在合法范围内,以避免意外的错误。

选项中,指向同一数组的两指针变量进行关系运算可表示它们所值数组元素之间的关系

以下选项中,对基本类型相同的指针变量不能进行运算的运算符是()

A
+
B

C

D

正确答案:A
你的答案:B
官方解析:暂无官方题目解析,去讨论区看看吧!
知识点:C语言
题友讨论(10)
推荐最新楼层
在这里输入你的观点吧
头像
KnowledgeI

江西农业大学 前端工程师
A错误,因为两个地址相加无意义也可能越界,所以规定不允许指针相加。 其他的都很好理解,B选项,可以求出两个数据元素储存位置之间的相隔同数据类型的元素个数,C选项,赋值,很好理解,D选项,判断两指针所指向的是否是同一数据元素
67
送花
回复
发布于 2018-05-10 14:59

在这里插入图片描述
在这里插入图片描述

解答
在这里插入图片描述

以下代码会出现什么问题?打印结果是是多少?
int main(int argc, const char *argv[])
{
char aa[10];
printf(“%d”,strlen(aa));
return 0;
}

参考答案:
sizeof()和初不初始化,没有关系,计算的是参数所占的内存字节大小;strlen()和初始化有关,计算参数指定的字符串不包含\0的字符个数,数组如果不初始化,数组存储空间上内容是未知的,所以计算字符串长度的话,无法预知有没有\0,打印结果值未知。

指针所占的字节大小取决于计算机系统的架构(即系统是32位还是64位)以及具体的编译器和编译目标。

### 1. **32位系统**
   -32位系统上,指针的大小通常为 **4字节**32位)。这适用于所有类型的指针(例如 `int*`、`char*`、`float*` 等),因为它们都需要能够寻址4GB的内存空间。

### 2. **64位系统**
   -64位系统上,指针的大小通常为 **8字节**64位)。在这种系统中,指针需要能够寻址更大的内存空间,理论上可以支持高达16EB(Exabytes)的内存地址空间。

### 3. **指针大小与类型无关**
   - 指针的大小与它指向的数据类型无关。在同一系统中,`int*`、`char*`、`double*` 等不同类型的指针都具有相同的大小。

### 4. **检测指针大小的代码示例**

你可以使用C语言中的 `sizeof` 操作符来确定当前系统中指针的大小。例如:

```c
#include <stdio.h>

int main() {
    printf("Size of char*: %zu bytes\n", sizeof(char*));
    printf("Size of int*: %zu bytes\n", sizeof(int*));
    printf("Size of float*: %zu bytes\n", sizeof(float*));
    printf("Size of double*: %zu bytes\n", sizeof(double*));
    return 0;
}
```

### 5. **输出示例**

-32位系统上,输出通常是:
  ```
  Size of char*: 4 bytes
  Size of int*: 4 bytes
  Size of float*: 4 bytes
  Size of double*: 4 bytes
  ```

-64位系统上,输出通常是:
  ```
  Size of char*: 8 bytes
  Size of int*: 8 bytes
  Size of float*: 8 bytes
  Size of double*: 8 bytes
  ```

### 总结

- **32位系统**:指针大小通常为 **4字节**- **64位系统**:指针大小通常为 **8字节**。

指针的大小决定了它可以寻址的内存空间大小,因此在不同的系统架构上,指针的大小会有所不同。在编写跨平台的代码时,这一点尤其重要。

数组名表示整个数组:在使用 sizeof 操作符时或数组初始化时,数组名表示整个数组。
数组名表示首元素的地址:在大多数其他情况下,例如传递给函数或用于指针运算时,数组名表示数组首元素的地址,即它被隐式转换为指向第一个元素的指针。

在这里插入图片描述

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值