C Language
Hello World
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}
With arguments
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("arg count: %i\n", argc);
for (int i=1; i<argc; i++) {
printf("argv: %s\n", argv[i]);
}
return 0;
}
编译与运行
gcc hello.c
./a.out
comments
// comment
/*
multiline comments
*/
Command-line arguments
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
for (i=1; i<argc; i++) {
printf("%s%s", argv[i], (i < argc-1) ? " ": "");
}
printf("\n");
return 0;
}
argc
: argument countargv
: argument vector
Includes
#include <xxx.h>
: search in standard places, ex: /usr/include#include "yyy.h"
: search in working dir
Variables
Data Types
Data Type | Size | Value Range | Format |
---|---|---|---|
boolean | 1 | ||
byte | 1 | ||
char | 1 | -128 ~ 127 | %d |
unsigned char | 1 | 0 ~ 255 | %u |
short | 2+(dependent on complier) | -32768 ~ 32767 | %d |
unsigned short | 2+ | 0 ~ 65535 | %u |
int | short to long(dependent on complier) | -2147483648 ~ 2147483647 | %d |
unsigned int | short to long | 0 ~ 2^32 | %u |
long | 4+(dependent on complier) | %ld | |
unsigned long | 4+ | %lu | |
float | 4 | 3.4e-38 to 3.4e+38 | %f |
double | 4 | 1.7e-308 to 1.7e+308 |
Type Cast
int x = 1;
// signed与unsigned互转,保持二进制表示不变,值可能改变
unsigned int ux = (unsigned int) x;
// 短类型转长类型
// 对于signed类型(Two's Complement编码)在左侧补最高位bit的值(sign extension)
// 对于unsigned类型,在左侧补0(zero extension)
long lx = (long) x;
// 长类型转短类型,截断高位,然后根据编码类型(signed or unsigned)解释数值
short sx = (short) lx;
Declaring and Instantiating Variables
// declarating
int year;
// instantiating
year = 2022;
// Declaring and instantiating simultaneously
int year = 2022
// Constant
const float pi = 3.14;
Symbolic Constants
#define LOWER 0
#define UPPER 300
#define STEP 20
Enum Constants
// starts at 0, next 1, etc...
enum boolean { NO, YES };
// values are specified
enum escapes { BELL = '\a', BACKSPACE = '\b', TAB = '\t',
NEWLINE = '\n', VTAB = '\v', RETURN = '\r' };
/* FEB = 2, MAR = 3, etc. */
enum months { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
Array
int ndigit[10];
for (i = 0; i < 10; ++i) {
ndigit[i] = 0;
}
// assigns values to first 5 data
int myarray[10] = {20, 30, 40, 50, 100};
int myarray[] = {20, 30, 40, 50, 100};
// size
size = sizeof(myArray) / sizeof(int)
2-D Array
// definition
char daytab[2][13] = {
{0, 31, 28, ..., 31},
{0, 31, 29, ..., 31}
};
// get value
daytab[i][j];
// passed to function
f(int daytab[2][13]) { ... }
f(int daytab[][13]) { ... } /* the number of row is irrelevant */
f(int (*daytab)[13]) { ... } /* a pointer to an array of 13 integers */
sizeof
size_t
:unsigned interger, defined in<stddef.h>
#define NKEYS (sizeof keytab / sizeof(struct key))
#define NKEYS (sizeof keytab / sizeof(keytab[0]))
Character string
every character string has a ’\0’ at the end
char line[10];
char c;
c = 'a';
for (int i = 0; i < 10; ++i){
line[i] = c;
++c;
}
printf("%s\n", line);
// equivalent
char pattern[] = "ould";
char pattern[] = { 'o', 'u', 'l', 'd', '\0' };
Strings
String name = "my text here";
name.charAt(0);
name.length();
Operator
Operators
Operator | Description |
---|---|
+ | Addition |
- | Substraction |
* | Multiplication |
/ | Division |
% | Modulus |
++ | Increment |
– | Decrement |
! | Logical NOT |
&& | Logical AND |
|| | Logical OR |
& | Bitwise AND |
| | Bitwise OR |
^ | Bitwise EXCLUSIVE OR |
~ | Bitwise NOT |
« | Left shift |
» | Right shift |
Conditional Expressions
z = (a > b) ? a : b; /* z = max(a, b) */
Control Flow
If-else
if (a > b) {
z = a;
} else if {
z = b;
} else {
z = c;
}
if ((a==1) && (b==1)){
}
if ((a==1) || (b==1)){
}
if (!(a==1)){
}
Switch
switch (c) {
case 'a':
break;
case 'b':
break;
case 'c':
break;
default:
break;
}
For
for (int i=0; i<n; i++) {
print(i);
}
for (int i=0; i<n; i++) {
if (i>10) {
break;
}
}
for (int i=0; i<n; i++) {
if (i<10) {
continue;
}
}
While
while (a < b) {
a++;
}
Pointers
int x = 1, y = 2, z[10];
int *ip; /* ip is a pointer to int */
ip = &x; /* ip now points to x */
y = *ip; /* y is now 1 */
*ip = 0; /* x is now 0 */
ip = &z[0]; /* ip now points to z[0] */
/* pointer to void, can hold any type of pointer */
void *v;
v = &x;
/* cannot be dereferenced before cast */
printf("%d\n", *((int*) v));
Pointers and arrays
- 一个array其实是一个指向首元素的pointer
arr[i]
与*(pa+i)
是一样的- array name不是变量,无法被赋值,但是指针可以
- 函数参数中传array name会在函数创建一个指向它的指针的局部变量
Pointers of pointers
char *lineptr[]; /* pointers to lines */
Pointers to functions
// comp is a pointer to a function that has two `void *` arguments
// and returns an `int`
int (*comp)(void *, void *)
Functions
int power(int m, int n); // declaration, called 'function prototype'
int main() {
int i;
for (i = 0; i < 10; ++i) {
printf("%d %d %d\n", i, power(2, i), power(-3, i));
}
}
int power(int base, int n) {
int i, p;
p = 1;
for (i = 1; i <= n; ++i) {
p = p * base;
}
return p;
}
or
// definition before caller
int power(int base, int n) {
int i, p;
p = 1;
for (i = 1; i <= n; ++i) {
p = p * base;
}
return p;
}
int main() {
int i;
for (i = 0; i < 10; ++i) {
printf("%d %d %d\n", i, power(2, i), power(-3, i));
}
}
- all function arguments are passed ‘by value’.
Argument list
...
means that the number and types of these arguments may vary
int printf(char *fmt, ...)
use <stdarg.h>
to step through an argument list
#include <stdarg.h>
/* minprintf: minimal printf with variable argument list */
void minprintf(char *fmt, ...) {
va_list ap; /* points to each unnamed arg in turn */
char *p, *sval;
int ival;
double dval;
va_start(ap, fmt); /* make ap point to 1st unnamed arg */
for (p = fmt; *p; p++) {
if (*p != '%') {
putchar(*p);
continue;
}
switch (*++p) {
case 'd':
ival = va_arg(ap, int);
printf("%d", ival);
break;
case 'f':
dval = va_arg(ap, double);
printf("%f", dval);
break;
case 's':
for (sval = va_arg(ap, char *); *sval; sval++) {
putchar(*sval);
}
break;
default:
putchar(*p);
break;
}
}
va_end(ap); /* clean up when done */
}
Structures
// struct declaration
struct point {
int x;
int y;
};
// declare struct variable
struct point pt;
struct maxpt = { 320, 200 };
// refer struct members
printf("%d, %d", pt.x, pt.y);
// nested struct
struct rect {
struct point pt1;
struct point pt2;
};
struct rect screen;
printf("%d, %d", screen.pt1.x, screen.pt1.y);
// pointer to struct
struct point *pp;
pp = &pt;
printf("%d, %d", (*pp).x, (*pp).y);
printf("%d, %d", pp->x, pp->y);
Typedef
typedef int Length;
Union
union u_tag {
int ival;
float fval;
char *sval;
} u;
- a union is a structure in which all members have offset zero from the base, the structure is big enough to hold the “widest’’ member
- It is the programmer’s responsibility to keep track of which type is currently stored in a union
- A union may only be initialized with a value of the type of its first member;
Header files
- Declaration: 声明变量或函数的类型
int sp;
double val[MAXVAL]
- Definition:同时分配空间
extern int sp;
extern double val[]
- extern variable只能被define一次,其他文件使用时需要declare才能用
- static variable限定只有源文件能用
- 通常将要共享的外部变量的declaratin放到一个header file中,在别的source file中include
- 当included file变更时,所有include它的文件都要重新编译
calc.h
#define NUMBER '0'
void push(double);
double pop(void);
main.c
#include <stdio.h>
#include "calc.h"
int main() {
...
}
stack.c
#include <stdio.h>
#include "calc.h"
int sp = 0;
double val[MAXVAL];
void push(double) {
...
}
double pop(void) {
...
}
Macro
Conditional Inclusion
#if SYSTEM == SYSV
#define HDR "sysv.h"
#elif SYSTEM == BSD
#define HDR "bsd.h"
#elif SYSTEM == MSDOS
#define HDR "msdos.h"
#else
#define HDR "default.h"
#endif
#include HDR
#ifndef HDR
#define HDR
/* contents of hdr.h go here */
#endif
Input and Output
Standard IO
get/put character
获取下个字符:getchar
/getc
/fgetc
写入一个字符:putchar
/putc
/fputc
getchar
int getchar(void)
// routine
int c; // int, not char, for holding EOF(-1) reason
while((c=getchar()) != EOF) {
}
getline
// routine
#include <stdio.h>
#include <stdlib.h>
// or allocate memory via `malloc`
// size_t buf_size = 32;
// char *buffer = (char *) malloc(buf_size * sizeof(char));
size_t buf_size = 0;
char *buffer = NULL;
size_t read_size;
buffer = (char *) malloc(buf_size * sizeof(char));
if( buffer == NULL)
{
perror("Unable to allocate buffer");
exit(1);
}
while ((read_size = getline(&buffer, &buf_size, stdin)) > 0) {
}
printf
int printf(char *format, arg1, arg2, ...);
char* s = "hello world"
printf("%s", s);
scanf
int scanf(char *format, ...)
- the arguments to
scanf
andsscanf
must be pointers
// reads `25 Dec 1988` into day, monthname, and year
int day, year;
char monthname[20];
scanf("%d %s %d", &day, monthname, &year);
sscanf
int sscanf(char *string, char *format, arg1, arg2, ...)
while (getline(line, sizeof(line)) > 0) {
if (sscanf(line, "%d %s %d", &day, monthname, &year) == 3) {
printf("valid: %s\n", line); /* 25 Dec 1988 form */
} else if (sscanf(line, "%d/%d/%d", &month, &day, &year) == 3) {
printf("valid: %s\n", line); /* mm/dd/yy form */
} else {
printf("invalid: %s\n", line); /* invalid form */
}
}
File
#include <stdio.h>
// fp is a pointer to a `FILE`
FILE *fp;
// `fopen` returns a pointer to a `FILE`
FILE *fopen(char *name, char *mode);
// freeing the file pointer
int fclose(FILE *fp);
fp = fopen(name, mode);
fclose(fp);
// returns the next char from the stream referred to by `fp`
int getc(FILE *fp);
// writes char `c` to the file `fp` and returns the char written
int putc(int c, FILE *fp);
// scanf from file instead of stdin
int fscanf(FILE *fp, char *format, ...);
// printf to file instead of stdout
int fprintf(FILE *fp, char *format, ...);
// reads the next input line from file `fp` into `line`
char *fgets(char *line, int maxline, FILE *fp);
// writes a string to a file
int fputs(char *line, FILE *fp);
patterns
char* name = "main.c";
FILE *fp = fopen(name, "r");
if (fp == NULL) {
printf("cannot open file%s\n", name);
exit(1);
}
fclose(fp);
Standard Libs
- <stdio.h>:标准输入输出
- <ctype.h>:Character Class Tests - isalnum(c),isalpha(c), etc…
- <math.h>:数学运算
- <unistd.h>:Unix标准库
- <time.h>:时间相关
- <limits.h>:整数类型常量
- <float.h>:浮点类型常量
string
<string.h>
strcat(s, t)
: concatenatet
to end ofs
strcmp(s, t)
: compare to strings, return negative ifs<t
strcpy(s, t)
: copyt
tos
strlen(s)
: return length ofs
strchr(s, c)
: return pointer to firstc
ins
, orNULL
if not presentstrrchr(s, c)
: return pointer to lastc
ins
, orNULL
if not present
ctype
<ctype.h>
isalpha(c)
isupper(c)
islower(c)
isdigit(c)
isalnum(c)
isspace(c)
toupper(c)
tolower(c)
stdlib
<stdlib.h>
system(char* s)
: executes the commands
void *malloc(size_t n)
: obtain blocks of memory dynamically, returns a pointer to n bytesfree(p)
: frees the space pointed to byp
math
<math.h>
sin(x)
cos(x)
exp(x)
log(x)
pow(x, y)
: x^ysqrt(x)
fabs(x)
: absolute value of x
Complie
gcc -Wall main.c # -Wall: enable all warnings
gcc -E main.c # -E: preprocess
gcc -c helper.c # -c: to produce object files
gcc -g main.c # -g: to enable debugging with gdb
gcc -O main.c # -O: to turn on optimization
gcc -lm main.c # The -lXXX flag tells the linker to look for libXXX.so or libXXX.a
gcc -I/foo/bar main.c # look for headers in the directory `/foo/bar`
gcc -L/foo/bar main.c # look for libraries in the directory `/foo/bar`
gcc -std=c89 main.c # ISO C90标准,默认选项
gcc -std=c99 main.c # ISO C99标准
gcc -std=c11 main.c # ISO C11标准
查看动态链接库
ldd a.out