ANSI C (1) —— 基础

2024-03-27 22:38
文章标签 基础 ansi

本文主要是介绍ANSI C (1) —— 基础,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

常量字符指针和字符指针的传参问题

1)
没有错误:

#include <stdio.h>
void out(const char *p){printf("%s\n",p);
}
int main(){char *str="hello";out(str);return 0;
}

2)
出现错误:
t.c:2:6: note: expected ‘char ’ but argument is of type ‘const char
void out(char *p){

#include <stdio.h>
void out(char *p){printf("%s\n",p);
}
int main(){const char *str="hello";out(str);return 0;
}

char * 变量可以传向const char *的参数,反之不行。

EOF

windows下我们按下ctrl+Z代表文件结束
linux下我们使用ctrl+D表示文件结束(在linux下使用ctrl+Z,如:
$ cat > t2
abc^Z
$ cat t2:
(nothing!)
)

$ cat > t2
abc^D

t.c:

#include <stdio.h>int main(){FILE *fin=fopen("t2","r");FILE *fout=fopen("t4","w");char ch;while(fscanf(fin,"%c",&ch)!=EOF){fprintf(fout,"(%c: %d) ",ch,ch);}return 0;
}

运行后查看输出文件t4:
(a: 97) (b: 98) (c: 99)

预处理器

C源码转化为目标代码的过程:

C源文件 ——> 预处理器 ——> 编译器

关键词:#预处理指令,宏

例子:

mydoc.c:

#include <stdio.h>
void print(){printf("hello\n");
}
int a=10;

t.c:

#include <stdio.h>/* "dir"表示用户目录,<dir>表示编译器的库目录  */#include "mydoc.c"
int main(){print();printf("%d\n",a);return 0;
}

out:

hello
10

查看库文件的源码:

cat /usr/include/stdio.h > read
vim read
: /EOF
:n

定位后:

133 #ifndef EOF
134 # define EOF (-1)
135 #endif

我们可以知道,EOF的整数值是-1

宏的便易性:
有时候,宏的替换功能可以高效实现多数据类型的操作,比普通函数更加简单。
例如下面的求最小值:

#include <stdio.h>
#define min(t1,t2)  (t1)-(t2) < 1e-7 ? (t1):(t2)
int main(){int a=34;float b=34.5;long long c=25;double d=30.9;printf("int and float: %g\n",min(a,b));printf("float and long long: %g\n",min(b,c));printf("int and double:%g\n",min(a,d));return 0;
}
/×
int and float: 34
float and long long: 25
int and double:30.9
×/

利用宏进行条件编译:

#include <stdio.h>
#define a 10
int main(){#if aprintf("a > 0\n");#endifreturn 0;
}

#error指示编译器产生错误,并显示相应的消息。

下列的程序,运行的结果linux是inf,windows是1.#INF

#include <stdio.h>
double div(int a,int b){return 1.0*a/b;
}
int main(){printf("%g\n",div(2,0));return 0;
}

我们利用预处理来改进一下:

#include <stdio.h>
double div(int a,int b){#if (b==0)#error "b can't be 0!"#endifreturn 1.0*a/b;
}
int main(){printf("%g\n",div(2,0));return 0;
}

out:

t.c: In function ‘div’:
t.c:4:7: error: #error "b can't be 0!"#error "b can't be 0!"^

#program 代表有特殊实现的代码,如Acmer常用的扩栈代码。

强大的跳跃者goto

合理的使用goto label可以使得程序跳出多重循环。

#include <stdio.h>int main(){int ans=0;for(int i=1;i<100;i++){for(int j=1;j<100;j++){for(int k=1;k<100;k++){if(i==4&&j==5&&k==6) {ans=i+j+k;goto out;}}}}out:printf("%d\n",ans);return 0;
}

指针和数组不是一样的

    FILE *fin, *fout;fin=fopen("tt","r");fout=fopen("t2","w");char *s;while(fscanf(fin,"%s",s)!=EOF){fprintf(fout,"%s ",s);}

上面这段程序并没有将字符串赋予s,下面的数组能够正常工作。字符指针不能直接被scanf输入字符串,但是可以等于赋值(char *str=”hello”;)

#include <stdio.h>int main(){FILE *fin, *fout;fin=fopen("tt","r");fout=fopen("t2","w");char s[20];int c=0;while(fscanf(fin,"%s",s)!=EOF){fprintf(fout,"%s ",s);}fclose(fin);fclose(fout);return 0;
}

字节计数器sizeof

对于sizeof(int)不能%d格式输出。
t.c:4:12: warning: format ‘%d’ expects argument of type ‘unsigned int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
正确的是输出%lu

#include <stdio.h>int main(){printf("char: %lu\n",sizeof(char));printf("int: %lu\n",sizeof(int));printf("long: %lu\n",sizeof(long));printf("long long: %lu\n",sizeof(long long));printf("float: %lu\n",sizeof(float));printf("double: %lu\n",sizeof(double));printf("8: %lu\n",sizeof(8));printf("8LL: %lu\n",sizeof(8LL));int a[10];printf("int[]: %lu\n",sizeof(a));printf("str: %lu\n",sizeof("abc"));return 0;
}/*
char: 1
int: 4
long: 8
long long: 8
float: 4
double: 8
8: 4
8LL: 8
int[]: 40
str: 4
*/

从以上结果来看,sizeof()计算的是按字节为单位的存储量。

计算参数的顺序

我们看一个有趣的例子,来说明有时参数的赋值和计算的顺序是不确定的。
源码文件的前半部分是这样的:

#include <stdio.h>
int max(int a,int b){return a>b?a:b;
}
void fun(int a,int b){
}

1)fun(++a,++a)

int main(){int a=1;fun(++a,++a);printf("%d\n",a);return 0;
}

gdb调试:

edemon@linux:~$ gdb exe
(gdb) break 5
Breakpoint 1 at 0x400534: file t.c, line 2.
(gdb) run
Breakpoint 1, fun (a=3, b=3) at t.c:6
6   }
(gdb) c
Continuing.
3
[Inferior 1 (process 3597) exited normally]

表格中的1,2,3,4代表计算或者传参的顺序,前者和后者是针对fun函数的第一个参数和第二个参数而言。

对象计算传参
前者1&23
后者1&23

2)fun(a++,++a)
当我小小的改变它后:

int main(){int a=1;fun(a++,++a);return 0;
}

gdb调试:

Breakpoint 1, fun (a=2, b=3) at t.c:6
6   }
(gdb) c
Continuing.
3
[Inferior 1 (process 3613) exited normally]
对象计算传参
前者12
后者34

3) fun(++a,a++):

int main(){int a=1;fun(++a,a++);return 0;
}

gdb调试:

Breakpoint 1, fun (a=3, b=1) at t.c:6
6   }
(gdb) c
Continuing.
3
[Inferior 1 (process 3632) exited normally]
对象计算传参
前者34
后者21

4) fun(a++,a++):

int main(){int a=1;fun(a++,a++);return 0;
}

gdb调试:

Breakpoint 1, fun (a=2, b=1) at t.c:6
6   }
(gdb) c
Continuing.
3
[Inferior 1 (process 3705) exited normally]
对象计算传参
前者43
后者21

这篇关于ANSI C (1) —— 基础的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853626

相关文章

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

Spring的基础事务注解@Transactional作用解读

《Spring的基础事务注解@Transactional作用解读》文章介绍了Spring框架中的事务管理,核心注解@Transactional用于声明事务,支持传播机制、隔离级别等配置,结合@Tran... 目录一、事务管理基础1.1 Spring事务的核心注解1.2 注解属性详解1.3 实现原理二、事务事

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

MySQL数据类型与表操作全指南( 从基础到高级实践)

《MySQL数据类型与表操作全指南(从基础到高级实践)》本文详解MySQL数据类型分类(数值、日期/时间、字符串)及表操作(创建、修改、维护),涵盖优化技巧如数据类型选择、备份、分区,强调规范设计与... 目录mysql数据类型详解数值类型日期时间类型字符串类型表操作全解析创建表修改表结构添加列修改列删除列

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.