常量字符指针和字符指针的传参问题
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:
查看库文件的源码:
cat /usr/include/stdio.h > read
vim read
: /EOF
定位后:
133 #ifndef EOF
134 # define
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
int main(){
#if
printf("a > 0\n");
#endif
return 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
#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 <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;
}
指针和数组不是一样的
*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
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函数的第一个参数和第二个参数而言。
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]
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]
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]