目录
1 Basic Features of C
1.1 Introducing C
1.2 C Fundamentals
1.3 Formatted Input/Output
Q3.1:
scanf(“%d,%d”,&i,&j)
;//如何输入。
A3.1: 10,20 //两个int中间必须有“,”。
Q3.2:
scanf(“ %c”,&ch)
;//%c前的空格什么用?
A3.2: skips white space (including newlines) and reads the next character。请看下面代码。
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main(int argc, char *argv[]){
char c;
scanf("%c",&c);
printf("%c\n",c);
scanf("%c",&c);
printf("%c\n",c);
}
//为什么上面代码第二个scanf不能正常工作,而若将``scanf("%c",&c);``里加空格“scanf(" %c",&c);”就可以。
Because input is put in a input buffer, what you input from keyboard is something like A\n, thus “A” is for the 1st &c and “\n” is for the 2nd &c. To avoid 2nd &c read “\n”, the whitespace is need in second scanf.
1.4 Expressions
1.5 Selection Statements
1.6 Loops
1.7 Basic Types
Q7.1: What does static mean in “static variable”?
A7.1: static means both variable storage duration(live as long as program live) and linkage(only has internal linkage(not accessible by external)) are static.
Q7.2: Should we maximize or minimize the use of external variable vs. passing as arguments?
A7.2: passing as arguments is preferred. Otherwise, global variable may be altered in different functions.
1.8 Arrays
T A[N]
has two effects. First, it allocates N*L bytes in memory, where L is the length of data type T; secondly, it creates an identifier A that can be used as the pointer to the beginning of the array.
1.9 Functions
Q9.1: 为什么需要函数声明。
A9.1: 1) main may call function A, function A may call function B. Thus be careful to ensure function definition order B->A->main; 2) function A and B may call each other; 3) separate function in different file, use declaration to public and formally tell the world what function you have in this file(.h).
1.10 Program Organization
Q10.1: 通常.c文件的程序结构是怎么样的?
A10.1: 见下面代码。
1
2
3
4
5
6
7
#include directives
#define directives
//Type definiton
//Declaration of external variables
//Prototypes for functions other than main
//Definition of main
//Definitions of other functions
Q10.2: 函数的comment该如何显示在code里?
A10.2: 见下面代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/************************************************************
* print: Prints a listing of all parts in the database, *
* showing the part number, part name, and quantity*
* on hand. Parts are printed in the order in which*
* they were entered into the database. *
*************************************************************/
void print(){
printf("Part Number, Part Name, Quantity on Hand\n");
for(int i = 0; i < num_parts; i++){
struct part p = inventory[i];
printf("%4d, %2s, %7d\n",p.number,p.name,p.quantity);
}
print_separator();
}
2 Advanced Features of C
2.1 Pointers
Q11.1: “&”和“*”的关系
A11.1: *和&是相反操作,printf("a: %d;\n",a)
和printf("a: %d;\n”,*&a)
一样。
Q11.2:
int *p, i; p = &i;
,请解释*p
和i
的关系。
A11.2:*p
是i
的别名。
Q11.3:
int *p
和*p = i
这两个表达式*
是否一样。
A11.3:两个*
意义不一样,前者(最好和int相连)表示p是1个int指针,后者*p
表示对p的一元运算符(dereference,解引用)。
Q11.4: p+j的地址如何决定,是否和p的类型有关。
A11.4:p+j的地址取决于p的类型,如果p是int *
,则p+j的地址是p+4*j(int是4byte);如果p是double *
,则p+j的地址是p+8j(double是8byte)。
Q11.5:
int a[] = {1,2,3}; int *p = a
,请解释a
和p
的区别和联系。
A11.5:a
和p
都是地址,但是p是指针变量,a是地址常数。
Q11.6: 在
int find_largest(int a[])
函数里,可以将二维指针a
作为输入参数吗?
A11.6: 不能。你只能输入a[1]
,虽然a[1]
和a
都是地址,但是它们的类型不同而c是强类型语言。
2.2 Pointers and Arrays
2.3 Strings
Q13.1: 如何显示长String?
A13.1: 其中一种方法是用连续""
,例如printf("Hello","World");
。
Q13.2:
printf('\n')
有问题吗?
A13.2: printf第一个参数是string,而'\n'
表示char,应该用"\n"
。
Q13.3: 如何打印string前6位。
A13.3:printf("%.6s\n",str)
。
Q13.4: 为什么C函数如果有1个参数是数组,通常会附加1个数组长度参数,而不是在函数里直接通过类似
n = sizeof(a)/sizeof(int)
操作获取长度?
A13.4: 因为在C函数里,数组参数会退化成指针,而对指针实行类似n = sizeof(a)/sizeof(int)
操作是获取不了数组长度,因为sizeof(a)
当a
是指针时返回的是指针长度而不是数组长度。参考下面代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void printString(char *str, int length){
for(int i = 0; i < length; i ++){
putchar(str[i]);
}
}
void printString(char *str){
int length = sizeof(str)/sizeof(char); //incorrect, sizeof(str) is the size of char *, not size of str pointing to.
for(int i = 0; i < length; i ++){
putchar(str[i]);
}
}
//but we can use str pointer to print with the help of ‘\n’ and no need of its length.
int countSpace2(char *str){
int count = 0;
for(; *str !='\n'; str++){
if(*str == ' '){
count++;
}
}
return count;
}
Q13.5:
<string.h>
包含了哪些常用字符串函数?
A13.5: strcpy, strncpy; strlen; strcat, strncat; strcmp; strchr。
Q13.6: 请实现
<string.h>
里的strlen?
A13.6: 见下面代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int my_strlen1(char *s){
int n = 0;
for(; *s!='\0'; s++){
n++;
}
return n;
}
int my_strlen2(char *s){
const char *p = s;
while(*s){ //*s is not null then move s to next,; if s is null, stop.
s++;
}
return s-p;
}
int my_strlen3(char *s){
const char *p = s;
while(*s++); //*s is not null then move s to next, continue; if s is null, also move s to next then stop.
return s-p-1;
}
Q13.7: What is “ragged array”?
A13.7: 见下图,string array用正适合的空间存储string而不是用同等column的2维数组。
2.4 The Preprocessor
2.5 Writing Large Programs
Q15.1: 解释.h在不同文件里被#inlucde的含义?
A15.1: 见下图。
Q15.2: 同一个file3.h在不同文件里file1.c和file2.c被include,同时file1.c和file2.c都被include到prog.c。在这种情况下file3.h相当于被prog.c include两次。如果file3.h 里面有宏定义,就会出现错误。这种错误如何避免?
A15.1: 使用Header Protection 宏定义技巧。见下图。
Q15.3: 如何编译多个.c成1个可执行文件?
A15.3: terminal里gcc main.c readline.c -o calculator。
2.6 Structures, Unions and Enumerations
Q16.1: struct作为函数参数是pass by value还是pass by reference?
A16.1: 都可以。
Q16.2: C语言数组不能赋值给数组,但是struc可以赋值给struct。所以如果1个struc的member有数组,则struct被赋值的同时,它里面的数组是否也被赋值。
A16.2: 是。见下面代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
typedef struct {
int a[4];
} ArrayStruct;
void printArray(ArrayStruct *,int);
int main(int argc, char *argv[]){
ArrayStruct a1 = 1,a2 = 11;
printf("a1: ");
printArray(&a1,4);
printf("a2: ");
printArray(&a2,4);
a2 = a1;
printf("a2: ");
printArray(&a2,4);
}
void printArray(ArrayStruct *aStruct,int n){
for(int i = 0; i < n; i++){
printf("%d ",aStruct->a[i]);
}
printf("array address: %p\n",aStruct->a);
}
/*输出:
a1: 1 2 3 4 array address: 0x7fff54a81a80
a2: 5 6 7 8 array address: 0x7fff54a81a70
a2: 1 2 3 4 array address: 0x7fff54a81a70
*/
Q16.3: accessing a structure by a structure pointer is so common that C devise a special operator for this purpose “->”。
1
2
struct node *new_node = malloc(sizeof(struct node))
(*new_node).value = 10;或 new_node->value = 10;
2.7 Advanced Uses of Pointers
Q17.1: How to declare the type of pointer when request a block of memory but at that time the type of data, planning to store in the block, is unknown?
A17.1: using a generic pointer type “void *”。
Q17.2: After allocate a block of memeory, before using the pointer, one always need to test whether the pointer is null or not
if(p == NULL){ allocation failed };
。
Q17.3: The malloc, calloc, realloc memory is in heap. Except those functions, memory is in stack.
2.8 Declarations
Q18.1: What is a register?
A18.1: A register is a storage area located in a computer’s CPU. Data stored in a register can be accessed and updated faster than data stored in ordinary memory。
Q18.2: What exactly the difference between “scope” and “linkage”?
A18.2: scope is for the benefit of the compiler, while linkage is for the benefit of the linker. The compiler uses the scope of an identifier to determine whether or not it’s legal to refer to the identifier at a given point in a file. When the compiler translates a source file into object code, it notes which names have external linkage, eventually storing these names in a table inside the object file. Thus , the linker the access to names with external linkage; names with internal linkage; names with internal linkage or no linkage are invisible to the linker。