HelloWorld
vi HelloWorld.c
#include <stdio.h>
int main(int argc,char* argv[]){
printf("HelloWorld!\n");
return 0;
}
clang -g -o helloworld HelloWorld.c
ls -alt helloworld
./helloworld
常用基本類型
- short、 int、 long
- float、double
- char
- void
#include <stdio.h>
int main(int argc,char* argv[]){
int a = 100;
float b = 1.23;
char c = 'C';
printf("Hello World!\n");
printf("a = %d\n",a);
printf("b = %f\n",b);
printf("c = %c\n",c);
return 0;
}
clang -g -o helloworld1 HelloWorld.c
./helloworld1
打印:
Hello World!
a = 100
b = 1.230000
c = C
常量與變量
- int a = 0; //變量,可以再賦值
- const int len = 256; //常量定義
內存管理:
指針與數組
- 指針就是內存地址:void* 、 char*
- 數組 如:char c[2] 、 int arr[10]
指針:
- 它就是內存中的一個地址
- 指針本身運算
- 指針所指內容的操作
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char* argv[])
{
int *a,*b;
a = (int*)malloc(sizeof(int)); //在棧中開闢內存
b = (int*)malloc(sizeof(int));
*a = 1;
*b = 2;
int c[3] = {0,1,2};
printf("addr of a:%p,%p,%d\n",&a,a,*a);
printf("addr of b:%p,%p,%d\n",&b,b,*b);
printf("addr of c:%p,%p,%d,%d,%d\n",&c,c,c[0],c[1],c[2]);
return 0;
}
gcc -g -o testpoint testpoint.c
./testpoint
打印結果:
addr of a:0x7ffee1cb1830,0x7fa99b402b60,1
addr of b:0x7ffee1cb1828,0x7fa99b402b70,2
addr of c:0x7ffee1cb184c,0x7ffee1cb184c,0,1,2
操作系統時如何管理內存的?
- 棧空間
- 堆空間
- 內存映射
內存的分配與釋放
- 分配內存
void* mem = malloc(size);
- 釋放內存
free(mem);
內存泄漏與野指針
- 不斷向系統申請內存
- 申請的內存不用,也不釋放
- 佔用別人的內存稱爲野指針
函數指針
- 返回值類型(*指針變量名)([形參列表]);
int func(int x);//聲明一個函數
int(*f)(int x);//聲明一個函數指針
f = func;//將func函數的首地址賦給指針f
函數指針示例:
vi testfunc.c
#include<stdio.h>
int sum(int a,int b)
{
return (a + b);
}
int sub(int a,int b)
{
return (a- b);
}
int main(int argc,char* argv[])
{
int(*f)(int,int);
f = sum;
int result = f(3,5);
f = sub;
int result2 =f(result,3);
printf("3+5 = %d\n",result);
printf("8-3 = %d\n",result2);
return 0;
}
clang -g -o testfunc testfunc.c
./testfunc
打印:
3+5 = 8
8-3 = 5
結構體
vi testst.c
#include<stdio.h>
struct st{
int a;
int b;
};
int main(int argc,char* argv[])
{
struct st sst;
sst.a = 10;
sst.b = 20;
printf("struct content is :%d,%d\n",sst.a,sst.b);
return 0;
}
clang -g -o testst testst.c
./testst
打印結果:
struct content is :10,20
枚舉
vi testenum.c
#include<stdio.h>
enum e_type{
red = 0,
green,
blue
};
int main(int argc,char* argv[]){
enum e_type et;
et = red;
printf("the color is: %d\n",et);
et = blue;
printf("the color is: %d\n",et);
return 0;
}
clang -g -o testenum testenum.c
./testenum
打印結果:
the color is: 0
the color is: 2
文件操作
- 文件類型
FILE* file;
- 打開文件
FILE* fopen(path,mode);
- 關閉文件
fclose(FILE*)
#include<stdio.h>
int main(int argc,char* argv[])
{
FILE* file;
char buf[1024] = {0,};
file = fopen("1.txt","a+");//在末尾添加,遊標指向末尾
fwrite("hello world!",1,13,file);
rewind(file);//遊標指向最前
fread(buf,1,13,file);
fclose(file);
printf("buf : %s\n",buf);
return 0;
}
clang -g -o testfile testfile.c
./testfile
buf : hello world!
C語言編譯器
gcc/clang -g -O2 -o test test.c -I... -L... -l
- -g: 輸出文件中的調試信息
- -O:對輸出文件做指令優化
- -o: 輸出文件
- -I: 指定頭文件
- -L:指定庫文件位置
- -l :指定使用哪個庫
編譯過程
- 預編譯
- 編譯
- 鏈接,動態鏈接/靜態鏈接
vi add.h
int add(int a,int b);
vi add.c
int add(int a,int b){
return (a + b);
}
vi add.c
#include<stdio.h>
#include "add.h"
int main(int argc,char* argv[])
{
printf("add = %d\n",add(2,3));
return 0;
}
clang -g -c add.c
libtool -static -o libmylib.a add.o
clang -g -o testlib testlib.c -I. -L. -lmylib
./testlib
打印結果:
add = 5
或者:
clang -g -c testlib.c
clang -o testlib1 testlib.o -L . -lmylib
./testlib1
打印結果:
add = 5
C語言調試器
調試器原理
- 編譯輸出帶調試信息的程序
- 調試信息包含:指令地址、對應源代碼和行號
- 指令完成後,回調
gdb和lldb
命令 | gdb | lldb |
---|---|---|
設置斷點 | b | b |
運行程序 | r | r |
單步執行 | n | n |
跳入函數 | s | s |
跳出函數 | finish | finish |
打印內容 | p | p |
lldb testlib
b main
break list
r
s
p a
p b
finish
n
c #continue執行完之後的
quit # 退出
cd testlib.dSYM/Contents/Resources/DWARF
dwarfdump testlib