ANSI C (1) —— 基础

网友投稿 628 2022-09-06

ANSI C (1) —— 基础

ANSI  C (1) —— 基础

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

1) 没有错误:

#include 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 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 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 void print(){ printf("hello\n");}int a=10;

t.c:

#include /* "dir"表示用户目录,

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

out:

hello10

查看库文件的源码:

cat /usr/include/stdio.h > readvim read: /EOF

定位后:

133 #ifndef EOF134 # define135 #endif

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

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

#include #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: 34float and long long: 25int and double:30.9

利用宏进行条件编译:

#include #defineint main(){ #if printf("a > 0\n"); #endif return 0;}

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

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

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

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

#include double div(int a,int b){ #if #error #endif return 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 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;}

指针和数组不是一样的

*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 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 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: 1int: 4long: 8long long: 8float: 4double: 88: 48LL: 8int[]: 40str: 4*/

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

计算参数的顺序

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

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

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 5Breakpoint 1 at 0x400534: file t.c, line 2.(gdb) runBreakpoint 1, fun (a=3, b=3) at t.c:66 }(gdb) cContinuing.3[Inferior 1 (process 3597) exited normally]

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

对象

计算

传参

前者

1&2

3

后者

1&2

3

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:66 }(gdb) cContinuing.3[Inferior 1 (process 3613) exited normally]

对象

计算

传参

前者

1

2

后者

3

4

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:66 }(gdb) cContinuing.3[Inferior 1 (process 3632) exited normally]

对象

计算

传参

前者

3

4

后者

2

1

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:66 }(gdb) cContinuing.3[Inferior 1 (process 3705) exited normally]

对象

计算

传参

前者

4

3

后者

2

1

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:waf 编译入门小练习
下一篇:shell编程 (1) —— 基础
相关文章

 发表评论

暂时没有评论,来抢沙发吧~