c回顾 03

1 int *p = a 指针与数组

cpp 复制代码
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *p = a;

【详细解释一下这个,int *p = a是不是创建一个指针变量p指向a数组?】

int *p = a; 确实是创建一个指针变量 p 并让它指向数组 a 的起始位置

详细解释如下:

  1. 在 C 语言中,数组名 a 本身代表数组的首地址(即第一个元素的地址),它相当于 &a[0]

  2. int *p 声明了一个指向 int 类型的指针变量 p

  3. int *p = a; 这条语句的含义是:

    • 创建指针变量 p
    • 将数组 a 的首地址赋值给 p
    • 此时 p 指向数组的第一个元素 a[0]
  4. 赋值后,以下几种访问方式是等价的:

    • a[0] 直接访问第一个元素
    • *p 通过指针访问第一个元素
    • *(a + 0) 通过数组首地址访问第一个元素
    • *(p + 0) 通过指针访问第一个元素
  5. 同样地,访问第二个元素可以用:

    • a[1]
    • *(p + 1)
    • *(a + 1)
    • p[1](指针也可以像数组一样使用下标)

简单来说,这个语句建立了指针 p 和数组 a 的关联,使我们可以通过指针来操作整个数组。

2 函数调用时要注意

cpp 复制代码
有以下函数定义:
void fun(int n, double x) {...}
若以下选项中的变量都已正确定义并赋值,则对函数fun的正确调用语句是()
A fun(int y,double m);
B k=fun(10,12.5);
C fun(x,n);
D void fun(n,x);

正确答案:C

函数调用需要严格按照函数声明的参数类型和顺序来传递参数。

原函数fun的声明为void fun(int n, double x),它需要第一个参数为int类型,第二个参数为double类型。

C选项fun(x,n)是正确的,因为题目说明"所有变量都已正确定义并赋值",所以可以假设x和n的类型分别是int和double类型,符合函数声明的参数要求。

分析其他选项:

A错误:fun(int y,double m)是函数声明的形式,不是函数调用。函数调用时不能带参数类型。

B错误:fun函数的返回类型是void,表示不返回任何值,因此不能用赋值语句k=fun(10,12.5)来接收返回值。【我的错解!!!!】

D错误:void fun(n,x)同样是函数声明的形式而不是调用,而且声明时缺少了参数类型,语法错误。
总结:

函数调用时要注意:

  1. 不需要写参数类型

  2. 参数类型要匹配

  3. void类型函数不能用于赋值

  4. 区分函数声明和函数调用的语法

3 宏定义的文本替换特性以及运算符优先级

宏定义是简单的文本替换,不会自动添加括号改变运算优先级

cpp 复制代码
下面程序的运行结果是:
#define N 2
#define M N + 1
#define NUM (M + 1) * M / 2
main(){
    printf("%d\n", NUM);
}

A 4
B 9
C 8
D 6

正确答案:C
  1. 替换过程:

    • N 替换为 2
    • M 替换为 N + 1 → 即 2 + 1(注意不是 (2 + 1)
    • NUM 替换为 (M + 1) * M / 2 → 即 (2 + 1 + 1) * 2 + 1 / 2【并且输出类型是int会自动替换】
  2. 关键问题:由于宏替换只是文本替换,M 被替换后是 2 + 1 而不是 (2 + 1),导致运算顺序与预期不同实际计算过程:(2 + 1 + 1) * 2 + 1 / 2 = 4 * 2 + 0 = 8

如果希望得到数学上的预期结果(9),正确的宏定义应该为:

cpp 复制代码
#define N 2
#define M (N + 1)  // 增加括号保证运算顺序
#define NUM (M + 1) * M / 2

因此这道题主要考察对宏定义文本替换特性以及运算符优先级的理解。

4 文件操作函数fclose()返回值

cpp 复制代码
当顺利执行了文件关闭操作时,fclose函数的返回值是()
A -1
B TRUE
C 0
D 1
正确答案:C

主要考察对 C 语言中文件操作函数fclose()返回值的理解。

考点解析:

fclose()函数用于关闭已打开的文件,其返回值规则是:

  • 当文件关闭操作成功时,返回0
  • 当关闭失败时(如出现错误),返回EOF (在标准库中通常定义为-1

因此正确答案是选项 C(0)。

补充知识点:

  1. 函数原型

    cpp 复制代码
    int fclose(FILE *stream);
  2. 使用场景 :每次使用fopen()打开文件后,都应该在操作完成后调用fclose()关闭文件,这是良好的编程习惯,能:

    • 确保缓冲区中的数据被正确写入文件
    • 释放系统为该文件分配的资源
    • 避免文件描述符泄露
  3. 错误处理示例

    cpp 复制代码
    FILE *file = fopen("example.txt", "r");
    if (file == NULL) {
        // 处理打开失败
    }
    
    // 文件操作...
    
    if (fclose(file) != 0) {
        printf("文件关闭失败\n");
    }
  4. 与其他 I/O 函数的区别 :不同于fopen()(失败返回NULL),fclose()通过返回值明确告知操作是否成功,这是 C 语言文件操作中重要的错误检查点。

5 函数默认参数的使用规则

cpp 复制代码
考虑下面函数原型
void hello(int a,int b=7,char* pszC="*");
下面的函数调用不合法的是()
A hello(5)
B hello(5,8)
C hello(6,"#")
D hello(0,0,"#")

正确答案:C

函数默认参数的使用规则,关键在于关键在于理解函数参数的传递顺序和类型匹配要求。

函数原型分析

给出的函数原型是:

cpp 复制代码
void hello(int a, int b=7, char* pszC="*");

这是一个带有默认参数的函数,参数特点如下:

  1. 第一个参数 int a必须显式传递,无默认值
  2. 第二个参数 int b=7:有默认值 7,调用时可省略
  3. 第三个参数 char* pszC="*":有默认值 "*",调用时可省略

默认参数的核心规则

  • 默认参数必须从右向左定义(本题已满足:后两个参数有默认值)
  • 调用时必须按顺序传递参数,不能跳过前面的参数传递后面的参数
  • 参数类型必须匹配,否则会导致编译错误

各选项分析

A. hello(5)
  • 只传递了第一个参数 a=5
  • 第二个参数使用默认值 b=7
  • 第三个参数使用默认值 pszC="*"
  • 合法(符合参数传递规则)
B. hello(5,8)
  • 传递了前两个参数 a=5, b=8
  • 第三个参数使用默认值 pszC="*"
  • 合法(按顺序传递,类型匹配)
C. hello(6,"#")
  • 第一个参数 a=6 正确传递
  • 第二个参数试图传递 "#"(字符串常量,类型为 char*),但函数第二个参数要求是 int 类型
  • 这里错误在于:跳过了第二个参数(int 类型),直接传递了第三个参数,导致类型不匹配
  • 不合法(违反顺序传递规则,类型不匹配)
D. hello(0,0,"#")
  • 三个参数都显式传递:a=0, b=0, pszC="#"
  • 所有参数类型均匹配(int, int, char*)
  • 合法(完整传递,类型正确)

总结

错误的关键是选项 C跳过了第二个 int 类型的参数,直接传递了第三个字符串参数,违反了 "按顺序传递参数" 的规则,导致类型不匹配,因此调用不合法。

【char*是什么?】

char* 是 C 和 C++ 中的一种指针类型 ,专门用于指向字符(char 类型)数据。它最常见的用途是表示字符串(由多个字符组成的序列)。

详细解析:

  1. 基本含义

    • char 表示字符类型(1 字节,用于存储单个字符,如 'a''0''#' 等)。
    • * 表示这是一个指针类型,char* 即 "指向字符的指针"。
    • 一个 char* 类型的变量,存储的是某个字符在内存中的地址。
  2. 与字符串的关系 在 C/C++ 中,字符串被定义为以空字符 '\0' 结尾的字符序列 ,而 char* 通常作为字符串的 "标识",指向这个序列的第一个字符。例如:

    cpp 复制代码
    char* str = "hello";  // str 指向 'h' 的地址,后续字符依次存储

    此时,str 指向字符串的首地址,通过指针移动可以访问整个字符串(直到遇到 '\0' 结束)。

  3. 常见用法

    • 作为函数参数传递字符串(避免复制整个字符串,提高效率):

      cpp 复制代码
      void printString(char* s) {
          while (*s != '\0') {  // 遍历到字符串结尾
              printf("%c", *s);
              s++;  // 指针移动到下一个字符
          }
      }
    • 动态分配字符数组(结合 mallocnew):

      cpp 复制代码
      char* buffer = (char*)malloc(100);  // 分配100字节的字符缓冲区
  4. 注意事项

    • char* 指向的字符串可能是常量字符串 (如 "hello"),此时不能修改其内容(否则会导致未定义行为)。

    • 若需要修改字符串,应指向可修改的字符数组:

      cpp 复制代码
      char arr[] = "hello";  // 字符数组,内容可修改
      char* ptr = arr;       // ptr 指向数组首元素,可通过 ptr 修改内容
      ptr[0] = 'H';          // 合法,数组内容变为 "Hello"

简单说,char* 是处理字符串的 "工具",通过它可以访问和操作内存中的字符序列。

相关推荐
代码村新手2 小时前
C语言-指针
c语言·开发语言·jvm
yuxb732 小时前
华为云学习笔记(四):运维类服务与企业网站上云实践
笔记·学习·华为云
一只小风华~3 小时前
Vue Router 命名路由学习笔记
前端·javascript·vue.js·笔记·学习·ecmascript
La Pulga4 小时前
【STM32】ADC数模转换器
c语言·stm32·单片机·嵌入式硬件·mcu
超级大只老咪4 小时前
HTML学习路线
前端·学习·html
゜ eVer ㄨ4 小时前
React学习第三天——生命周期
前端·学习·react.js
顾你&4 小时前
机器学习之无监督学习算法大总结
学习·算法·机器学习
xiaoxusun06215 小时前
【最终章】-串口收发指令处理器-Verilog语法学习EP12
学习·fpga开发
老虎06275 小时前
黑马点评学习笔记01(手机号校验(正则表达式))
笔记·学习